文章目录
- 一:新建基于库函数开发的工程
- 二:截图操作实现
- 三:main.c 大致代码实现
- 道友:凡事只想着蒙混过关,困难只会越来越多。我们要有,独立解决问题的能力,才能成长为更好的自己。
基于库函数开发
一:新建基于库函数开发的工程
使用库函数进行开发,需要准备STM32库函数。 这个库函数由ST公司提供,而Keil软件所需的器件支持包是由Keil公司提供
本文使用的是STM32F10x标准外设库的压缩包“STM32F10x_StdPeriph_Lib_V3.5.0”,解压后文件如图
1._htmresc:存放两个图片,没用。
2.Libraries:存放库函数的文件。
3.Project:官方提供的工程示例和模板,使用库函数的时候可以参考。
4.Utilities:STM32官方评估板的相关例程,这个评估板是STM32官方自己做的小电路板,专门用于测评STM32。
5.Release_Note.html:库函数的发布文档,有一些版本说明。
6.stm32f10x_stdperiph_lib_um.chm:使用手册,说明如何使用库函数。
新建工程步骤:
1.建立工程文件夹,Keil中新建工程,选择型号。
2.工程文件夹里建立Start、Library、User文件夹,复制固件库里面的文件到工程文件夹。
3.工程里对应建立Start、Library、User等同名文件夹,然后讲文件夹内的文件添加到工程分组里。
4.工程选项(魔法棒),C/C++,Include Paths 内声明所有包含头文件的文件夹。
5.工程选项(魔法棒),C/C++,Define内定义USE_STDPERIPH_DRIVER。
6.工程选项(魔法棒),Debug,下拉列表选择对应调试器,Settings,Flash Download 里勾选Reset and Run(每个项目都要手动设置一次)。
基于库函数的开发方式,就是在基于寄存器开发的基础上,真正引入库函数,并创建文件夹“Library”单独存放。新建工程步骤:
- 建立工程文件夹,Keil中新建工程,选择型号。
- 工程文件夹里建立Start、User、Library文件夹,复制固件库里面的文件到工程文件夹。
Start部分1:启动文件,位于固件库文件夹“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\arm”。STM32的程序从启动文件执行。
Start部分2:位于固件库目录“.\Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x”的三个文件。“stm32f10x.h”描述STM32外设寄存器及其对应的地址,作用相当于51单片机中的头文件“REGX52.h”。
“system_stm32f10x.h”、“system_stm32f10x.c”主要用于配置时钟,比如配置STM32的主频为72MHz。Start部分3:位于固件库目录“.\Libraries\CMSIS\CM3\CoreSupport”的两个文件。“core_cm3.h”、“core_cm3.c”是内核寄存器的描述文件,并且还带了一些内核的配置函数。
Library部分1:位于固件库目录“.\Libraries\STM32F10x_StdPeriph_Driver\src”。其中的misc.c是内核的库函数,其他的都是内核外的外设库函数。
Library部分2:位于固件库目录“.\Libraries\STM32F10x_StdPeriph_Driver\inc”。是上述库函数的头文件。
User部分1:存放用户编写的main.c等文件。 User部分2:位于固件库目录“.\Project\STM32F10x_StdPeriph_Template”中的三个文件。“stm32f10x_conf.h”用于配置库函数头文件的包含关系,并且也有用于参数检查的函数定义,所有的库函数都需要。“stm32f10x_it.h”、“stm32f10x_it.c”这两个文件用于存放中断函数。
要知道先在项目的文件夹里面从固件库复制所需的文件到各自分配的文件夹中,接着在keil里面添加文件,两者并不会自动同步
3.工程里对应建立Start、User、Library同名称的分组,然后将文件夹添加到工程分组里。
- Start分组:注意启动文件的选择,只能根据下表选择其中一个 .s文件
- User部分1:注意添加main.c文件时,路径要选上User文件夹,否则默认路径在文件外。下面是给出main.c文件中的代码:
#include "stm32f10x.h" // Device header
int main(void){
while(1){
}
}
//注意最后一行必须是空着
- User部分2:配置宏定义。要使“stm32f10x_con.h”被添加进来,而从使得所有的库函数定义生效,需要宏定义USE_STDPERIPH_DRIVER。右击“stm32f10x.h”滑到最下面,可以看见此条定义语句。打开“魔术棒”→C/C++→Define项目栏粘贴USE_STDPERIPH_DRIVER→OK"。
4.工程选项,C/C++,Include Paths内声明所有包含头文件的文件夹,否则软件找不到 .h文件。
- 点击魔术棒按钮→C/C++→Include Path →右侧的三个点按钮,将三个文件夹都添加进来。
5.要使用STLINK下载程序的话,需要在“魔术棒 → debug → use → ST-Link Debugger”,然后进一步点击右侧的“settings”,在第一个界面“debug”的port选择SW,在第三个界面“Flash Download”勾选Reset and Run”。
6.最后进行编译,通过。点击编译按钮右侧的“Download”按钮,便可以将程序下载在开发板上。
- 若报错,可以试一下点击魔法棒,target → ARMCompiler 选择V5.06。
- 注:为了防止乱码问题,可以在扳手工具那里选择UTF-8编码。
- 小技巧:点击“三个箱子”按钮,可以改变组函数顺序。
工程到目前为止搭建完成。库函数本质上也是间接配置寄存器,所以总体步骤和上面基于寄存器点灯相似。下面展示如何基于库函数,点亮LED,上面代码是基于寄存器实现,下面代码是基于库函数实现
#include "stm32f10x.h" // Device header
int main(void){
// //配置RCC寄存器,使能GPIOC的时钟。GPIO都属于APB2外设
// RCC->APB2ENR = 0x00000010;
// //配置寄存器PC13:通用推挽输出模式、输出模式50MHz
// GPIOC->CRH = 0x00300000;
// //输出数据寄存器PC13:
// //GPIOC->ODR = 0x00002000;//LED灭
// GPIOC->ODR = 0x00000000;//LED亮
//1.开启GPIO的外设时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
//2.配置寄存器PC13的端口模式
//2.1 首先配置GPIO结构体
GPIO_InitTypeDef GPIO_InitStructure ;//给结构体起名字
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//寄存器模式为通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;//寄存器引脚为13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度为50MHz
//2.2 然后才能调用函数配置寄存器
GPIO_Init(GPIOC,&GPIO_InitStructure);
//3.配置数据寄存器PC13的输出
GPIO_SetBits(GPIOC,GPIO_Pin_13);//设置高电平,灯灭
// GPIO_ResetBits(GPIOC,GPIO_Pin_13);//设置低电平,灯亮
while(1)
{}
}
二:截图操作实现
代码调用本质上就是一个User文件夹里面的main.c函数,其他的都是复制的,下面是上述操作细节。
三:main.c 大致代码实现
3.1 开启GPIO的外设时钟
选中这个函数,看这个函数定义,按F12进入右击或者点 GO TO Definition Of “xxx”
3.2 配置寄存器PC13的端口模式
//2.配置寄存器PC13的端口模式
//2.1 首先配置GPIO结构体
GPIO_InitTypeDef GPIO_InitStructure ;//给结构体起名字
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//寄存器模式为通用推挽输出
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;//寄存器引脚为13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度为50MHz
//2.2 然后才能调用函数配置寄存器
GPIO_Init(GPIOC,&GPIO_InitStructure);
3.2.1 首先配置GPIO结构体
按F12
芯片设计的模式,其中内部的001011信号已经由内部的电路决定,应用的话会调用“GPIO_Mode_Out_PP”就行
GPIO_Mode_AIN:模拟输入模式
GPIO_Mode_IN_FLOATING:浮空输入模式
GPIO_Mode_IPD:下拉输入模式
GPIO_Mode_IPU:上拉输入模式
GPIO_Mode_Out_OD:开漏输出模式
GPIO_Mode_Out_PP:推挽输出模式
GPIO_Mode_AF_OD:复用开漏输出模式
GPIO_Mode_AF_PP:复用推挽输出模式
问题:为什么GPIO_Mode_Out_PP = 0x10?
先是寄存器写法
这是库函数写法
两者放在一起看,
答案:
3.2.2 寄存器引脚
在注释里面按F12是跳转不了的,只能查找,注释内说GPIO_Pin这个参数被定义了
在GPIO_pins_define找被定义的PC13端口
3.2.3 输出速度为50MHz
同理可得
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//输出速度为50MHz
3.3 调用函数配置寄存器
GPIO_Init(GPIOC,&GPIO_InitStructure);
4.1 配置数据寄存器PC13的输出
GPIO_SetBits(GPIOC,GPIO_Pin_13);//设置高电平,灯灭
GPIO_ResetBits(GPIOC,GPIO_Pin_13);//设置低电平,灯亮
参考博主:【哈工大虎慕】