STM32F103C8芯片学习日记(小白学习心得)- 标准库开发和固件函数库【1】
目录
【1】.标准库文件的添加与描述
1.启动文件的添加
2.时钟频率设置函数的添加
3.外围器件的寄存器地址库的添加
4.内核寄存器的设置
编辑5.标准库函数的添加
6.中断函数的添加
编辑7.库函数的包含函数添加
8.在编写程序时界面要引用的库
【2】GPIO的介绍与程序编写
1.配置外围器件的时钟
2.定义选择的GPIO的结构体
第一个成员变量:模式的选择。
【GPIO的模式解释】
【参数查找说明】
3.设置第二个成员变量:引脚的选择,上面我们提到一个GPIO有16个引脚,这里你就要选择使用哪个引脚,当然这里的引脚也可以进行或操作来同时选中多个引脚
4.设置第三个成员变量:设置所用时钟的频率(之前设置了打开外设的时钟,自然还要设置它的跑的速度),这里如果你对频率没有要求可以随便选一个填入;
5.将外设的结构体初始化,之前设置了结构的变量,还没有将结构体给它初始化;
3.GPIO的输入输出操作
1.GPIO_ReadInputDataBit()
2.GPIO_ReadInputData()
3.GPIO_ReadOutputDataBit()
4.GPIO_ReadOutputData()
5.状态标志位的命名规则
6.GPIO_SetBits()
7.GPIO_ResetBits
8.GPIO_WriteBit()
9.GPIO_Write()
10.GPIO_PinLockConfig()
4.程序编写部分和电路图连接
1.GPIO输出模式:
2.GPIO输入模式
【1】.标准库文件的添加与描述
1.启动文件的添加
要从这些启动文件中选择你所使用的启动文件,启动文件选择规则如下:
比如,我这里使用的STM32F103,Flash容量为64~128K;
那么就选择后缀名为MD的文件:startup_stm32f10x_md.c;
2.时钟频率设置函数的添加
比如系统的时钟和外围器件的时钟频率的设置就是使用这个函数。
3.外围器件的寄存器地址库的添加
4.内核寄存器的设置
5.标准库函数的添加
6.杂项固件库函数的添加
7.中断函数的添加
8.库函数的包含函数添加
这个函数包含上面了所有库的.h文件;
9.在编写程序时界面要引用的库
因为这个库里面有以下这个语句
#ifdef的语句作用:判断某个宏是否被定义,若已被定义,执行随后的语句
当有了宏定义#define USE_STDPERIPH_DRIVER时,就能包含如图中的库,上面我们知道这个库中包含了所有库的.h文件,引用这一个库就相当于引用了标准库要用到的所有库;
当然这个宏定义我们该怎么设置呢,就要点开魔术棒,然后点C\C++;
在如图的Preprocessor Symbols下的Define栏中输入USE_STDPERIPH_DRIVER;这个操作就相当于定义了一个预处理宏
【2】GPIO的介绍与程序编写
1.配置外围器件的时钟
当你要使用某个GPIO进行端口操作时,就必须要先给它配置时钟,STM32有GPIO类型(A~G),每个GPIO类型有16个端口,实际上不同类型芯片不一定有这么多GPIO的引脚,比如,GPIO资源,STC32F103C8T6芯片就只有GPIOA和GPIOB和(GPIOC的三个引脚),不同的芯片类型有哪些资源要看芯片的数据手册;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOX,ENABLE);
//第一个参数:
//RCC_APB2Periph_GPIOX:这个参数的可以改成A~G,比如RCC_APB2Periph_GPIOA
//第二个参数:
//ENABLE:这是开启时钟的参数;
//DISABLE:这是关闭时钟的参数;
这个芯片的RCC的时钟开启函数可以开启,AHB,APB2,APB1三个总线上的时钟,手册上说AHB到APB的桥连接了所有APB设备也就是挂载的外设资源,如图下
APB1和APB2之间的区别还有就是操作速度上面限度的不同
GPIO是挂载在APB2上的所以用RCC_APB2PeriphClockCmd()函数开启,如果你想知道具体的外设是挂载在哪个外设上的,这里可以从标准库的h文件查看,如下,点开标准库命名后缀为rcc的c文件,然后找到RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOX,ENABLE),这个函数,你在keil5上输入这个函数,一般keil5上面你输入一段代码后,会进行自动提示,如果没有可以点击ctrl+alt+空格进行操作,然后右键点击
自动跳转函数定义,然后看上面的参数说明,就能知道是否有这个外设资源了
这里可以同时开启多个外设的时钟,操作举例如下:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);
为什么进行可以或操作呢,这里可以看这个变量的定义:
比如RCC_APB2Periph_GPIOA的地址:
0x00000004即0000 0000 0000 0000 0000 0000 0000 0100
RCC_APB2Periph_GPIOB的地址:
0x00000008即0000 0000 0000 0000 0000 0000 0000 1000
将RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOA即
0x00000004 | 0x00000008
即 0x0000 000c,分开操作打开时钟和或操作后打开时钟最后达到的效果是一样的
都是 0x0000 000c;
2.定义选择的GPIO的结构体
1,这个变量可以自己随便填,一般写GPIO_InitStructure, 这样写变量含义比较明显,规范。
GPIO_InitTypeDef 变量名称;
举例:GPIO_InitTypeDef GPIO_InitStructure;
2.引出该结构的成员变量并且进行赋值,结构体其实内部就是存储了一堆可以是不同数据类型的变量和数组,你现在要先引出来这些变量,并且赋值,怎么引出来呢,这里格式就是:用上面定义的变量名 + . (点运算符) +成员变量;这里输入完点之后,这里会有个自动提示,没有的话快捷键ctrl+alt+空格就出来了,只要将这里面的成员变量全部引出来,并进行赋值;
第一个成员变量:模式的选择。
GPIO_InitStructure.GPIO_Mode= ;
举例:GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP ;
【GPIO的模式解释】
进行GPIO模式的选择,GPIO一般有八个模式可以选择:
当然这些变量也可以进行右键查找定义,不用死记硬背,以后敲得多了也自然就记住了,如果还没有,就在它下面的参数解释里面快捷键ctrl+f进行查询;
【参数查找说明】
以下图片进行说明:
如果输入ctril+f没有搜到,可能是这个变量在这个文件下没有,就要换成搜索整个工程
当然有时候会遇到这种:双击右键后弹出这个框框
那么你就双击里面的member,后面的操作就一样了
3.设置第二个成员变量:引脚的选择,上面我们提到一个GPIO有16个引脚,这里你就要选择使用哪个引脚,当然这里的引脚也可以进行或操作来同时选中多个引脚
GPIO_InitStructure.GPIO_Pin= ;
//举例:
//开启一个引脚:GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1;
//开启两个引脚:GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1 | GPIO_Pin_2;
4.设置第三个成员变量:设置所用时钟的频率(之前设置了打开外设的时钟,自然还要设置它的跑的速度),这里如果你对频率没有要求可以随便选一个填入;
//这里有三种时钟频率可以选择:
GPIO_Speed_10MHz;
GPIO_Speed_2MHz;
GPIO_Speed_50MHz;
//举例:GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
5.将外设的结构体初始化,之前设置了结构的变量,还没有将结构体给它初始化;
GPIO_Init(GPIOX,&GPIO_InitStructure);
//第一个参数X可以是A~G,比如GPIOA
//第二个参数是你之前定义的结构体变量的地址,格式:& 结构体变量
//举例:GPIO_Init(GPIOB,&GPIO_InitStructure);
下面是官方固件函数库手册对这个函数的说明,也就是说这个函数是用来初始化GPIO外设寄存器
3.GPIO的输入输出操作
在这个固件库中,STM32的一些常见数据类型,它将一些常见的数据类型都进行了typedef重命名的操作,因为这样可以使得它得书写更简洁了,也不至于输入一大串字符,这里对它的数据类型进行一个介绍,它的重命名都放在了stdint的函数库中,这里STM32的头文件库 "stm32f10x.h" 也对这些定义进行了重命名,也就是两种命名都可以进行变量数据类型的定义,一个字节有八位 ;
接下来就是进行GPIO的操作了,这里先介绍一下操作GPIO的几个函数:
1.GPIO_ReadInputDataBit()
这个函数的意思就是读取指定GPIO的某个引脚的电平,这个函数的第一个参数就是比如GPIOA或GPIOB这样格式的,第二个参数就是选择管脚,比如选择第一个管脚就是GPIO_Pin_1(这里的1可以换成0~15)
2.GPIO_ReadInputData()
这个函数是用来读取整个GPIOX(X可以是A~G)的输入值,即不是某一个端口,而是16个端口,所以返回的是16位即两个字节的数据;
3.GPIO_ReadOutputDataBit()
这个函数是指可以读取某个GPIO的某一个端口的输出,就是读取当前这个端口输出的是什么电平
4.GPIO_ReadOutputData()
这个函数是用来读取整个GPIOX(X可以是A~G)的输出值,即不是某一个端口,而是16个端口,所以返回的是16位即两个字节的数据;
5.状态标志位的命名规则
也就是说当这个端口状态为低电平时,一般写成RESET(重置状态);高电平写为SET(设置状态);
6.GPIO_SetBits()
这个函数是用来将GPIO的某个端口Pin设置为高电平状态(设置状态)
7.GPIO_ResetBits
这个函数是用来将GPIO的某个端口Pin设置为低电平状态(重置状态)
8.GPIO_WriteBit()
这个函数是将某GPIO的某个端口设置为高电平(设置状态)或者低电平(清除状态)
9.GPIO_Write()
这个函数就是对某个GPIOX(X:A~G)整个外设写入一个16位的数据即2个字节的数据
10.GPIO_PinLockConfig()
这个函数就可以将某个引脚的配置锁定,让它不能更改,在下一次系统复位之前不能更改这个引脚的配置了。
4.程序编写部分和电路图连接
1.GPIO输出模式:
GPIO为开漏输出模式,点亮led灯(将GPIO更换为推挽输出效果也是一样的,低电平驱动led点亮,只不过推挽输出的高低电平驱动能力都很强,开漏模式只有低电平驱动能力,就比如你在开漏模式输入高电平,STM32芯片内部这个引脚正处于高阻态,当这时候,如果你的外部电路有高电平流入时,这时高阻态的引脚就会受到影响变成高电平,所以一般开漏模式都是要接入一个上拉电阻才有高电平驱动能力)
#include "stm32f10x.h" // Device header
int main()
{
GPIO_InitTypeDef GPIO_InitSturcture;
GPIO_InitSturcture.GPIO_Mode=GPIO_Mode_Out_OD;
GPIO_InitSturcture.GPIO_Pin=GPIO_Pin_1;
GPIO_InitSturcture.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitSturcture);
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
引脚要设置为低电平,led灯才亮,因为它的阳极接入的电源也就是高电平,阴极要为低电平才能导通;
这里还可以试试GPIO的其他输出模式,比如GPIO_WriteBit(GPIOA,GPIO_Pin_1,Bit_RESET); 也能实现,到这里你就能输出一个引脚的高低电平了,多个引脚也是一样的,多写几个输出语句或这在函数里进行或运算,如果用不同的GPIO的引脚记得一定要进行初始配置;
2.GPIO输入模式
#include "stm32f10x.h" // Device header
#include "delay.h"
int main()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitSturcture1;
GPIO_InitTypeDef GPIO_InitSturcture2;
GPIO_InitSturcture1.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitSturcture1.GPIO_Pin=GPIO_Pin_1;
GPIO_InitSturcture1.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitSturcture2.GPIO_Mode=GPIO_Mode_IPU;
GPIO_InitSturcture2.GPIO_Pin=GPIO_Pin_6;
GPIO_InitSturcture2.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitSturcture1);
GPIO_Init(GPIOA,&GPIO_InitSturcture2);
GPIO_SetBits(GPIOA,GPIO_Pin_1); //初始化led熄灭
while(1)
{
if( (GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_6)) == RESET )
{
Delay_ms(20); //软件消抖
GPIO_ResetBits(GPIOA,GPIO_Pin_1);
}
}
}
我这里使用led的端口用的推挽输出,按键输入的端口用的上拉输入,默认高电平,当检测到低电平,执行点亮led;当然你也可以用浮空输入,当检测到低电平,执行点亮led;或者用下拉输入,默认输入低电平,这时就要把按键接入的地换成电源(高电平)了,然后当按键检测到高电平,执行点亮led;
作者:星空客