库函数配置
ARM Cortex™ 微控制器软件接口标准(CMSIS:Cortex Microcontroller Software Interface Standard)
STM32单片机是Cortex-M3内核,有ARM公司设计,其他片上外设都是由芯片制造商设计开发(ST、TI)的。
同样是用相同内核的单片机,内核相同但是是不同的公司的不同外设,其控制方式也有很大的区别。
不同公司的芯片都用自己封装的函数的话会造成混乱,所以ARM与芯片厂商建立了CMSIS标准。
CMSIS处于开发中间层,向上提供给用户程序所需的函数接口,向下负责与内核和其他外设通信的函数。
其中,由ARM公司提供了内核设备访问层和中间设备访问层,而芯片公司提供了外设访问层,提供了片上所有外设定义的函数。
将CMSIS层再具体展开:
本质上,配置库函数、建立工程,实际上就是要正确配置这些函数文件。正确配置完成才能正确调用函数来实现对应的功能。
结合CMSIS构架来整理库函数文件比较有条理性。
以core_cm3.h为例,在图中可以看到这个文件属于CMSIS层当中的CMSIS核心层内核相关文件。
首先是用户层USER:
从图中可以看见“stm32f103x_it.c”和“stm32f103x_it.h”这两个文件是和中断程序有关的。(it:interrupt—中断的缩写)
STM32相比51单片机功能更加强大,几乎每个引脚都能使用中断,48引脚的单片机可能有46个中断,因此STM32内部还有一个:NVIC——嵌套相量中断控制器。
stm32f103x_conf.h(conf:config)
其次是CMSIS层:
图中可以看到“stm32f10x_ppp.c”和“stm32f10x_ppp.h”,其中“ppp”表示“外设名称”(GPIO、i2C)。
例如:“stm32f10x_gpio.c”和“stm32f10x_gpio.h”等。
STM32的头文件当中除了函数声明以外,还包括寄存器的映射和一些结构体。
所以再在编写程序的过程中需要用到寄存器时,就需要包含这些对应寄存器头文件。但是如果随着程序的复杂,需要包含的头文件也随着增多。因此为了解决这个问题,我们只要包含“stm32f103x_conf.h”即可,包含了它就等于包含了所有的头文件。但是实际上写程序的时候,我们包含的头文件是“stm32f103x.h”。因为这个头文件本身就包含了“stm32f103x_conf.h”。
在CMSIS核心层还可以看见“system_stm32f10x_it.c”和“system_stm32f10x_it.h”这两个文件,这两个文件是用来设置时钟的。
然后就是“core_cm3.c”和“core_cm3.h”这两个文件,这两个文件是和内核相关的,其中:
“core_cm3.h”文件实现了内核的寄存器映射
“core_cm3.c”文件包含了操作内核外设寄存器的函数
包括上文提到的“stm32f103x.h”,该文件针对的是片上的外设;而“core_cm3.h”针对的是片上的外设。
还有“misc.c”和“misc.h”两个文件,这两个文件属于设备外设部分,例如上文提到的NVIC(嵌套向量的中断控制器)、SysTick(系统滴答定时器)——一般用于操作系统的时钟节拍,也可以用做普通的定时,这些相关函数都可以在misc.c文件当中找到。
其次是启动文件“startup_stm32f10x_md.s”,其中m的意思是medium(中等容量),根据不同容量大小选择对应的启动文件。
启动文件内的内容是使用汇编语言写,我们之前在写代码的时候,都需要在主函数下面写一个systemInit();,是因为系统在进入主函数之前要进行一系列的初始化工作,初始化工作包括了对时钟的配置工作。而对时钟的配置我们都是自己操作寄存器配置完了,不需要系统初始化,启动文件里又恰好需要这个函数来初始化。但为了骗过编译器,所以才写了systemInit();这个空函数以通过编译。
总结以上内容,上图的文件就是我们新建库函数模板的相关文件。
STM32F103官方固件库文件目录:
Keil配置设置:
USE STDPERIPH DRIVER STM32F10X_MD是宏定义,实际上是两个语句中间用逗号隔开。
第一句宏定义意思是使用标准的外设驱动。
之所以需要做这个宏定义,主要是和移植有关。
因为程序不是适用于所有的芯片,如果这个程序之前是用在F103上的,现在把程序放在F104上来用,就需要添加这个宏。
C语言当中的条件编译:
图中语句的含义是:
如果定义了USE_STDPERIPH_DRIVER这个宏,就执行下面的语句,即:#include "stm32f103x_conf.h" 这个语句。因为之前在keil的设置中有定义这个宏,所以keil就会包含这个头文件。
第二宏:
同理,第二句宏定义将会执行244-268行的语句。
但是这个时候问题就来了,在这个宏的上面还有别的一些宏:
该如何选择定义哪个宏呢?
这时候就要根据开发的目标芯片Flash容量的大小,来选取需要设置的宏。
实际上并不是一定要在keil上设置对应的宏定义,也可以直接在对应的文件中写出来:
在keil设置只是为了方便和统一。
新建工程步骤:
1、创建文件模板
新建“Temp”文件夹,并在Temp文件夹当中创建文件目录:
Lib、Output、Project、User四个文件夹,分别存放固件函数库、编译输出文件、keil工程文件以及用户编程文件。