跑马灯实验:库函数版本
参考资料:
阿波罗STM32F429开发板:
《STM32F429开发指南-HAL库版本》-第六章跑马灯实验6.1小节
ST官方资料:
《STM32F4xx中文参考手册》-第7章通用IO笔记基于正点原子官方视频
视频连接https://www.bilibili.com/video/BV1Wx411d7wT?p=71&spm_id_from=333.1007.top_right_bar_window_history.content.click
如有侵权,联系删除
一、跑马灯硬件连接
- GPIO输出方式:推挽输出(上拉)
- LED灯共阳极接法,即端口输出1不亮,输出0亮
- 操作的两引脚为PB0、PB1
1.推挽输出
可以输出强高低电平,连接数字器件
2.开漏输出
只可以输出强低电平,高电平得靠外部电阻拉高。输出端相当于三极管的集电极. 要得到高电平状态需要上拉电阻才行. 适合于做电流型的驱动,其吸收电流的能力相对强(一般20ma以内)
二、GPIO相关库函数说明
1.GPIO操作HAL库函数分布文件:
头文件:stm32f4xx_gpio.h
源文件:stm32f4xx_gpio.c
重要函数:
1个初始化函数:
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
1个读取输入电平函数:
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
1个设置输出电平函数:
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState);
1个电平翻转函数:
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
1个引脚电平锁定函数:
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
2个外部中断相关函数:现在先不讲解
2.重要库函数介绍
1.初始化函数
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
- 作用:初始化
一个或者多个IO口
(同一组)的工作模式,输出类型,速度以及上下拉方 式。
也就是一组IO口的4个配置寄存器。
(GPIOx->MODER, GPIOx->OSPEEDR,GPIOx->OTYPER,GPIOx->PUPDR) - GPIO_Init函数初始化样例:
GPIO_InitTypeDef GPIO_Initure;
GPIO_Initure.Pin=GPIO_PIN_0|GPIO_PIN_1; //PB1,0
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_HIGH; //高速
HAL_GPIO_Init(GPIOB,&GPIO_Initure)
可以一次初始化一个IO组下的多个IO,前提是这些IO口的配置方式一样。
2.读取输入电平函数
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 作用:读取某个GPIO的输入电平。实际操作的是GPIOx_IDR寄存器。
- 例如:
GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5); //读取GPIOA.5的输入电平
3.设置引脚输出电平函数
void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin,
GPIO_PinState PinState);
- 例如:
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //RESET 低电平;SET高电平
4.输出电平翻转函数
void HAL_GPIO_TogglePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
- 例如:
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_1);
三、跑马灯实验
配置HAL库操作IO口步骤
- 初始化HAL库:HAL_Init();
- 初始化系统时钟 :Stm32_Clock_Init( );
- 使能IO口时钟。
操作寄存器:配置IO口时钟使能寄存器: RCC->AHB1ENR
HAL库方法:__HAL_RCC_GPIOB_CLK_ENABLE(); - 初始化IO口模式。
操作寄存器:GPIOx_MODER OTYPER OSPEEDR PUPDR
HAL库方法:HAL_GPIO_Init(); - 操作IO口,输出高低电平。
操作寄存器:配置寄存器GPIOX_ODR或者GPIOx_BSRR 。
HAL库方法:HAL_GPIO_WritePin();
1.main主函数
打开HAL库模板,把主函数main.c文件夹清理成下图所示
2.初始化HAL库:HAL_Init();
3.初始化系统时钟:STM32F429: Stm32_Clock_Init(360,25,2,8);
4.使能IO口时钟:__HAL_RCC_GPIOB_CLK_ENABLE();
5.初始化IO口模式 - HAL库方法:HAL_GPIO_Init();
- GPIO输出方式:推挽输出(上拉)
这里我们要调用HAL_GPIO_Init();函数,在文件中位置如下
语句:void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init);
可见HAL_GPIO_Init();中有两组数据,数据类型为:GPIO_TypeDef和GPIO_InitTypeDef
*GPIOx和 *GPIO_Init为两组变量,前面*号则说明类型为指针类型
1.下面定义HAL_GPIO_Init();
(1). 下面查看void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef GPIO_Init);中GPIOx有哪些变量名
选中HAL_GPIO_Init右键点击查看定义
打开页面如下
同样,可以看到有IS_GPIO_ALL_INSTANCE(GPIOx),说明IS_GPIO_ALL_INSTANCE中有定义了变量名,选中IS_GPIO_ALL_INSTANCE右键产看定义
打开界面如下,可以看到里面可以(定义了)调用变量,名有GPIOA、GPIOB 、···、GPIOK,这里我们需要使用GPIOB
(2).下面查看void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef GPIO_Init);中GPIO_Init有哪些变量名
同样打开GPIO_InitTypeDef的定义,如下图
可以看到类型是结构体,有下面5个类型,也就是说要对这五个类型逐一设置。
因为*GPIO_Init中有多个数据,我们在设置的时候要定义一个变量,然后令变量等于这些数据,最后在初始化函数中引入一个指针,让指针指向这个变量(即指向这些数据)就可以了
这一段代码为:
2.接下来就要对结构体函数(即变量GPIO_InitStructure)进行初始化
写入代码GPIO_InitStructure. 这里GPIO_InitStructure后面加个“ . ”是定义GPIO_InitStructure里的子变量,在弹出的小窗口中可见有五组数据(Alternate、Mode、Pin、Pull、Speed)需要设置
里面GPIO_InitStructure.Alternate是关于串口复用的,这里可以不定义(使用默认设定)
下面定义GPIO_InitStructure.Mode,这指GPIO的模式
查看Mode下有哪些变量
打开如下
这里我们使用推挽输出,即使用变量名GPIO_MODE_OUTPUT_PP
即定义GPIO_InitStructure.Mode为推完输出代码如下:
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP;
**下面定义GPIO_InitStructure.Pin **
按上面同样方式打开Pin定义如下,发现还有一层变量定义,继续打开
发现Pin可以定义的变量如下:
这里我们定义GPIO_PIN_0 代码如下:
GPIO_InitStructure.Pin=GPIO_PIN_0;
下面定义GPIO_InitStructure.Pull
打开Pull定义如下:有三个选项
这里设置上拉模式,代码如下:
GPIO_InitStructure.Pull=GPIO_PULLUP;
下面定义GPIO_InitStructure.Speed
打开Speed定义如下:
这里设置高速,代码如下:
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;
设置PB1
到这里PB0设置好了,因为PB1和PB0一样的模式,在Pin设置时加入或运算即可,代码如下
GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1;
于是初始化IO口的代码可以写为:
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个变量GPIO_InitStructure
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //初始化系统时钟
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能PB时钟
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; //定义PB0 PB1引脚
GPIO_InitStructure.Pull=GPIO_PULLUP; //上拉模式
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速模式
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIOB:初始化PB口
//&GPIO_InitStructure:结构体指针指向变量GPIO_InitStructure
}
6.操作IO口,输出高低电平
这里我们可以用函数HAL_GPIO_WritePin();来写
其定义如下
通过打开定义
的方式可以查看 GPIOx、 GPIO_Pin、 PinState,三个变量的定义名
这里就不打开了,直接写代码如下
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //写PB0口低电平
7.引入延时函数
Stm32_Clock_Init(360,25,2,8); //初始化系统时钟
delay_init(180); //延时函数初始化,一个循环1ms
延时函数
delay_ms(500); //延时500ms
delay_us(500); //延时500us
8.主函数所有代码
#include "sys.h"
#include "delay.h"
#include "usart.h"
int main(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //定义一个变量GPIO_InitStructure
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //初始化系统时钟
delay_init(180); //初始化延时函数
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能PB时钟
GPIO_InitStructure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitStructure.Pin=GPIO_PIN_0 | GPIO_PIN_1; //定义PB0 PB1引脚
GPIO_InitStructure.Pull=GPIO_PULLUP; //上拉模式
GPIO_InitStructure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //高速模式
HAL_GPIO_Init(GPIOB,&GPIO_InitStructure); //GPIOB:初始化PB口
//&GPIO_InitStructure:结构体指针指向变量GPIO_InitStructure
while(1)
{
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET); //写PB0口低电平
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET); //写PB1口高电平
delay_ms(500);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET); //写PB0口低电平
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET); //写PB1口高电平
delay_ms(500);
}
}