直接使用寄存器地址来进行STM32开发要对每一个寄存器的地址通过查找芯片手册,对每一个寄存器的各个位的含义也要查清楚,然后决定对那个地址的哪些位进行怎样的设置。这种编程效率低,程序的可移植性差,程序的可读性差。
一、CMSIS
基于cortex系列的处理器内核都是一样的,区别在于除内核以外的外设的差异,由于这些差异,导致不同处理器移植起来比较麻烦,所以ARM与芯片厂商建立了CMSIS标准。ARM Cortex™ 微控制器软件接口标准(CMSIS:Cortex Microcontroller SoftwareInterface Standard) 。 是 Cortex-M 处理器系列的与供应商无关的硬件抽象层,使用CMSIS,可以为处理器和外设实现一致且简单的软件接口,从而简化软件的重用、缩短微控制器新开发人员的学习过程,并缩短新设备的上市时间。通过在所有Cortex-M芯片供应商产品中标准化软件接口,这一成本会明显降低,尤其是在创建新项目或将现有软件迁移到新设备时。
CMSIS架构
1、CMSIS软件层次
CMSIS可以分为多个软件层次,分别由ARM公司、芯片供应商提供。
其中ARM提供了下列部分,可用于多种编译器:
● 内核设备访问层:包含了用来访问内核的寄存器设备的名称定义,地址定义和助手函数。同时也为RTOS(实时操作系统)定义了独立于微控制器的接口,该接口包括调试通道定义。
● 中间设备访问层:为软件提供了访问外设的通用方法。芯片供应商应当修改中间设备访问层,以适应中间设备组件用到的微控制器上的外设。
芯片供应商扩展下列软件层:
● 微控制器外设访问层:提供片上所有外设的定义。
● 外设的访问函数(可选):为外设提供额外的助手函数。
CMSIS为Cortex-Mx微控制器系统定义了:
● 访问外设寄存器的通用方法和定义异常向量的通用方法。
● 内核设备的寄存器名称和内核异常向量的名称。
● 独立于微控制器的RTOS接口,带调试通道。
● 中间设备组件接口(TCP/IP协议栈,闪存文件系统)。
2、CMSIS包含的组件
① 外围寄存器和中断定义: 适用于设备寄存器和中断的一致接口
② 内核外设函数:特定处理器功能和内核外设的访问函数
③ DSP 库:优化的信号处理算法,并为 SIMD 指令提供Cortex-M4 支持
④ 系统视图说明(SVD):描述设备外设和中断的XML文件。
该标准完全可扩展,可确保其适合于所有 Cortex-M处理器系列微控制器,从最小的8 KB 设备到具有复杂通信外设(如以太网或USB)的设备。(内核外设函数的内存要求少于1 KB 代码,少于10 字节RAM)。
二、基于CMSIS应用程序的基本结构
1、CMSIS-外设访问层的文件
① 独立于编译器的文件:
● Cortex-M3内核及其设备文件(core_cm3.h + core_cm3.c)
─ 访问Cortex-M3内核及其设备:NVIC,SysTick等
─ 访问Cortex-M3的CPU寄存器和内核外设的函数
● 微控制器专用头文件(device.h)
对STM32F10x的头文件为"stm32f10x.h"
─ 指定中断号码(与启动文件一致)
─ 外设寄存器定义(寄存器的基地址和布局)
─ 控制微控制器其他特有的功能的函数(可选)
● 微控制器专用系统文件(system_device.c)
对STM32F10x的程序文件为"system_stm32f10x.c",头文件为"system_stm32f10x.h"
─ 函数SystemInit,用来初始化微控制器
─ 函数Sysem_ExtMemCtl,用来配置外部存储器控制器。它位于文件startup_stm32f10x_xx.s /.c,在跳转到main前调用
─SystemFrequncy,该值代表系统时钟频率
─ 微控制器的其他功能(可选)
② 编译器供应商+微控制器专用启动文件
● 编译器启动代码(汇编或者C)(startup_device.s)
对STM32F10x的头文件为"startup_stm32f10x_XX.s",对STM32F103ZET6使用"startup_stm32f10x_hd.s
─ 微控制器专用的中断处理程序列表(与头文件一致)
─ 弱定义(Weak)的中断处理程序默认函数(可以被用户代码覆盖)
2、库文件简介
① core_cm3.c文件
在CoreSupport文件夹中有core_cm3.c和头文件core_cm3.h,它的作用是采用Cortex-M3内核设计的SoC芯片厂商设计的芯片提供了一个进入CM3内核的接口。core_cm3.c中还有一些与编译器(MDK、IAR等)有关的代码。较重要的是core_cm3.c中包含stdio.h头文件,这是一个ANSI C文件,主要作用是提供一些新类型的定义。
② system_stm32f10x.c文件
DeviceSupport文件夹下是启动文件、外设寄存器定义、中断向量定义层的一些文件,这些文件由ST公司提供。system_stm32f10x.c的主要作用是设置系统时钟和总线时钟。
③ stm32f10x.h文件
这个文件非常重要,是非常底层的文件,包含了寄存器地址和结构体类型的定义,在使用到stm32固件库的地方都要包含它。
④ stm32f10x_it.c和stm32f10x_conf.h文件
stm32f10x_it.c这个文件主要是编写中断程序的,stm32f10x_conf.h被包含在stm32f10x.h文件中主要是配置外设的头文件,我们需要什么在这里打开。
⑤ startup_stm32f10x_hd.s文件
在这个文件中有一段启动文件,启动文件中先初始化系统时钟,然后才执行主函数,因此我们要注意配置时钟在这个文件里配置。
三、创建项目,加入必要文件和配置相关参数
1、在项目文件夹下新建一个"pCMSIS"文件夹,然后在该文件夹中创建"CMSIS"、"Device"、"Startup"和"User"四个文件夹,创建不同的文件夹主要是为了分类存放不同作用的文件,便于文件管理,当项目比较复杂时方便文件管理,不分文件夹也是可以的。在"CMSIS"文件夹中复制"core_cm3.c"和"core_cm3.h"文件;在"Device"文件夹复制"stm32f10x.h"、"system_stm32f10x.c"和"system_stm32f10x.h"文件;在"Startup"文件夹下复制"startup_stm32f10x_hd.s。
2、在Keil5中新建项目pCMSIS,存放在"pCMSIS"文件夹中,点击按钮或者通过菜单"Project"->"Manage"->"Components,Environment,Books…"打开进行"Manage Project Items"对话框,对项目文件管理。
在"Groups"中分别添加"CMSIS"、"Device"、"Startup"和"User"四个组,并为每一个组添加上述1中叙述的文件。
3、新建一个文件并保存为"main.c"(保存在"User"文件夹下),然后将该文件添加到"User"组中,在文件内添加如下内容:
#include "stm32f10x.h" int main() { } |
4、点击工具按钮,在对话框的"Output"选项卡中选中"Create HEX File",在"C/C++"选项卡中的"Include Paths"项目点击按钮,打开"Folder Setup"对话框,添加如下包含路径:
这时,项目框架搭建完成,可以编译生成hex文件。
5、实现LED灯控制。
实现过程同样是使能GPIO时钟、设置工作方式、点亮LED灯几个步骤,因为前面为项目添加了几个文件,在这些文件中包含了相关的预定义,所以编程只需要使用这些预定义即可。
① 使能GPIOC时钟。
由于在"stm32f10x.h"文件中有上述预定义,标识符"RCC"为一个结构体类型的指针,只需要通过给RCC->APB2ENR的第4位赋值就能就能使能GPIOC的时钟,所以使用:
RCC->APB2ENR |=0x1<<4; //开启GPIOC时钟
② 配置GPIOC_0为推挽输出,50M速度。
同样,由于在"stm32f10x.h"文件中有上述预定义,标识符"GPIOC"为一个结构体类型的指针,通过给GPIOC->CRL的3~0位设置为"0011"就可以配置GPIOC_0为推挽输出,50M速度。即:
GPIOC->CRL &= ~(0x0F<<(4*0)); //对GPIOC_0设置为通用推挽输出,最大速度50MHz
GPIOC->CRL |= (0x03<<(4*0));
③ 点亮LED灯。点亮LED1,需要给GPIOC_0输出低电平,可以通过BSRR复位实现。
while(1)
{
GPIOC->BSRR |= 0x01<<(16+0); //对GPIOC_0复位
delay(1000);
GPIOC->BSRR |= 0x01<<(0+0); //对GPIOC_0置位
delay(1000);
}
main.c的完整程序如下:
#include "stm32f10x.h" void delay(int t) { int i; for( ;t>0; t--) for(i=0;i<1000;i++); } int main() { RCC->APB2ENR |= 0x1<<4; //ʹÄÜGPIOCʱÖÓ GPIOC->CRL &= ~(0x0F<<(4*0)); //¶ÔGPIOC_0ÉèÖÃΪͨÓÃÍÆÍìÊä³ö£¬ËÙ¶È50MHz GPIOC->CRL |= (0x03<<(4*0)); while(1) { GPIOC->BSRR |= 0x01<<(16+0); //¶ÔGPIOC_0¸´Î» delay(1000); GPIOC->BSRR |= 0x01<<(0+0); //¶ÔGPIOC_0ÖÃλ delay(1000); } }
|
6、编译,下载程序,LED1闪烁。