赞
踩
STM32的三种开发方式:
Libraries :库函数的文件,新建工程时会用到
Project:官方提供的工程示例和工程模板,在使用库函数时可以参考
Utilities:STM32官方评估板的相关例程,此文件存储测评程序
*评估板就是官方做的小电路板,用来测评STM32
Release_Notes:库函数的发布文档,有版本的说明
stm32f10x_stdperiph_lib_um:库函数的使用手册,教大家如何使用库函数
新建一个有关标准库的工程
新建一个文件夹,用来存储后续相关的工程
打开Keil
这里是新建文件夹,再把工程存在新建文件夹里
文件夹名是很容易更改的,所以可以在名称上起到说明的作用,工程名不方便更改
在新建工程设立的文件夹里开始搭配环境
这些是STM32的启动文件,STM32的程序就是从启动文件开始运行的
将上述文件粘贴至start里
改名
后面选择.c和.h文件都要选择进来
点击魔术棒,选择
新建一个main函数,打开工程文件夹,新建一个用来保存main函数文件夹,叫做user
操作main.c文件
- #include "stm32f10x.h" // Device header
-
- int main(void){
-
- while(1){
- }
-
- }
-
一定要在末尾多一行空格,否则程序就会报错
到目前为止没有添加过STM32的库函数,所以还是一个基于寄存器开发的工程,如果使用寄存器开发,那么工程建到这里就足够了
以下,是关于如何用配置寄存器的方式完成点灯操作
小tip:点击扳手图标,再选择ASM和C/C++编辑器用来调节字体,在Courier New里面选择字号
同样是扳手工具,选择UTF-8选项,可以防止中文乱码问题,打开别人的工程中文是乱码时也要修改这个编码格式
点击模式棒,选择调试器默认是ULINK,改为STLINK
只需配置三个寄存器就可以点灯了
寄存器①:RCC,用来使能GPIOC的时钟,GPIO都是APB2的外设,所以在这个APB2外设时钟使能寄存器RCC_APB2AENR里
可以看到这一位是使能GPIOC的时钟的,上面解释是这一位写1就是打开GPIOC的时钟
将整个寄存器的2进制转换为16进制,4个一分组就是00000010
RCC->APB2ENR = 0X00000010;
在keil里写入,这样可以打开GPIOC的时钟
寄存器②:配置PC13口的模式
可以看到CNF13和MODE13就是用来配置13号口的
同样换算成16进制是00300000
回到keil
GPIOC-> CRH = 0X00300000;
接下来要给PB13口输出数据了
ODR13写0就是低电平,写1就是高电平
这里需要高电平,所以是00002000
GPIOC—>ODR = 0X00002000;
灯是低电平点亮的,所以给ODR全是0便点亮,给ODR0X00002000就是灭
有个弊端是将除了PC13都设置成了0,会影响其他端口的原有配置,如果要做到只配置PC13而不影响其他端口,这还需要&=和|=的操作
所以
- #include "stm32f10x.h" // Device header
-
- int main(void){
- RCC->APB2ENR = 0X00000010;
- GPIOC->CRH = 0X03000000;
- GPIOC->ODR = 0X00000000;
-
- while(1){
- }
-
- }
此代码下,灯点亮
- #include "stm32f10x.h" // Device header
-
- int main(void){
- RCC->APB2ENR = 0X00000010;
- GPIOC->CRH = 0X03000000;
- GPIOC->ODR = 0X00002000;
-
- while(1){
- }
-
- }
此代码下,灯熄灭
以上是配置寄存器的点灯方式,这种方式需要不断地查手册来知道每个寄存器每一位是用来干什么的
接下来添加库函数
打开工程文件夹,再创立一个文件夹Library,用来存放库函数
这个misc是内核的库函数,其他的是内核外的外设库函数
全选复制到Library文件夹下
Ctrl + A 全选复制到Library文件夹下
回到keil软件,在Target1右键添加组改个名字叫Library
再右键加入已存在的Library文件,全选加入进去
这样便添加了所有库函数文件
但对于这个库函数来说,还不能直接使用,还需添加
这个conf(configuration)文件是用来配置库函数头文件包含关系的,还有所有函数都需要的用来参数检查的函数定义
两个it(interupt)文件是用来存放中断函数的
这三个文件需要复制下来,粘贴到user目录下
再回到keil软件在use组里把三个文件添加进来
最后,我们还需要一个宏定义
点击头文件右键,打开文件
划到最下面 看到这条语句,这是一个条件编译,意思是只有你定义了USE_STDPERIPH_DRIVER这个字串,下面这个stm32f10x_conf.h语句才会有效,所以需要复制下来USE_STDPERIPH_DRIVER,点击魔术棒按钮再到C/C++,粘贴到define这栏
这样才能包含标准外设库,也就是库函数
还有头文件路径,点击Include Paths
加入user和Library
这样基于库函数的工程已经建立好了
Library组的文件也全都带了钥匙,不需要我们修改,唯一需要我们修改的是user组里的文件
可以点三个箱子的图标,把Library往上挪,让页面看起来整齐一些
接下来使用库函数来实现点灯操作
首先是使能时钟,库函数有这样一个函数来开启时钟
RCC_APB2PeriphClockCmd,接下来提示两个参数,第一个是选择外设,第二个是选择新的状态
可以点击右键跳转到函数定义*这里一开始无法跳转,因为没有编译一直显示no browse
这上面有函数的简介和参数说明
简介说,这个函数是用来使能或者失能APB2外设时钟,第一个参数可以是下面的这些值,可以找到APB2外设GPIOC这一项,然后复制作为第一个参数即可,在看第二个参数,NewState的值可以是ENABLE或者DISABLE,那我们复制ENABLE放在第二个参数的位置
这样GPIOC的外设时钟就配置好了
可以看到这个函数,它的内部其实还是配置RCC_APB2ENR这个寄存器,但是经过函数的包装,不需要再去查手册,去确认哪一位是干什么 ,而且这里应用了&=和|=来操作,所以这个库函数配置是不会影响到寄存器的其他位的
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
这个代码虽然比寄存器长,但是语义更加明确其,也不需要查表计算值,只需要调用库函数,按照它的提示,把参数填好就行了
2.接下来是配置端口模式,我们需要用到GPIO_Init这个函数
两个参数,选择哪个GPIO和参数的结构体(这里用到了结构体配置参数)
首先还是去到函数的定义
是PC13口的LED,所以第一个参数就写GPIOC,第二个参数是一个GPIO_InitTypeDef的结构体,首先需定义一个结构体,先把结构体的类型写上GPIO_InitTypeDef,这个名字可以随便起,但根据官方推荐最好叫作GPIO_InitStructure,然后把结构体的每个参数写上,复制粘贴结构体的名字,然后用点 . 来引出结构体的参数,先把参数罗列出来,可以看到结构体有三个参数,分别是GPIO模式、GPIO端口、GPIO速度
右键转到Mode的定义
右边介绍说,参数可以是GPIOMode_TypeDef里面的一个值
注释里的内容无法右键跳转了,所以可以选中GPIOMode_TypeDef这个字符,按下Ctrl+F,搜索这个定义的位置点击Find Next,可以看到这是个枚举
选择GPIO_Mode_Out_PP这一项复制,这一项就是通用推挽输出
回来,点击下一个Pin
出现的这个框代表,可以跳转的定义有很多
选择member这一项双击跳转,还是刚刚那个位置,选中Ctrl+F、Find Next然后跳转,这里是个宏定义的列表
选中GPIO_Pin_13复制,填在第二个位置上
第三个参数也是一样,跳转定义,选中,Ctrl+F、Find Next,选中GPIO_Speed_50MHz复制,填在第三个参数上
这样结构体变量就有了,就可以填写GPIO_Init的第二个参数了
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
可以回到之前的定义里说明,第二个参数是指向结构体的指针,所以这里需要传输结构体的地址
复制结构体的名字,加上&取地址,&GPIO_InitStructure作为第二个参数
最后来设置端口的高低电平来进行点灯,这里有个函数GPIO_SetBits这个就可以把指定端口设置为高电平
也有函数将端口配置为低电平,GPIO_ResetBits,参数与SetBits一样,GPIO_ResetBits(GPIOC, GPIO_Pin_13);这句便可将PC13号端口设置为低电平
整个代码是
- #include "stm32f10x.h" // Device header
-
- int main(void){
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- //GPIO_SetBits(GPIOC, GPIO_Pin_13);
- GPIO_ResetBits(GPIOC, GPIO_Pin_13);
- while(1){
- }
- }
-
灯亮
- #include "stm32f10x.h" // Device header
-
- int main(void){
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
- GPIO_InitTypeDef GPIO_InitStructure;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
- GPIO_Init(GPIOC, &GPIO_InitStructure);
- GPIO_SetBits(GPIOC, GPIO_Pin_13);
- //GPIO_ResetBits(GPIOC, GPIO_Pin_13);
- while(1){
- }
- }
-
灯灭
以上是学习库函数的基本操作
新建工程里启动文件的选择
新建工程一个要添加的就是启动文件,启动文件有很多类型,至于选择哪个,需要根据芯片的型号来确定
如何判断?当选择STM32F100的产品时,就选择带VL的启动文件,然后再根据Flash的大小来确定LD、MD、HD、XL
当选择STM32F101/102/103的型号,就选择不带VL的启动文件,根据Flash的大小来确定LD、MD、HD、XL
当选择STM32F105/107的型号,就直接选择CL即可
eg:用到的STM32F103C8T6是F103,直接看LD、MD、HD、XL,可知C8T6是64K的Flash,所以选择后缀带有md的启动文件
这就是STM32F10系列的型号分类和启动文件选取
总结新建工程的顺序
工程架构
首先start up启动文件,这个是程序执行最基本的文件
keil中启动文件是用汇编写的,启动文件内部定义了中断向量表、中断服务函数等,中断服务函数中有一个复位中断,这是整个程序的入口
当STM32上电复位或者按下复位键时,程序就会进入复位中断函数的执行,复位中断函数主要做两件事情,一个是调用SystemInit函数,第二个是调用main函数,对应启动文件这里
然后程序就结束了,事实上单片机由于while的循环程序永远不会结束
SystemInit的文件就是定义在这个system_xx.c/.h文件里的
可以在keil中看到这个函数的定义,brief简介中写了函数的作用,是设置微控制处理器的启动,初始化嵌入式闪存接口、锁相环、更新系统内核的时钟变量,note写得是这个函数仅在复位后需要调用
下面这些是用来配置这些东西的,不需要修改,在main函数之前,单片机已经执行了一堆东西了,帮把这个闪存接口、时钟等一系列杂碎的东西都配置好了
另外在启动文件还定义了STM32所有的其他中断,这些中断达到条件后会自动执行
启动文件下面就是其他文件的中断调用了 ,这个中断函数定义就是在stm32fx_it里面
打开keil可以看到中断函数的定义
ST还建议我们将中断写在这个位置,当然我们还是习惯在哪里用就写在哪里 这些就是中断部分的执行逻辑了,另外可以自己定义一些用户文件,来封装一些模块来供主函数和模块中断调用,这有利于我们程序结构模块化,不然所有结构都堆在主函数里面,主函数会非常长
*目前我还不明白封装具体用法和整体概念
以上是工程主动执行部分内容,剩下的是被动执行的东西了,相当于STM32的资源
在主函数或者中断函数里面就可以调用这些资源
右上角是stm32f10x.h和core_cm3.c / .h分别是外设寄存器描述内核寄存器描述
打开keil可以看到
寄存器和寄存器每一位的名字和对应的地址信息,直接调用寄存器来使用STM32(有些麻烦),这是寄存器的开发方式
所以ST公司提供了库函数文件misc.c / .h、stm32f10x_adc.c / .h库函数
在keil中可以看到,每个外设都提供有一大堆函数,这些函数封装了寄存器的操作,提供了函数调用的方式
stm32f10x_conf.h库函数配置这个conf文件就是用来配置头文件的包含关系的
可以看到conf文件include所有库函数的头文件
同时在是stm32f10x.h最后又包含了stm32f10x_conf.h,所以在使用这些库函数是只需要包括stm32f10x.h这一个头文件即可,就相当于包含了所有库函数的头文件,这样我们就可以任意调用库函数了
这些就是工程的结构和每个文件的作用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。