前言
学习本篇之前,推荐先学习基础操作
https://blog.csdn.net/weixin_43014010/article/details/123112458
固件库
所谓固件库就是把各种寄存器操作用函数和宏封装起来。这样在编程的时候就不需要接触到最底层的地址操作,也不需要反反复复去查参考手册,而可以使用更加接近自然语言的方式来编程。
固件库包含以下的内容:
-
启动文件——使用汇编语言编写,完成最基本的初始化
-
时钟配置文件——正常情况下不修改,即使是要超频或者降频也是把对应函数拿出来操作
-
外设控制部分——我们要学的部分
-
内核控制部分——我们要学的部分
-
头文件的头文件——大概是怕你漏掉某些头文件吧
-
中断服务函数——但是实际上中断服务程序不一定只能写在这里
其实固件库里面大多数东西都是写好的,所以只需要知道在哪里去找,怎么用就行
固件库编程
固件库编程套路如下:
- 使用宏封装硬件相关信息
- 开启时钟
- 配置初始化结构体
- 调用初始化函数
- 编写用户内容
接下来就以点亮PC13 LED为例,解释固件库编程。固件库编程是一个非常套路的东西,不管是要用LED,还是蜂鸣器或者串口,DMA等等,流程和方法都是一样的。
「本文为了讲解方便所以将所有内容都写在main.c里了」
使用宏封装硬件相关信息
多说无益,直接上代码
#define LED0_PIN GPIO_Pin_13
#define LED0_PORT GPIOC
#define LED0_GPIO_CLK RCC_APB2Periph_GPIOC
#define LED0_OFF GPIO_SetBits(GPIOC, GPIO_Pin_13)
#define LED0_ON GPIO_ResetBits(GPIOC, GPIO_Pin_13)
开启时钟
数字电路不管干什么都是要开时钟的。这个在固件库里面是已经写好函数的。我们知道时钟由RCC寄存器控制,因此打开时钟对应的函数,就应该在stm32f10x_rcc.c里面。
(这里并不是要真的从头读到尾去找。这是套路,比如现在你知道了RCC_APB2PeriphClockCmd,那以后要去找其他外设,就很简单了,可以直接搜索PeriphClockCmd)
看着这个函数,可以知道,函数有两个输入,第一个是外设名称,在这里也就是GPIOC「实际上这也是固件库给套好的宏,实际传入的是一个地址」,第二个是状态,也就是ENABLE或者DISABLE「不用说了这个也是宏,实际上是0和1」。那么这一行代码也就出来了:
RCC_APB2PeriphClockCmd(LED0_GPIO_CLK,ENABLE);
「这个时候使用宏封装硬件信息的优势就体现出来了,封装好之后,这里就不用管这个灯哪个总线,哪个GPIO口了,只需要打上它的代号——LED0_GPIO_CLK就可以了,在后期移植的时候,如果板子换了,不再点亮PC13,也可以更加方便的修改」
配置初始化结构体
要使用一个外设就需要初始化,而使用固件库编程就可以通过一个结构体来初始化。这个结构体是固件库里面已经写好的,可以在相应的文件里面去找,比如点亮LED灯需要使用GPIO,那么就去stm32f10x_gpio.c里面找
要找的话,找TypeDef就可以了
根据这个结构体,在相应的位置填入相应的内容就可以了。「当然第一步是新建一个这样式的结构体啊」
GPIO_InitTypeDef GPIO_InitStruct;//新建初始化结构体
GPIO_InitStruct.GPIO_Pin=LED0_PIN;//配置针脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//配置输入输出模式
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//配置速度
关于结构体里面的各个位置,可以参考官方手册
调用初始化函数
初始化结构体写好了,接下来要去使用它。这里就需要调用初始化函数了。没得说,这个函数也是固件库写好的,到外设对应的文件里面去找就可以了。
同理GPIO对应的东西,到stm32f10x_gpio.c里面去找。函数比较长,也就没有全部抄下来了。看看输入需要什么。第一个变量,一个地址,表示需要配置的GPIO端口。第二个变量,也是一个地址,指向配置信息,也就是初始化结构体。
因此这一行代码也就出来了:
GPIO_Init(LED0_PORT,&GPIO_InitStruct);
编写用户内容
到这里所有的配置就完成了,接下来就可以自己编写用户函数了。LED灯,想怎么亮,就怎么亮。
完整代码:
#include "stm32f10x.h"
#define LED0_PIN GPIO_Pin_13
#define LED0_PORT GPIOC
#define LED0_GPIO_CLK RCC_APB2Periph_GPIOC
#define LED0_OFF GPIO_SetBits(GPIOC, GPIO_Pin_13)
#define LED0_ON GPIO_ResetBits(GPIOC, GPIO_Pin_13)
int main(void)
{
RCC_APB2PeriphClockCmd(LED0_GPIO_CLK,ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;//新建初始化结构体
GPIO_InitStruct.GPIO_Pin=LED0_PIN;//配置针脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP;//配置输入输出模式
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//配置速度
GPIO_Init(LED0_PORT,&GPIO_InitStruct);//初始化外设
LED0_ON;//点亮led灯
}
注:写在宏里面的GPIO_SetBits和GPIO_ResetBites,也是固件库已经写好的置位和清零函数,用来控制对应的针脚输出高或者低电平。要查看详细信息,同样在stm32f10x_gpio.c里面找。