stm32入门-----GPIO口输出的学习与使用(下)
目录
前言
一、创建工程
二、时钟和GPIO口
1.RCC时钟
2.GPIO引脚
3.void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
4.void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
5.void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
三、项目实践
1.实现一个LED呼吸灯
2.实现LED流水灯
3.控制蜂鸣器响应
前言
本期紧接着上一期的内容,是对上一期的理论进行代码编写操作,也是对GPIO口进行输出功能的实践,本期分为三个项目,分别是一个LED呼吸灯,8个LED流水灯、控制蜂鸣器的响应。(本文章内容是跟着江大科协一起做的,对应的视频内容:[3-2] LED闪烁&LED流水灯&蜂鸣器_哔哩哔哩_bilibili)
一、创建工程
相较于51单片机,stm32创建工程相对比较麻烦的,细节是比较多的,因为不想51那样创建好了工程就可以去之间写代码了,stm32的需要引入相关文件,也就是前置文件。不过总体上还是差不多的。
老规矩,打开keil5新建工程,选择芯片。这里学过51的就不多说了,stm32也是一样的。
下面这个点击叉掉就行了
然后就是打开你这个工程文件的根目录下,然后去创建三个文件夹,分别是:user、start、library
然后就是去找固键库里面的文件复制粘贴进去,详细可看这里(STM32的工程模版创建(保姆级教程)_stm32工程模板-CSDN博客)
不过我这里的话就已经提前准备好了这三个文件夹里面的文件了,这里我会上传到本期的资源绑定上,你们可以去直接下载拿过来复制粘贴到你这个工程上就行了,到时候就不需要这么麻烦。解压后如下图:
然后就在Groups这里去添加这三个文件夹到本工程上,注意user最好放到最下面,方便去使用。
添加好了文件夹之后,就点击右边去添加相关的文件,比如我这里是给start这个文件夹去添加文件,那我下面这里就点击进入到start这个文件夹里面,然后选择全部(包括.c和.h文件),去添加就行了。
其他两个也是一样的,直接去添加就行了。
最后添加完成了,你会看到这个工程的左边会出现上面你添加好了的文件夹
还没完这里,点击魔术棒,然后选到C/C++这里。
然后就是点击下面箭头指向的位置,把这三个文件夹添加上去就行了。
后面回到原来的界面箭头指向的位置去填入USE_STDPERIPH_DRIVER,最后点击OK就行了。
不过到这里还没完,前置文件是添加好了,还有就是去设置keil5的环境。
老规矩,点击魔术棒。
然后点击下面箭头指向的位置,第一点击Debug,第二选择ST-Link Debugger。
进去之后点击 Debug,就按照下面箭头指向的位置选择即可。
最后一步就是点击Flash Download,然后勾选Reset and Run,就每次下载到stm32单片机后就继续复位操作。
最后就是点击确定,点击OK就行了,没毛病。工程创建完成。
二、时钟和GPIO口
(下面相关内容来自:STM32标准库常用函数的使用和代码说明_stm32标准库函数手册-CSDN博客)本期引用了要用的函数进行解释说明,详细可查阅链接的内容或者去查看手册。
1.RCC时钟
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState);
RCC APB2外设时钟控制,使能或者失能APB2外设时钟。
功能:
- 第一个参数选择外设,下图是可选择的外设。
- 第二个参数使能或使能。
在STM32中,所有的GPIO都是挂载在APB2外设总线上的,所以要给PA0端口低电平点亮LED,需要给RCC_APB2外设时钟使能,第一个参数就选择RCC_APB2Periph_GPIOA,第二个参数为ENABLE。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //将APB2总线上挂着的外设GPIOA时钟打开
RCC时钟不止这一个,其他我这里就没去讲了,不过一般情况下用到的RCC时钟也就只有三个。
2.GPIO引脚
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
这个函数的作用是,用结构体的参数来初始化GPIO口。
我们需要先定义一个结构体变量,然后再给结构体赋值,最后调用这个函数,这个函数内部就会自动读取结构体的值,然后自动把外设的各个参数配置好。
第一个参数是要初始化的GPIO口,第二个参数是一个结构体。
GPIO_InitTypeDef GPIO_InitStructure; //定义结构体变量 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //GPIO模式选择 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; //GPIO引脚选择 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //GPIO传输速度选择 GPIO_Init(GPIOA, &GPIO_InitStructure); //调用Init函数
这里的结构体就是一个数据打包的过程,首先将参数写到结构体的三个变量里,然后统一打包,将结构体传递到初始化函数里,接着在初始化函数里面,再把这个结构体拆包出来,读取变量,这就是使用结构体的整个过程。
第一行中GPIO_InitTypeDef是结构体的类型,GPIO_InitStructure是结构体的名字,这里结构体实际上也是一种局部变量。
在第二行,复制结构体名字,然后用“.”把结构体的成员都引出来;
通过在GPIO_Mode右键跳转,可以看到参数说明,在参数GPIOMode_TypeDef选中,Ctrl+F搜索一下,就能看到GPIO的8种工作模式,这里我们选择GPIO_Mode_Out_PP推挽输出模式。
GPIO_Mode_AIN = 0x0, //模拟输入 GPIO_Mode_IN_FLOATING = 0x04, //浮空输入 GPIO_Mode_IPD = 0x28, //下拉输入 GPIO_Mode_IPU = 0x48, //上拉输入 GPIO_Mode_Out_OD = 0x14, //开漏输出 GPIO_Mode_Out_PP = 0x10, //推挽输出 GPIO_Mode_AF_OD = 0x1C, //复用开漏 GPIO_Mode_AF_PP = 0x18 //复用推挽
第三行引脚选择,通过在GPIO_Pin右键跳转,在选中GPIO_pins_define 参数处Ctrl+F搜索,就能找到引脚定义,这里我们用的是GPIOA外设的0号引脚,所以选择GPIO_Pin_0。
第四行同理,能找到引脚的输出速度定义,这里我们选则50MHz即可。
第5行就是调用GPIO_Init函数,然后第一个参数写GPIOA,然后GPIO初始化结构体的地址放到GPIO_Init的第二个参数,这样初始化就完成了,GPIO_Init函数执行完,这个GPIOA外设的0号引脚就自动被配置为推挽输出,50MHz的速度了。接下来就可以使用GPIO的这些输入输出函数了。
3.void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
这个函数可以把指定的端口设置为高电平。
第一个参数是GPIOx,第二个参数是GPIO_Pin。
GPIO_SetBits(GPIOA, GPIO_Pin_0); //将PA0口设置为高电平
4.void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
这个函数可以把指定的端口设置为低电平。
第一个参数是GPIOx,第二个参数是GPIO_Pin。
GPIO_ResetBits(GPIOA, GPIO_Pin_0); //将PA0口设置为低电平
5.void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);
前两个参数都是指定端口,第三个参数是BitVal,根据第三个参数的值来设置指定端口。
第三个参数:
Bit_RESET:清除端口值,也就是置低电平;
Bit_SET:设置端口值,也就是置高电平。
GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET); //给GPIOA中的0号引脚写入低电平(点亮LED)
想了解具体底层的话可自己查阅手册。 下面要用到的就是上面这些内容了。
三、项目实践
1.实现一个LED呼吸灯
这里的话要用到延时函数,所以这里需要在根目录下去创建一个system文件夹,然后把延时函数的文件跟导入进去。
面包板上的连线图:
main.c代码:
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { //设置时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); //定义结构体 GPIO_InitTypeDef GPIO_initstruct; //配置结构体的输入输出方式 8种之一 GPIO_initstruct.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式,高低电平都可以输出来,且有效 //配置选定的引脚IO口 GPIO_initstruct.GPIO_Pin=GPIO_Pin_0; //设置频率 多少hz GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz; //把上面定义好的结构体地址带入进行初始化设置 指定到GPIOA 口 GPIO_Init(GPIOA,&GPIO_initstruct); /* 说明: GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_RESET);与GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_SET);是一一对应的 GPIO_ResetBits(GPIOA, GPIO_Pin_0);与GPIO_SetBits(GPIOA, GPIO_Pin_0);也是一一对应的 上面两个前者是控制输出低电平,后者是控制输出高电平,效果是一样的 */ while(1){ //点亮LED,低电平亮 //GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_RESET); GPIO_ResetBits(GPIOA, GPIO_Pin_0); Delay_ms(100); //延时100毫秒 //熄灭LED //GPIO_WriteBit(GPIOA, GPIO_Pin_0,Bit_SET); GPIO_SetBits(GPIOA, GPIO_Pin_0); Delay_ms(100);//延时100毫秒 } }
2.实现LED流水灯
面包板上的连线图:
这里我选择的是GPIOA 口 0~7的引脚,其对应的位置下图所示:
main.c代码:
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { //打开GPIO指定的端口,这里打开GPIOA的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); GPIO_InitTypeDef GPIO_initstruct; //定义结构体 //配置结构体的输入输出方式 8种之一 GPIO_initstruct.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式,高低电平都可以输出来,且有效 //配置选定的引脚IO口 GPIO_initstruct.GPIO_Pin=GPIO_Pin_All ; //设置频率 多少hz GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz; //把上面定义好的结构体地址带入进行初始化设置 指定到GPIO A 口 GPIO_Init(GPIOA,&GPIO_initstruct); while(1){ //点亮LED,低电平亮 GPIO_Write(GPIOA,~0x0001); Delay_ms(200); GPIO_Write(GPIOA,~0x0002); Delay_ms(200); GPIO_Write(GPIOA,~0x0004); Delay_ms(200); GPIO_Write(GPIOA,~0x0008); Delay_ms(200); GPIO_Write(GPIOA,~0x0010); Delay_ms(200); GPIO_Write(GPIOA,~0x0020); Delay_ms(200); GPIO_Write(GPIOA,~0x0040); Delay_ms(200); GPIO_Write(GPIOA,~0x0080); Delay_ms(200); } }
3.控制蜂鸣器响应
面包板上的连线图:
这里要用到无源蜂鸣器模块 ,相关介绍如下。
无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音
main.c代码:
#include "stm32f10x.h" // Device header #include "Delay.h" int main(void) { //打开GPIO指定的端口,这里打开GPIOA的时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); GPIO_InitTypeDef GPIO_initstruct; //先定义结构体 //配置结构体的输入输出方式 8种之一 GPIO_initstruct.GPIO_Mode=GPIO_Mode_Out_PP; //推挽输出模式,高低电平都可以输出来,且有效 //配置选定的引脚IO口 GPIO_initstruct.GPIO_Pin=GPIO_Pin_12 ; //设置频率 多少hz GPIO_initstruct.GPIO_Speed=GPIO_Speed_50MHz; //把上面定义好的结构体地址带入进行初始化设置 指定到GPIOB 口 GPIO_Init(GPIOB,&GPIO_initstruct); while(1){ GPIO_ResetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_ResetBits(GPIOB, GPIO_Pin_12); Delay_ms(100); GPIO_SetBits(GPIOB, GPIO_Pin_12); Delay_ms(700); } }
以上就是本期的全部内容了,我们下次见!
每日壁纸: