使用STM32固件库操作控制LED灯(CMSIS)

    直接使用寄存器地址来进行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闪烁。

猜你喜欢

转载自blog.csdn.net/fanxp66/article/details/80214976