购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

第5章
STM32单片机标准外设固件库

为了后续能够顺利进行STM32单片机开发,首先需要初步熟悉该平台对应的固件库,具体包括标准的 外围设备 (简称“外设”,可以理解为“控制器”)固件库(不同的单片机系列对应不同的固件库,STM32F103C8T6对应STM32F10x_StdPeriph_Lib)与USB全速设备固件库(STM32_USB-FS-Device_Lib)。也就是说,与USB控制器相关的固件库是分开的,我们先从标准的外围设备固件库切入。

有人可能会问:为什么要使用固件库呢?记得以前开发51单片机的时候可没这些? 直接访问底层寄存器 就可以做项目呀!实际上,STM32单片机也可以采用 直接访问底层寄存器 的方式编程,但是由于STM32单片机比51单片机复杂得多,底层的寄存器数量也很庞大,直接访问它们还是会影响开发效率的,所以STM32单片机的生产厂商意法半导体(SGS-THOMSON Microelectronics, ST)推出了固件库,它将对底层寄存器访问的函数进行包装,并提供一套应用程序接口(Application Programming Interface, API)函数,我们只需知道在适当的时候调用哪些函数即可。

当然,本书并不是不讨论底层寄存器,只不过从固件库入手能够帮助你建立更宏观的概念,否则直接钻到一大堆寄存器当中就很难理清楚头绪了。我们很快就会使用简单的例子展示API函数与底层寄存器之间的映射关系。如此一来,即使你的开发平台与本书并不一致,也并不影响你对本书内容的理解。换句话说。固件库只是帮助我们理解USB控制器的工具,最终还是会深入硬件底层,毕竟我们要理解问题的实质所在,而不是简单地运行一个例程就完事了。

那我们应该如何使用固件库呢?一般在main主函数所在的文件中, 只需包含头文件stm32f10x.h即可 ,它与51单片机开发中需要包含的头文件reg51.h具有等同的意义。但是前面已经提过,STM32单片机是比较复杂的,所以 stm32f10x.h 包含的信息量比较大(超过8000行代码),其中的细节暂时不必深究,后续有需要时再来讨论,但是你会看到其中又包含了几个头文件,如清单5.1所示。

清单5.1 stm32f10x.h头文件(部分)

core_cm3.h(.c)是由ARM公司提供的核心文件,它提供了进入Cortex-M3内核的接口,不需要对其进行修改,而system_stm32f10x.h(.c)提供了设置系统与总线时钟的函数。ARM是负责芯片内核架构设计的公司(Cortex-M3内核就是其中之一),其本身并不制造芯片。ST(或其他有需要的厂商)获得Cortex-M3内核授权后,根据自己的市场战略制造出一系列具体的单片机(简单地说,就是在内核的基础上添加很多控制器,如Timer、ADC、SPI、I 2 C、USB等)。ST之类芯片的制造厂商卖出的每个芯片,都需要给ARM公司缴纳一定的费用,这就是ARM公司的营利模式。

由于多家厂商会从ARM公司获得Cortex-M3授权,但是它们的市场战略或本身拥有的资源不尽相同,最终制造出来的单片机自然也会有差异(内核仍然是一样的)。为了让使用相同内核的不同厂商单片机的源代码能够尽量保持兼容,ARM与芯片的制造厂商提出了ARM Cortex TM 微控制器软件接口标准(Cortex Microcontroller Software Interface Standard, CMSIS)。简单地说,CMSIS制定了一些规范化的命名方式,厂商在设计自己的固件库时必须按该标准来做,这样就不会出现不同的代码风格。

头文件stm32f10x_conf.h由ST厂商提供,主要用来包含相关外设控制器的头文件(相当于多个头文件的汇总),其主要源代码如清单5.2所示。STM32单片机内部的每个控制器都对应了一个头文件(与源文件),对于那些当前项目不需要使用的外设,将相应的“头文件包含的预处理指令行”注释掉即可(当然,也可以选择全部包含,只不过编译时间会长一些而已)。

清单5.2 stm32f10_conf.h头文件

特别注意清单5.1中,必须要定义一个USE_STDPERIPH_DRIVER宏才能包含stm32f10_conf.h头文件,我们通常会在开发软件平台(本书使用Keil)中定义,如图5.1所示。

图5.1 Keil软件平台中的宏定义

stdint.h头文件是一个标准C库文件,大部分单片机C编译器均支持,其中定义了很多数据类型的别名,如清单5.3所示。

清单5.3 stdint.h头文件(部分)

也就是说,在后续的编程开发过程中,我们不会直接使用标准C定义的char、int等基本数据类型,而是使用重新定义后的int8_t、int16_t等数据类型,这样做的目的主要是保证固件库的独立性,以方便可能存在的源代码移植,因为不同编译器对每种基本数据类型字节大小的定义可能不完全一样,如果直接使用char、int等基本数据类型,则更换平台编译后可能会使代码产生解析上的错误,继而导致出现功能异常;如果要让它重新正确运行起来,就需要将固件库中所有使用到的数据类型都做相应的替换,这将会非常麻烦且容易出错!如果使用重定义后的数据类型,我们仅需要在必要时针对不同的编译器更改stdint.h文件中的数据类型定义即可,而引用这些数据类型的源代码却可以完全保持不变,这就是刚刚提到的“保证固件库独立性”的意思。

总体上,在开发STM32单片机项目时需要的库文件架构如图5.2所示。其中,stm32f10x_it.h(.c)是存放STM32工程中所有中断函数的模板文件。如果不使用中断,可以将这两个文件都去掉。当然,也可以将中断函数放在其他的文件中。也就是说,这两个文件的包含并不是必需的。stm32f10x_ppp.h(.c)是STM32外设驱动文件的统称(ppp对应某个外设名称),它对应诸如stm32f10x_gpio.h(.c)、stm32f10x_rcc.h(.c)等文件。misc.h(.c)是中断向量嵌套的外设驱动文件,大家了解一下即可。

图5.2 项目开发时需要的库文件架构

前面提到的库文件可以在ST厂商发布的标准固件库中找到,V3.5.0版本的库文件结构如图5.3所示。

我们重点关注一下启动文件(51单片机也有启动文件),它主要包含堆栈初始化、中断向量表及中断函数的定义,不同STM32系列的单片机对应的启动文件也不一样,具体如表5.1所示,其中的“容量”主要针对Flash存储器容量。通常,16~32KB为小容量,64~128KB为中容量,256~512KB为大容量,512~1024KB为超大容量。STM32F103C8T6的Flash存储器容量大小为64KB,属于中容量芯片,所以应该选择startup_stm32f10x_md.s,只需要将其包含在项目中即可。

图5.3 V3.5.0版本的库文件结构

表5.1 不同芯片对应的启动文件

不同芯片对应的启动文件不一样,相应的中断号也会不一样。stm32f10x.h头文件针对不同芯片系列定义了各自的中断号,如清单5.4所示,其中针对不同单片机系列定义了中断号枚举类型IRQn_Type。也就是说,宏STM32F10X_LD、STM32F10X_LD_VL、STM32F10X_MD、STM32F10X_MD_VL、STM32F10X_HD、STM32F10X_HD_VL、STM32F10X_XL、STM32F10X_CL与启动文件是对应的,既然我们选择的单片机对应的启动文件是startup_stm32f10x_md.s,那么也应该定义相应的宏,所以图5.1所示的对话框中还定义了STM32F10X_MD宏。

清单5.4 中容量STM32F10X系列单片机的中断号定义

顺便提一下本书对源代码的注释方式。官方固件库的注释语言均为英文,且使用“/**/”的注释方式。如果本书对原来的注释进行了任何修改(例如,删除、增加、翻译等),将会采用“//”的注释方式,否则保持原有注释形式不变。

当你需要使用某些库文件进行开发时,可以选择的方式主要有两种:其一, 将需要的库文件复制到自己开发的每个项目中 。虽然这会使项目的源代码占用很大的磁盘空间,但可以将工程直接给别人使用(拿到手就可以编译)。其二, 直接从固件库中添加相应的文件到项目中(库文件不在项目所在的目录下,只是引用而没有复制) 。虽然这种方式会占用较小的磁盘空间,但别人此时只有项目的源代码而没有固件库(或固件库的目录跟你的设置不一致),需要重新进行固件库文件的配置,比较麻烦。厂家为了方便对评估板例程进行管理,通常会使用后一种方式,这样同一个评估板对应的多个例程就可以共享相同的库文件了。

为了简单起见,我们将所有需要的头文件、源文件及启动文件全部放在一个目录下(切记,在stm32f10_conf.h头文件中注释掉没有使用的外设对应的“头文件包含的预处理指令行”,除非你已经将所有头文件都复制过来),并且在该目录下建立项目。将源文件与启动文件添加到项目后的项目文件如图5.4所示。

main.c是新建的源文件,后续编写的应用代码就在里面。如果你觉得项目文件有点乱,则可以进一步新建组(Group)对文件进行分组。“组”是一种逻辑上的概念,与目录是不同的,即便你将所有文件都放在同一目录,也可以进行“组”的划分。例如,我们将核心文件与启动文件归为Core组,将外设文件归为STM32F10x_StdPeriph_Driver组,其他文件归为User组,分组后的项目文件如图5.5所示。

图5.4 将源文件与启动文件添加到项目后的项目文件

图5.5 分组后的项目文件

当然,现在项目中所有的文件都是“扎堆”放在同一目录的,你也可以根据自己的习惯新建目录将它们分类放置,只需要记得在图5.1中将相关的头文件目录添加到“Include Paths”中,这已经不是本书的讨论范畴了,大家了解一下即可。

还有一点值得提醒的是,在进行项目编译时,应该勾选图5.1所示对话框中“Output”标签页中的“Create HEX File”与“Browse Information”两项,前者表示生成可被单片机执行的十六进制文件,将其下载到单片机就可以运行;后者表示编译时生成浏览信息,这样在Keil软件平台中进行标识符、函数或文件跳转查询时就会很方便,如图5.6所示。

图5.6 “Output”标签页

接下来就从main.c源文件开启简单快乐的编程开发之旅吧! jH4BswGMBdkkQomkxs76eKZBfC3kFkItBoY9akj2HSPOAh0vd8XhUmJphJTnJqeh

点击中间区域
呼出菜单
上一章
目录
下一章
×