跟工程师学嵌入式开发 ——基于STM32和μC/OS-III(txt+pdf+epub+mobi电子书下载)


发布时间:2020-07-13 02:28:34

点击下载

作者:谭贵,易确,等

出版社:电子工业出版社

格式: AZW3, DOCX, EPUB, MOBI, PDF, TXT

跟工程师学嵌入式开发 ——基于STM32和μC/OS-III

跟工程师学嵌入式开发 ——基于STM32和μC/OS-III试读:

前言

进入21世纪以来,随着微电子技术、计算机技术及网络通信等技术的深入发展,整个社会信息化的程度越来越高,不用说智能手机,各种信息设备,如应用于医疗健康领域的智能心电仪、智能血糖仪,工业生产领域的自动测试装置、机器人手臂,安防领域的指纹识别、人脸识别技术,智能家居里的智能空调、冰箱、电表,甚至军事领域中的精确制导武器、红外热成像眼镜、自动跟踪……都无一例外地具有“智慧”的大脑,它们的应用已深入我们生活的每个角落,改变着我们的生活方式。

在上面所提及的应用中,其“智慧”的大脑,实质就是一套套嵌入式系统,它们由不同的硬件和软件组成。这里所说的“不同”,一是指构成嵌入式系统的硬件核心,可能是由基于不同厂商的SoC芯片所拓展设计的实用电路,如ST公司的STM8、STM32系列SoC、NXP公司的LPC系列SoC;二是指嵌入式系统的软件构成,除去SoC片上外设的必要驱动外,还有管理这些驱动和应用的操作系统,如Embedded Linux、μC/OS-III和文件管理系统(如FatFs)等。

目前,嵌入式应用处理器多采用ARM体系结构。ARM公司为了细分市场,将其芯片按应用领域分为 Cortex-A、Cortex-R、Cortex-M 三个系列。Cortex-A 系列芯片带有 MMU (内存管理单元)、MPU(内存保护单元)部件,主要针对复杂的嵌入式应用,如智能手机、平板电脑及高档成像设备等;Cortex-R 系列面向实时应用领域,如精密机器控制、炉温监控;Cortex-M系列则面向传统的单片机市场,其子系列M0~M4涵盖了从8位到32位单片机的所有应用,与传统的C51系列单片机相比,功能更强大。因此,学习嵌入式开发技术,应本着“循序渐近,由简单到复杂”的原则,首先学习基于Cortex-M系列的单片机是最好的入门选择,在此基础上,进阶学习Cortex-A系列就显得“自然而游刃有余”。

本书就以基于 CM3 内核架构(Cortex-M3)的芯片 STM32F103ZET6(意法半导体公司ST,基于MCU应用的32位芯片系列,简称STM32)为讲解线索,合理选择实际应用中广泛使用的USART、I2C、SPI、SDIO、以太网等接口,结合ST公司提供的库函数,通过一个个具有实际使用价值的案例代码,详细介绍每种接口的工作原理、驱动配置和综合应用。在学习本书之前,如果读者对CM3体系结构有一定的了解,当然最好;如果没有此类的背景知识,也不用担心会影响对本书的学习。笔者在讲解过程中,会在涉及需要CM3体系结构知识的地方,自然而然地引入相应知识点的介绍。

本书对章节、知识点的安排有以下三个显著特点,以便读者快速、高效地掌握基于“STM32+μC/OS-III结构”的嵌入式开发。

在章节的安排上,遵循“先总体,后细节”的原则。第1章以一个跑马灯实验作为引子,为读者介绍了嵌入式开发所涉及的基本概念和流程,如 GPIO 配置、事件的轮询和中断处理机制等,以及基于STM32库开发所涉及的库文件组织和CMSIS标准、开发工具。建立了嵌入式开发的基本过程等轮廓性认识之后,第2章自然地切入STM32系列芯片的框架结构,包括总线、外设地址空间映射和时钟树。只有清楚了这三者之间的关系,才有可能对后面章节所讲解的外设工作过程和相关操作有深刻的理解。在此基础上,第3章开启了嵌入式系统的启动之旅,透彻地分析了基于CM3核的芯片系统之启动过程。有了前面三章的基础,随后的章节则以“先简单,后复杂”的原则逐一介绍GPIO、外部中断线、USART、DMA、I2C、SDIO等外设的结构原理及相应的驱动代码。

其次,对每一种外设的讲解,除了遵循“先总体,后细节”的原则之外,采用“以实验现象为驱动(每章的第一节首先呈现给读者一个最终的实验结果画面)”的思路,一步步进入外设的内部世界。这样的安排有利于激起读者对未知世界的强烈兴趣,随着对外设“先总后细”的逐层深入,最终使读者彻底理解并掌握每种外设“实验现象”背后的逻辑。

最后,本书除了讲解每种外设的工作原理和驱动代码之外,还穿插了三个有实用价值的综合案例,以拓展读者对外设应用的认识和理解,以及必要的知识面。第一个综合实例是基于USART接口的Shell(俗称“外壳”,类似于Linux的bash)程序,通过它可以将“对外设的操作”封装为一个个Shell 命令,以随时执行。因此,Shell 程序贯穿本书的始末。第二个综合实例是Telnet远程登录服务程序,该程序底层硬件是基于SPI总线的以太网芯片ENC2860,上层使用uIP协议栈来完成常用的TCP/IP功能,如ping、ICMP、IP、TCP等。“麻雀虽小,五脏俱全”,通过实现这样的服务程序,不但可以使读者理解和掌握Telnet协议的工作原理及过程,而且有利于进一步学习理解TCP/IP协议栈代码实现。最后一个综合示例实现了使用μC/OS-III操作系统来管理前面所讲解的硬件,充分利用操作系统的任务通信、消息传递等机制来提升硬件系统的运行效能。μC/OS-III系统结构紧凑,代码量小,容易理解掌握,通过移植和应用μC/OS-III,使读者在掌握系统应用场景的同时,加深理解操作系统内部的工作机理,为后续进一步学习基于Linux的嵌入式开发打下基础。

由于社会信息化日趋明显,必定导致包括STM32在内的MCU的应用越来越多。希望本书能为渴望进入嵌入式开发领域的人员提供一个好的入门指引,为后续深入嵌入式开发的高级应用奠定基础。作为学习教材,本书每一章的实验代码都由笔者在Keil MDK开发环境中调试通过,读者可以放心学习使用。同时,由于笔者水平有限,书中难免会存在对相关知识点理解不够准确之处,敬请读者批评指正。

参与编写本书的人员还有我的同事易确,他负责本书所有的实验电路设计;熊立宇,负责完成最后三章的初稿编写及全书的校验工作。十分感谢他们的辛勤付出!

在本书的编写过程中,得到了电子工业出版社的田宏峰老师的悉心支持,在此表示衷心感谢,同时感谢他为我提供了一个这样施展自己特长机会;十分感谢我的同事彭丽兰,是她在我工作忙碌的时候,分担了我的工作,使我能够安心写作;最后想表达对我的家人,特别是朋友熊姬珠的谢意,是她们给予我精神上的鼓励,才使我得以完成这“马拉松”式的写作。

谭贵

2017年8月于深圳第1章 开发利器:STM32库和MDK KeiI“工欲善其事,必先利其器”,对于干技术活的工程人员来说,对这句话有比一般人更深刻的理解。尤其是软件开发领域,可供使用的工具众多,选择一个好的开发平台,不但可以有效地管理工程文件、配置工程参数,而且可更快捷有效地发现并解决程序设计中出现的问题。

本章以一个简单有趣的外设实验为线索,为您讲解本书将要使用的“利器”—MDK Keil开发环境的使用方法,包括工程建立、源文件管理、编译配置等。同时通过这个实验,为读者首先建立一个开发流程的初步印像,为后续学习打下基础,并一步步地进入趣味无穷的嵌入式世界。1.1 学习启航:闪烁的跑马灯

对于任何刚开始接触嵌入式技术的人来说,对学习对象的直观感受是十分重要的。所谓“第一印象决定了以后的交往”,在技术领域也有这种效应。换句话说,首先得要让他对所学的东西有初步的兴趣。本节内容的目的就是如此,通过对一个四向(上下左右)摇杠不同方向的按钮来控制4颗LED灯闪烁频率和方向。1.1.1 实验结果呈现

实验操作:

● 步骤A:当将摇杠向上推时,4颗LED灯以顺时针方向间隔1 s依次闪烁。

● 步骤B:将摇杠向下推,4颗LED以逆时针方向间隔1 s闪烁。

● 步骤C:将摇杠向左推,加快LED的闪烁频率。

● 步骤D:将摇杠向右推,降低LED的闪烁频率。1.1.2 实验分析

根据以上实验现象,电路输入有4个信号:即摇杠的4个方向(对应于如图1-1所示的JOY_DOWN、JOY_UP、OY_LEFT、JOY_RIGHT),输出反映在4颗LED灯(原理图中的 LED1、LED2、LED3、LED4)的闪烁频率和轮转方向上。在这里我们不讨论该电路的设计,而是利用设计好的电路图,如何找出8个I/O信号所用到GPIO引脚,然后依据它们在数据手册上的定义,对相关的寄存器做出配置即可。图1-1 灯控实验的电路图

在编写代码之前,首先查看电路图明确以下几点。(1)确定硬件的连接关系。摇杠的“上右下左”4个方向作为MCU的输入信号分别连接到 PG15、PG13、PG11、PG14 引脚;而 4 个 LED 灯分别与 PF6、PF7、PF8、PF9相连。

说明:对于STM32F10x系列芯片,除了电源(VDD)、地(VSS)、时钟(OSC)三类引脚之外,其余的外部引脚被分组管理,将它们命名为GPIOx(x=A、B、C、D、E、F、G),其中每组下有0~15共16根引脚(P0~P15),如GPIOA.P1。(2)查MCU(STM31F103ZET6)的数据手册(Datasheet),总结上述8个GPIO引脚的功能定义,如表1-1所示。表1-1 灯控实验所用GPIO引脚功能定义

为了减小芯片面积(与功耗、价格密切相关),芯片设计时在保持功能不受影响的前提下都尽可能地减少引脚数量。这样每根引脚不可避免地具有复用(多重)功能,默认情况下都作为普通I/O引脚使用(表1-1中的Main function),但可以通过配置来启用它们的其他功能(关于如何配置,从第4章的外设实验开始会详细详解)。

本实验所用到的8根引脚中,除PG15外,其余的都有复用功能。但本实验是单点控制(即每根引脚对应外接一个外部元件)实验,不涉及复杂的协议(如I2C、SPI、USART等),因此使用表1-1所列GPIO引脚的默认功能:输入和输出。(3)配置引脚。虽然是单点控制,但每个引脚也有“入”和“出”之分,得根据实验要求对这些引脚进行必要的配置,在这之后才可能按软件的逻辑去控制“信号从哪根引脚进入,又从哪根引脚出”。

问题的逻辑是这样的:CPU怎么知道有输入信号从摇扛那边过来呢?如果不知道,它就不可能去指挥4颗LED灯按实验的要求闪烁。

办法其实有两种:打个比方,假如你有一个远方的朋友几天前告诉你,他明天会来你家,但具体时间可能多种原因(晚点、汽车抛锚维修等)无法确定,要你等他的电话。

CPU等待有按键输入信号,就如同你等这个电话何时到来一样。你可以将电话放在客厅后就去厨房洗菜,中途由于担心错过电话,可能你会不停地往返于厨房和客厅之间,直到你接到朋友的电话为止。或者你换一种等电话的方式,你还是把电话放在客厅,交代你的女儿:要是有人打电话进来,你告诉我。于是你就可以安心地去洗菜、拖地……当女儿告诉你:爸爸,你有电话时,你便可以放下手中的工作,去接听电话,然后驱车去车站接你的朋友。这两种等电话的方式分别对应计算机处理事件的两种方式—轮询和中断。很明显,采用中断的等待方式更有效。

回到前面的问题“CPU怎么知道有输入信号从摇扛那边过来呢?”答案很简单:采用中断的机制。

所有基于CM3核的处理器芯片,其核内都有一个称为向量中断控制器(NVIC)的部件,负责处理240个外部中断输入和11个内部异常源。具体到STM32F10x系列芯片,有两种中断信号:一种是寄存器位中断(它没有单独的连线与外部 GPIO 引脚相连,而是通过寄存器的中断控制位来传递中断的);另一种就是与GPIO 引脚有物理连接的EXTI(外部中断/事件控制器)。

STM32F103ZET6提供了19个EXTI,每个EXTI都由相应的边沿检测器组成并连接到芯片上的引脚上,如图1-2所示。图1-2 EXTI与GPIIO引脚对应关系

由图1-2可知,GPIOx的第0号引脚共享EXTI0外部中断/事件线,GPIOx第1号引脚共享EXTI1中断/事件线……GPIOx第15号引脚共享EXTI15中断/事件线。

外部摇杠的4个方向通过PG11、PG13、PG14、PG15分别连接到CPU的EXTI11、EXT13、EXTI14、EXTI15。当摇杠向上推时,电压信号通过 PG15 传入芯片内部的 EXTI15 中断/事件线,EXTI控制器收到该信号并产生中断,并最终传递到NVIC,由NVIC统一处理并通知CPU:“你有外部EXTI15号事件发生”,CPU这时就会停止当前的工作,转而去查询系统异常向量表,找到对应的中断/事件服务程序EXTI15_10_IRQHandler的入口地址,并跳转到该地址处进行处理,整个流程如图1-3所示。图1-3 外部中断/事件EXTIx的产生及传递过程

以上是一个外部中断事件从产生、传递到处理整个流程的粗略描述。实际上,中断事件信号的传递过程是比较复杂的,但鉴于“由浅入深”的原则,在这里只要求读者有一个整体认识就可以了,这有利于降低学习的难度,并保持学习的兴趣。1.1.3 配置GPIO引脚

要想使以上中断/事件的传递过程顺利进行,需要对所涉及的4个部件进行初始化配置。由于还没有正式学习STM32外设及GPIO的配置,在这里抽取真实代码的关键部分来说明这4个部件配置的大致过程,将问题简单化,先使读者对STM32的外设配置有一个基本的映像,为后续章节的学习打下基础。

1.四向开关按键GPIOG引脚初始化配置

由于按键信号是向MCU内部传输的,所以GPIO模式设置为GPIO_MODE_IPU(上拉输入),并且按键是接在GPIOG引脚分组上,所以将上面的配置写入GPIOG寄存器。

2.4颗LED灯GPIOG引脚初始化配置

由于点亮LED的信号是从MCU内向外传输的,所以LED所接引脚的GPIO模式设置为GPIO_MODE_OUT(输出),并且接在GPIOF引脚分组上,所以将上面的配置写入GPIOF寄存器。

3.EXTI11控制线初始化配置

EXTI控制器主要完成将器件(摇杆按键)所接GPIO引脚与内部的EXTI线关联的工作,并且定义好触发EXTI中断的信号方式(上升沿或下降沿),最后同样需要将这些配置写入相应的寄存器。

4.NVIC控制器初始化配置

在CM3体系结构中,所有外设的中断和内部的异常都由NVIC统一来管理。上面的代码完成将EXTI从EXTI10~EXTI15的中断线向NVIC注册(通道号EXTI15_10_IRQn),这样当EXIT中断发生时,NVIC才会调用相应的中断服务程序进行处理。

按以上步骤对所涉及的4个部件配置后过后,相当于打通了从按键到中断控制器之间的路径,如果此时有按键的中断信号传递到NVIC控制器,以下中断服务函数就会被执行,该中断函数由用户根据应用功能编写。

5.中断服务程序EXTI15_10_IRQHandler ()1.1.4 实验控制逻辑

我们从实验现象(选择5向开关不同的方向,获得LED灯不同的闪烁方式)出发,一步步深入梳理,最后进入CPU内部(EXTIx、NVIC、各寄存器),通过这个过程我们明白了实验现象内部的运作原理。在完成相关外设的配置以后,就可以看到本章开始的实验现象了吗?当然不是,完成配置只能说明信号传输的通路已没有了障碍。真正核心的是信号以什么的方式“流畅”起来,这里“以什么样的方式”就是控制逻辑。也就是说,这些部件到现在为止,在整个系统中都还只是孤立的,它们之间还需要一个统一的“线”贯穿起来,这条线就是主控制逻辑。

从前面的分析也可以得到这么一个结论:一个完整的嵌入式系统应该具有以下几个逻辑模块:主控制逻辑,外设驱动(对GPIO、EXTI的配置等),中断服务处理程序。再复杂的应用也不过是在此基础上进行了适当的添加。这几个模块反映在源代码文件上,就分别是main.c、keyLed.c、stm32f10x_it.c,这三个(模块)文件之间的关系如下。

主程序文件main.c:是整个系统的“统帅”,由它负责将各个“孤立”模块串在一起,并由它来发起外设初始化配置并提供各模块之间传递信息的全局变量。

LED驱动文件keyLed.c:LED灯功能实现文件,它完成了点亮或熄灭LED灯,以及LED灯闪烁频率的功能,它根据当前的全局变量值改变闪烁方向和频率,是应用功能的执行者。

中断服务源文件stm32f10x_it.c:其内部的诸多中断服务函数是控制信号的改变者,改变某些控制LED灯闪烁方向和频率的全局变量。

下面列出这三个文件的代码,代码做了简化处理,供读者参阅以便了解整个实验的文件组成及功能实现。

1.主程序main.c

代码1-1 工程入口函数 main.c

2.外设驱动源文件:keyLed.h/keyLed.c

代码1-2 外设驱动头文件keyLed.h

3.异常/中断服务程序文件:stm32f10x_it.c

代码1-3 外设中断处理函数EXTI15_10_IRQHandler()1.2 STM32库结构和CMSIS标准

什么是STM32库?

它是由ST公司为缩短STM32开发周期,降低开发成本而提供的函数接口,它通过向下直接处理寄存器,完成外设初始化、外设功能函数的封装;用户的上层应用直接调用这些接口完成特定的功能。下面是STM32官方提供的对函数库的一种描述,可进一步加深对STM32库的理解。

STM32函数库,又称为固件函数库或固件函数包,它由程序、数据结构和宏组成,包括了微控制器所有外设的性能特征。该函数库还包括每一种外设的驱动描述和应用实例。通过使用固件函数库,无须深入掌握细节,用户也可以轻松应用每一种外设。每种外设驱动都是由一组函数组成的,这组函数涵盖了该外设所有功能。每个器件的开发都由一个通用API驱动,API对该驱动程序的结构、函数和参数名都进行了标准化。

什么是CMSIS标准?

基于CM3核的芯片制造厂商很多,如ST、Freescale、SAMSUNG等。虽然它们采用的内核都相同,但由于每一家公司的芯片都有自己不同的外设,此时即使芯片厂商们都提供了所谓的固件函数包,对不同芯片间代码的移植来说,也是一件很耗时的难事。为了解决不同厂商生产的Cortex微控制器软件的兼容性问题,ARM公司于2008年11月发布了旨在降低 Cortext-M 处理器软件的移植难度,并减少新手使用微控制器开发和学习时间,加快产品上市而推出的处理器软件接口 CMSIS,即 ARM Cortex 微控制器软件接口标准(Cortex Micro-controller Software Interface Standard)。

固件库解决的是快速开发的问题,CMSIS标准则侧重于代码的移植。STM32库也是遵循CMSIS而开发的,为了充分发挥STM32库的优势(快捷、移植性好),在正式进入开发之前,得先要了解一下基于CMSIS标准的STM32库的结构。1.2.1 STM32库层次结构

图1-4中的方框文字代表了库目录,非方框文字表示目录下面的文件。图1-4 外部中断/事件EXTIx的产生及传递过程

从库的结构来看:“CMSIS/CM3/CoreSupport”及其下面的文件 core_cm3.h/c 距离 CM3 核最近,它们由ARM公司实现,因此在CMSIS标准中它们被称为CPAL层;“CMSIS/CM3/DeviceSupport/..”下面的文件具有明显的厂商芯片特征,它们完成启动代码、芯片寄存器级的诸多定义和操作,对应于CMSIS标准的DPAL层。可见“CMSIS/CM3/..”目录下的文件是开发工作的基础,是每一个应用工程都必须要包含的。“STM32_StdPeriph_Driver/..”下是芯片上各种外设 xx.h 和 xx.c 文件的集合,比如USART、I2C接口分别对应于stm32f10x_usart.h/c、stm32f10x_i2c.h/c文件。这些文件实现相应外设功能所必需的操作函数,按CMSIS标准,被划分为AFP层。“STM32_Project_Template/..”下的文件,主要完成某些配置,如 stm32f10x_conf.h 文件就实现工程所用外设头文件的选择。这部分文件需要用户进行修改(stm32f10x_conf.h)或代码实现(stm32f10x_it.h/c)。1.2.2 CMSIS层次结构

通过上面STM32库层次结构的描述,从中也可以看出CMSIS从下(CM3核)到上(应用)分别有以下3个层次。(1)核内外设访问层(Core Peripheral Access Layer,CPAL)。该层由ARM负责实现,所定义的接口函数都是可重入的。其实现文件为core_cm3.h和core_cm3.c,其内容主要包括:

● 对核内寄存器名称,地址的定义。

● NVIC,以及对特殊用途寄存器、调试子系统的访问接口定义。

● 还有就是对不同编译器的差异使用__INLINE来进行统一化处理。

● 定义了一些访问CM3核内寄存器的函数,如对xPSR、MSP、PSP等寄存器的访问。(2)片上外设访问层(Device Peripheral Access Layer,DPAL)。该层由芯片厂商负责实现,负责对外设寄存器地址,及其访问接口进行定义。该层可调用CPAL层提供的接口函数,同时根据处理器特性对异常向量表进行扩展,以处理相应外设的中断请求。相应的实现文件有stm32f10x.h、system_stm32f10x.h/c、startup_stm32f10x_hd.s、stm32f10x_it.h/c。(3)外设访问函数(Access Functions for Peripherals,AFP)。这一层也由芯片厂商负责实现,主要提供访问片上外设的操作函数。实现文件为1.1节提到的库文件中的xxx.h/c、msic.c、stm32f10x_conf.h。1.2.3 STM32库结构中的文件关系

通过STM32库的层次结构,结合笔者的工程实际,在进行基于STM32库开发时,所涉及的文件具有如图1-5所示的层次关系。图1-5 STM32库文件层次关系

1.stm32f10x.h

该文件为最基础的头文件,它主要包含了以下几个方面的内容。(1)通用数据类型定义,如:(2)定义所有外设的寄存器组结构,例如1.1.3节提到的GPIO。

由于外设的功能是通过其内部的寄存器来实现的,因此应将这些寄存器视为一个整体。通过C语言的结构体类型定义的方式在代码级就可实现这个操作。上面代码片断中的结构体类型GPIO_TypeDef代表了外设GPIO,其内部成员是GPIO的7个寄存器。(3)外设变量的声明:

所谓的“外设的声明”,其实质主是一些宏定义,宏名就代表了某种外设,而宏值就是该外设基地址。如此一来,操作外设名就是在操作外设地址所在的寄存器,比如对外设GPIOA的操作可以是“GPIOA->IDR=17;”。

可见,文件 stm32f10x.h 在基于 STM32 库开发过程的地位和作用。由于 stm32f10x.h中绝大部分代码都是进行外设的声明和寄存器位定义,所以在用户使用STM32库编写外设驱动时,必须将其包含在自己的工程文件中。

2.system_stm32f10x.h和system_stm32f10x.c

在系统上电复位那一刻,完成系统初始化的两个函数 SystemInit()和 SystemCore ClockUpdate(),以及全局变量SystemCoreClock就在这两个文件中实现,它们的作用分别如下。

SystemInit():设置系统时钟源,其中涉及PLL倍频因子、AHB-APB预分频因子,以及扩展Flash的设置等,该函数在启动文件(startup_stm32f10x_xx.s)中被调用。

SystemCoreClock:此变量代表了系统的核心时钟HCLK的频率值,系统的“滴答”定时器定时长度的计算也是基于这个变量的。

SystemCoreClockUpdate():在系统运行期间,如果核心时钟HCLK需要改变,则必须调用此函数来调整SystemCoreClock的值。注意,只是在HCLK有了变化的情况下才使用它。

关于system_stm32f10x文件中所涉及的知识点,与系统的启动过程联系紧密。这在后面“3.3 STM32 系统时钟初始化”一节中,我们还会对它们进行详细的讲解。在这里先做一个简单的交代,不至于在后续的开发过程中,生搬硬套地引用了一大堆文件,却不知为什么要这样做。

3.启动文件:startup_stm32f10x_hd.s

使用STM32库开发时,startup_stm32f10x_hd.s文件中的函数完成系统启动功能,具体来说,完成了如下工作。

● 设置系统运行的初始堆栈;

● 设置系统运行的初始PC值;

● 设置异常/中断向量表;

● 调用前面提到的系统初始化函数SystemInit(),完成对系统时钟的设置;

● 跳转到C库中的__main()函数,完成应用程序运行环境的设置(如堆、栈、代码段、数据段等在内存中的布局)和系统引导工作。当这些都完成后,最后调用用户主程序入口函数main(),将系统控制权交给用户程序。

由于启动过程的重要性,本书第3章还会专门对系统的启动过程进行详细阐述,同时,在建立工程时必须导入该启动文件。

4.外设文件:stm32f10x_xxx.h、stm32f10x_xxx.c和stm32f10x_conf.h

标题中的“xxx”对应某种外设,如 USART,相应的外设文件就是 stm32f10x_usart.h和stm32f10x_usart.c。因此,STM32F10x系列芯片上有多少种外设,就相应有多少个这样的源文件。这类文件中定义和实现了针对相应外设功能的各种操作,如初始化、读/写数据寄存器、中断控制等。对于这些外设文件,应根据工作实际,导入实际使用到的外设文件,而这种“选择性的导入”是通过stm32f10x_conf.h来实现的。

stm32f10x_conf.h文件内容是这样的:

5.与异常/中断向量相关的文件:misc.c、stm32f10x_it.h、stm32f10x_it.c

在众多的外设源文件中,misc.h和misc.c是比较特殊的一对,其特殊性在于它不是普通的片上外设,而是针对CM3核内的NVIC而设计的。读者对NVIC一定不陌生,系统异常和片上外设中断都必须通过 NVIC 进行统一管理,因此,在基于中断的系统应用中,这对文件是必不可少的。

同理,有异常或中断产生,就必须有对应的ISR(中断服务处理程序)。外设负责产生中断,NVIC负责管理中断,异常/中断向量表中保存了相关ISR的服务程序地址,而真正响应中断的服务程序是在文件stm32f10x_it.h/c或其他文件中完成的。

图1-6很好地展示了异常或中断的传递及处理过程,以及此过程所涉及的相关文件。图1-6 中断的产生、管理和响应1.2.4 STM32库函数命名规则

为了更好地使用STM32库,查阅其中的源代码,了解STM32库对函数名的命名规则十分必要。(1)外设函数的命名“以外设的缩写加下画线开始,以外设所完成的功能描述作为结束”。每个单词的第一个字母都由英文字母大写书写。例如,SPI_SendData()表示外设 SPI的发送数据的函数,USART_Init()则是外设USART的初始化函数。(2)下列命名规则的函数在STM库中大量出现。每一种外设都基本有功能相同的函数,这里列举出来,让读者与这些函数先“混个脸熟”,以便在后续章节的外设实验中快速掌握它们的使用。为方便描述,用“P”来代表某种外设。

● 函数P_Init():功能是初始化外设P,如I2C_Init()。

● 函数P_DeInit():功能是复位外设P的所有寄存器到缺省值,如USART_DeInit()。

● 函数P_Cmd():功能为开启(使能)或关闭(除能)外设P,如SPI_Cmd()。

● 函数P_ITConfig():功能为开启或关闭来自外设P的某中断源,如RCC_ITConfig()。

● 函数 P_DMAConfig():功能为开启或关闭外设 P 的 DMA 通道,如 TIM1_DMAConfig()。

● 函数P_GetFlagStatus():功能是检查(获取)外设P某标志位的状态(是否被设置)。

● 函数P_ClearFlag():功能为清除外设P的某种标志/状态位,如I2C_ClearFlag()。

● 函数 P_GetITStatus():功能为判断来自外设 P 的某中断是否发生,如 EXTI_GetITStatus()。

● 函数P_ClearITPendingBit():功能为清除外设P中断待处理标志位。(3)中断号被定义为后缀为“_IRQn”的名称。异常处理函数的后缀是“_Handler”,中断处理函数的后缀是“_IRQHandler”。例如,对于USART,中断号为USART_IRQn,中断处理函数名为USART_IRQHandler()。1.2.5 STM32库常见的几个状态类型

在库开发中,常在代码中见到FlagStatus、FunctionalState、ErrorStatus类型变量的使用,它们定义在文件stm32f10x.h中,在这里将它们列举出来,以方便后续代码的理解和使用。(1)布尔型类型:(2)标志/中断状态类型:(3)功能状态类型:(4)错误状态类型:1.3 工程开发环境设置

终于到了建立工程的时候了。前面的跑马灯示例中,我们描述了一个完整的工程如何从查看电路连接开始到 GPIO 引脚及中断配置,所需外设源文件编写,最后通过主程序文件main.c将各源文件统一起来。当时我们并没有继续讲解如何进行工程编译,下载到学习板并运行。本节我们使用ARM公司的集成开发工具MDK对这最后一步做个交代,其中包括使用 MDK 进行基本的工程管理,其他更高级的技巧,尤其是工程调试,将在后面的章节中结合工程实例予以讲解。1.3.1 有关MDK

MDK(Microcontroller Development Kit)是ARM公司收购了Keil之后,推出的一款主要基于Cortex-M处理器的开发工具,它是Keil公司集成开发环境uVision IDE与ARM公司的编译工具RVCT(RealView Compile Tools)的完美组合,主要由以下4个部分组成。

● uVision IDE:是一个集项目管理器、源代码编辑器、调试器于一体的强大集成开发环境。

● RVCT:ARM公司提供的编译工具链,包含编译器、汇编器、链接器等。

● RL-ARM:实时库,可根据工程需要将其作为代码库来使用。

● ULINK USB-JTAG仿真器:用于连接目标板的调试接口(JTAG或SWD),帮助用户在目标板上调试程序。

图1-7是打开一个工程时的完整界面。我们以此来大致说明一下此GUI的功能区域划分。图1-7 Keil MDK工程管理界面

默认时整个窗口分为5个区:菜单栏、工具栏、工程管理区、源码编辑区和编译输出区。菜单和工具栏与传统 Window 程序相类似,其中与开发相关的工具或菜单在接下来的1.3.2节“使用MDK建立工程的步骤”的介绍中会做详细说明。

● 工程管理区:以分组(将工程源文件按不同性质划分为不同的分组)的方式管理整个工程的源文件。

● 源代码编辑区:在工程管理区选择的当前文件,其内容会显示在这个区域,开发人员可以在此进行源代码编辑和修改。

● 编译输出区(Build Output):编译工程时,编译成功或出错、报警等信息会显示在个区域。1.3.2 使用MDK建立工程的步骤

1.建立工程结构目录

在一个硬盘分区上建立工程文件夹,以本章“跑马灯”为例,取工程名为 keyLed,并且在该目录下再行建立 4 个空文件夹,如图1-8所示。

● project:在使用MDK新建工程时,工程文件应放在此目录下。

● usr:用户自定义的源码文件,如main.c、usart.h、usart.c 等应存放于此目录下。图1-8 工程文件管理目录

● output:编译链接过程中所产生的中间输出文件等会存放于此处。

● stm32:将原始的 STM32 库文件复制到此文件夹下。

2.工程创建过程(1)创建工程并选择处理器。选择“Project→New uVision Project”菜单项,弹出如图1-9所示对话框询问“新工程文件存放在哪里”,选择在第1步中建立好的project文件夹。

单击“保存”按钮后,弹出“选择处理器”对话框,如图1-10所示。本书配套学习板基于MCU“STM32F103ZET6”,所以在芯片列表中选择“STM32F103ZE”。

选择了芯片型号之后,MDK会弹出“是否在工程中加入CPU的启动代码”的提示框,在此我们选择“否”。因此我们会在随后的“新建源文件及文件组”步骤中,引入 STM32库中自带的启动代码。(2)选择工具链。选择“Project→Manage→Components,Environment and Books”菜单项,弹出图1-11所示的对话框。选择“Folders/Extensions”标签页,并注意“Select ARM Development Tools”群组框,选择的“Use RealView Compiler”是我们使用ARM公司的RVCT工具链。图1-9 创建工程对话框图1-10 选择处理器

3.目标选项配置

选择“Project→Options for Target...”菜单项,弹出“Options for Target”对话框,如图1-12所示。

试读结束[说明:试读内容隐藏了图片]

下载完整电子书


相关推荐

最新文章


© 2020 txtepub下载