一、什么是固件库
固件库是指“STM32标准库函数”,它是ST公司针对STM32提供的函数接口API(Application Program Interface),开发者可以调用这些函数接口来配置STM32的寄存器,可以使开发人员脱离繁琐的寄存器操作,有开发快速、易阅读、维护成本低等优点。
当我们使用固件库的时候,不需要过于去了解库函数底层的寄存器操作,就像我们学习C语言的时候,对于函数printf(),只是学习它的使用方法,并不研究它功能是怎么实现的。但当我们深入了解的时候,库源码就是我们最佳的学习范例。
实际上固件库是架设在寄存器和用户驱动之间的代码,向下处理与寄存器直接相关配置,向上为用户提供配置寄存器的接口。
二、为什么采用固件库编程
对于STM32,因为外设丰富,带来的必然结果就是寄存器的数量复杂度的增加,直接采用寄存器编程的缺点就出来了:
1)开发速度慢。
2)程序可读性差。
3)维护复杂。
这些缺点直接影响了开发效率、维护成本、交流成本。库开发方式正好弥补了这些缺点。
其实还有一点,看过固件库的源码,相信你会被它严谨,优美的实现方式而折服,对于想要修炼C语言,STM32的固件库是个不错的选择。
三、固件库工程模板的创建
1、我们建立一个”工程模板“文件夹,在它下面在新建4个文件夹
Listing | 存放编译器编译适合产生的C/汇编/链接的列表信息 |
Project | 存放工程 |
Output | 存放编译产生的调用信息、hex文件、预览信息、封装库等 |
User | 存放用户编写的驱动文件 |
2、打开keil5点击Project新建一个工程放到我们刚建的”工程模板“文件夹中的Project中命名按喜好来就行,这里建议使用英文。
3、 在弹出的界面中我们选中F1系列中103中的任意一款芯片,这里我选的STM31F103R6,因为我们用的Proteus仿真中有这款芯片,等下可以仿真。
4、在弹出的Manage Run-Time Environment(管理运行环境)窗口中选中CMSIS标准中CORE(内核)在Device中选定选定启动文件Startup和GPIO,在StdPeriph Drivers中选中时钟RCC、外设GPIO和框架Framework点击OK这样我们的工程就创建好了。
5、我们打开魔术棒
6、选择Output中选择我们自己建的文件夹中的Output文件夹 记得勾上HEX文件选项后面用Proteus仿真得用。
7、选择Listing中选择我们自己建的文件夹中的Listing文件夹
8、新建一个空白的文本把他保存为后缀为.c放到到我们的User文件夹中。
9、对准我们的Source Group 文件右击我们的鼠标点击图中的选项找到我们刚保存到User文件夹中的.c文件加入到文件中到此我们一个固件库的工程模板就已经创建好了可以开始正式的写代码了。
代码如下
LED头文件
#ifndef _LED_H_ //判断标号_LED_H_是否被定义,如果没有则#ifndef到#endif代码有效
#define _LED_H_
#include <stm32f10x.h>
#define LED_GPIO_PORT GPIOA //LED的GPIO端口
#define LED_GPIO_CLK RCC_APB2Periph_GPIOA //LED相对应的时钟端口开启
#define LED_GPIO_PIN GPIO_Pin_0 //LED的GPIO引脚号
void LED_GPIO_Confing(); //LEDdGPIO端口初始化函数
#endif
LED.c文件
#include "led.h"
void LED_GPIO_Config()
{
GPIO_InitTypeDef GPIO_InitStructure;
/*定义一个GPIO_InitTypeDef类型的结构体*/
RCC_APB2PeriphClockCmd(LED_GPIO_CLK,ENABLE);
/*开启LED相关的GPIO外设时钟*/
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
/*设置引脚模式为通用推挽输出*/
GPIO_InitStructure.GPIO_Pin=LED_GPIO_PIN;
/*选择要控制的引脚*/
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_2MHz;
/*设置引脚速率为2MHz*/
GPIO_Init(LED_GPIO_PORT,&GPIO_InitStructure);
/*调用库函数初始化GPIO*/
}
main主函数
#include "led.h"
int main()
{
LED_GPIO_Config(); //初始化函数
GPIO_ResetBits(LED_GPIO_PORT,LED_GPIO_PIN); //库函数端口置低
}
本文使用了库函数有
函数名 | GPIO_Init() |
函数原型 | void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) |
功能描述 | GPIO_InitStructuct中指定的参数初始化外设GPIOx寄存器 |
输入参数1 | GPIOx:x可以是A,B,C,D,来选择GPIO外设 |
输入参数2 | GPIO_InitStruct:指向结构体GPIO_InitTypeDef的指针,包含外设GPIO的配置信息 |
函数名 | RCC_APB2PeriphClockCmd() |
函数原型 | void RCC_APB2PeriphClockCmd(u32 RCC_APB2Periph, FunctionalState NewState) |
功能描述 | 使能或者失能APB2外设时钟 |
输入参数1 | RCC_APB2Periph:门控APB2外设时钟 |
输入参数2 | NewState:这个参数可以是ENABLE或DISABLE |
函数名 | GPIO_ResetBits() |
函数原型 | void GPIO_ResetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin) |
功能描述 | 清除指定的数据端口 |
输入参数1 | GPIOx:x可以是A,B,C,D,来选择GPIO外设 |
输入参数2 | GPIO_Pin:待清除的端口 该参数可以取GPIO_Pin_x(x可以是0到15的任意组合) |
编译后我们来看看仿真结果可以看出来LED已经被点亮了
希望对初学的您能有所帮助。