一,为什么要使用库函数
51单片机开发一般采用直接操作寄存器方式:如
P0=0x01;//51单片机8位
STM32开发也可以采用直接操作寄存器的方式:如
GPIO->BRR=0x0001 //STM32单片机16位
由于STM32芯片包含数百个寄存器,直接操作寄存器需要全部记下来,难度较大
所以官方推出了一套封装了底层寄存器操作的固件库,提供一套API给开发者使用
库函数的优势:
开发者不用知道具体操作了哪个寄存器,只要调用相应的函数即可实现
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//将指定IO口置0
库函数弊端:
对底层寄存器了解较少导致遇到困难Debug调试的困难
所以,需要开发者了解固件库函数内部寄存器配置的过程
二,库函数工程的搭建
开发环境:MDK5 固件库版本:V3.5
下载并解压固件库 STM32F10x_StdPeriph_Lib_V3.5.0
1,新建项目
打开MDK5,project->new vision project,选择工程保存路径并命名
(新建文件夹Template,其中新建目录USER存放项目生成的文件)
选择芯片类型STM32F103ZE,点击下一步
弹出提示添加工程依赖界面,点击Cancel取消
项目创建完成,文件目录为:
Listings和Objects为MDK自动生成的文件夹,用于存放编译过程中产生的文件
删除掉这两个文件夹,调整项目目录结构后重建OBJ文件夹存放编译文件
2,修改项目结构
在Template文件夹下新建3个文件夹:
CORE:用于存放核心文件和启动文件
OBJ:存放编译过程文件及hex文件
STM32F10x_FWLib:存放官方库函数源码文件
3,导入官方固件库文件
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\STM32F10x_StdPeriph_Driver
下的src和inc文件夹Copy到工程下STM32F10x_FWLib文件夹下
4,导入启动文件到CORE文件夹
STM32F10x_StdPeriph_Lib_V3.5.0\Libraries\CMSIS\CM3\CoreSupport
下的core_cm3.c + core_cm3.h
\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm
下的startup_stm32f10x_hd.s(STM32F103ZET6为大容量芯片,选取hd文件)
复制到项目CORE文件夹下:
5,导入文件到USER文件夹
\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x
复制到USER文件夹下
\Project\STM32F10x_StdPeriph_Template
复制到USER文件夹下
完成后USER目录结构为:
三,将复制的文件加入到工程中
1,修改工程名称并添加工程文件夹
选中项目右键,点击Manage Project items…
修改项目名称为Template并添加CORE.USER,FWLIB文件夹
点击确定,项目目录变更为:
2,将文件添加到工程中
将STM32F10x_FWLib/src/下全部文件添加到工程文件夹FWLIB下
将USER目录下三个文件添加到工程文件夹USER中
将CORE目录下文件添加到工程文件夹CORE中
完成后点击确定,更新后的工程目录结构为
四,配置项目:
1,自动生成HEX文件
2,指定编译过程中产生的中间文件存放在OBJ文件夹(为了兼容不使用默认提供的Object文件夹)
3,设置头文件路径
打开Options for Target->C/C++下Include Paths添加项目包含头文件的路径
4,加入定义 : STM32F10X_HD,USER_STDPERIPH_DRIVER
5,将main.c文件中的代码替换(官方例子中引入的.h文件我们没有引入导致编译报错)
#include "stm32f10x.h"
void Delay(u32 count)
{
u32 i=0;
for(;i<count;i++);
}
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|
RCC_APB2Periph_GPIOE, ENABLE); //使能PB,PE端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED0-->PB.5 端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //IO口速度为50MHz
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化GPIOB.5
GPIO_SetBits(GPIOB,GPIO_Pin_5); //PB.5 输出高
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //LED1-->PE.5推挽输出
GPIO_Init(GPIOE, &GPIO_InitStructure); //初始化GPIO
GPIO_SetBits(GPIOE,GPIO_Pin_5); //PE.5 输出高
while(1)
{
GPIO_ResetBits(GPIOB,GPIO_Pin_5);
GPIO_SetBits(GPIOE,GPIO_Pin_5);
Delay(3000000);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
GPIO_ResetBits(GPIOE,GPIO_Pin_5);
Delay(3000000);
}
代码功能:每隔一段时间切换两个LED亮灭
6,编译成功,0警告0错误
最后别忘记将C文件格式调整为中文,否则会出现乱码
Edit->configuration…->Editor选项卡下->Encodeing:ChineseGB2312(Simplified)