STM32单片机——GPIO外设 使用模块化编程与板级支持包的想法进行GPIO相关外设的构建
GPIO口配置步骤 GPIO口的初始化 在Drivers驱动中有stm32 hal库的相关文件,我们可以找到stm32f1xx_hal_gpio.c文件,查找初始化各个GPIO口的方法
1 2 3 4 5 6 7 8 9 10 11 __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_Init; GPIO_Init.Pin = ; GPIO_Init.Mode = ; GPIO_Init.Pull = ; GPIO_Init.Speed = ; HAL_GPIO_Init(GPIOA,&GPIO_Init);
GPIO_Init.Pin
GPIO_PIN_k(k∈[0,15])
激活引脚号
引脚编号
GPIO.Init.Mode
GPIO_MODE_INPUT
GPIO_MODE_OUTPUT_PP
GPIO_MODE_OUTPUT_OD
模式
输入模式
推挽输出
开漏输出
调控端口模式
从引脚读取数据
推挽输出的方式输出,控制一般外设用这个
开漏输出的方式输出,一般用于通信协议中?
GPIO_Init.Speed
GPIO_SPEED_FREQ_LOW
GPIO_SPEED_FREQ_MEDIUM
GPIO_SPEED_FREQ_HIGH
模式
低速
中速
高速
GPIO_Init.Pull
GPIO_NOPULL
GPIO_PULLUP
GPIO_PULLDOWN
模式
无上下拉
有上拉
有下拉
功能说明(用于输入模式时)
没有输入时,电平处于不稳定状态
没有输入时,处于高电平状态
没有输入时,处于低电平状态
GPIO口的读取
To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
1 2 3 4 5 6 7 8 9 10 HAL_GPIO_ReadPin(GPIOx,GPIO_Pin_x);
可以使用上述函数,读取调用此函数时对应引脚的电平状态
GPIO口写入
To set/reset the level of a pin configured in output mode use HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
可以使用上述两个函数给处于输出状态的端口写入值
方法一:写具体状态 1 void HAL_GPIO_WritePin (引脚字母GPIOx,引脚编号GPIO_PIN_x, 电平状态(GPIO_SET or GPIO_RESET))
GPIO_PinState 可以取
GPIO_RESET = 0 (低电平)
GPIO_SET = 1 (高电平)
方法二:反转电平状态 1 HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_12)
构建板级支持包 可以通过在工程存放的文件夹下,创建一个User的空间,用于存放各种外设。
用各个外设的名字来命名User的子文件夹,在子文件夹中存放.c and .h文件
记住:要将文件夹所在目录添加到#include配置中,然后可以用相对路径法索引.h文件
要把.c文件添加到工程(中的组——方便管理)中!!否则无法编译
第一个外设:二极管点亮 特点 引脚长的那一端接高电平,引脚短的那一端 接到低电平时,二极管会被点亮
二极管控制代码
LED_GPIO.h文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #ifndef __LED_GPIO_H_ #define __LED_GPIO_H_ #include "stm32f1xx_hal.h" #define LED_R_ON do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);}while(0) #define LED_R_OFF do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);}while(0) #define LED_R_CHANGE do{HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_1);}while(0) #define LED_B_ON do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_RESET);}while(0) #define LED_B_OFF do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_3,GPIO_PIN_SET);}while(0) #define LED_B_CHANGE do{HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_3);}while(0) #define LED_G_ON do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET);}while(0) #define LED_G_OFF do{HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET);}while(0) #define LED_G_CHANGE do{HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_4);}while(0) void LED_INIT (void ) ;#endif
LED_GPIO.c文件
1 2 3 4 5 6 7 8 9 10 11 12 13 #include "./LED/LED_GPIO.h" void LED_INIT (void ) { __HAL_RCC_GPIOA_CLK_ENABLE(); GPIO_InitTypeDef GPIO_Init; GPIO_Init.Pin = GPIO_PIN_1 | GPIO_PIN_3 |GPIO_PIN_4; GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init.Pull= GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA,&GPIO_Init); }
这样,我们在使用各种外设的时候就可以直接使用,而不需要
第二个外设:蜂鸣器 特点 在给I/O口低电平的时候,蜂鸣器会响起
蜂鸣器控制
bee.h文件
1 2 3 4 5 6 7 8 9 10 #ifndef __BEE_H_ #define __BEE_H_ #include "stm32f1xx_hal.h" void BEE_GPIO_INIT (void ) ; void BEE_CHANGE (void ) ; #endif
bee.c文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include "./BEE/bee.h" void BEE_GPIO_INIT (void ) { __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef GPIO_Init; GPIO_Init.Pin = GPIO_PIN_12; GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP; GPIO_Init.Pull= GPIO_NOPULL; GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB,&GPIO_Init); return ; } void BEE_CHANGE (void ) { HAL_GPIO_TogglePin(GPIOB,GPIO_PIN_12); return ; }
第三个外设:按键 特点 按键按下的时候会有抖动,由于连接方式,我们选择了将GND与端口相连,因此我们需要配置上拉输入模式,用来保持没有按下的时候读取的值为高电平,按下了之后读取的是低电平
每次检测到电平变化时(按下or松开导致的)时,需要Delay()一下,消除抖动
实质上:我在检测到电平变化的时候已经能够确定哪个按键被按下或者松开了 ,我还要delay而不是马上进行操作的原因就是防止按键带来的抖动对系统会造成的潜在影响,所以别急,先delay一下,也耽误不了多少时间
按键控制
key.h
1 2 3 4 5 6 7 8 9 #ifndef __KEY_H_ #define __KEY_H_ #include "stm32f1xx_hal.h" void KEY_GPIO_INIT (void ) ; uint8_t KEY_READ (void ) ; #endif
key.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include "./KEY/key.h" void KEY_GPIO_INIT (void ) { __HAL_RCC_GPIOB_CLK_ENABLE(); GPIO_InitTypeDef KEY_GPIO_Init; KEY_GPIO_Init.Mode = GPIO_MODE_INPUT; KEY_GPIO_Init.Pin = GPIO_PIN_0 | GPIO_PIN_1; KEY_GPIO_Init.Pull = GPIO_PULLUP; KEY_GPIO_Init.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB,&KEY_GPIO_Init); } uint8_t KEY_READ (void ) { if (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET){ HAL_Delay(20 ); while (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET); HAL_Delay(20 ); return 1 ; } else if (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET){ HAL_Delay(20 ); while (HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET); HAL_Delay(20 ); return 2 ; } return 0 ; }