快速入门STM32 G431 HAL库开发——GPIO输入与按键检测

一、GPIO常用的函数

1.HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)——用于读取指定GPIO引脚的电平状态。
2.HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)——手动写入GPIO引脚的高低电平。
3.HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)——用于切换指定GPIO引脚的电平状态。

二、按键官方原理图

三、配置STM32cubeMX

根据按键官方原理图:PB0控制B1按键
PB1控制B2按键
PB2控制B3按键
PA0控制B4按键
将这四个口配置为GPIO输入模式

GPIO输入口配置为上拉模式。

在很多情况下,当GPIO配置为输入模式并且没有连接任何输入信号时,该端口的状态是不确定的。也就是说,如果输入没有被拉高到VCC或拉低到GND,端口可能会随着环境噪声或电气干扰而随机地改变状态。这种状态被称为浮空状态(floating state),它可能导致不可预测的行为,特别是在数字逻辑电路中。为了避免这种情况,可以配置内部的上拉(pull-up)或下拉(pull-down)电阻器。上拉模式意味着内部电阻将GPIO端口拉高到VCC,确保在没有外部信号时,端口状态为高;下拉模式则意味着内部电阻将GPIO端口拉低到GND,确保端口状态为低。

上拉电阻是为了保证在没有信号输入的时候,IO口保持高电平,若按键为低电平有效,则没有信号的时候,IO应呈现高电平,所以,此处应设置为上拉输入。
同理,下拉电阻是为了保证在没有信号输入的时候,IO口保持低电平,若按键为高电平有效,则没有信号的时候,IO应呈现低电平。

四、按键控制LED亮与灭

实验现象:按下B1按键,LED1亮!按下B2按键,LED1灭!
按下B3按键,LED2亮!按下B4按键,LED2灭!
1.创建key.c和key.h文件,将其分别放入Src跟Inc文件中,与第一篇文章中代码封装的步骤一致。
2.编写key.c中代码

#include "key.h"
#include "main.h"
#include "led.h"

void key()
{
	//按下B1键 led1灯亮
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==RESET)//B1按下为低电平
	{
		HAL_Delay(5);//防抖动
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==RESET)//延迟消抖
		{
			//写功能
			led(1,1);
		}
		// 等待按键松开,按键松开之前程序一直卡在while循环里,按键松开之后才能处理其他的程序。
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==RESET);
	}
	//按下B2键,led1灯灭
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==RESET)//B2按下为低电平
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==RESET)
		{
			//写功能
			led(1,0);
		}
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==RESET);
	}
	//按下B3键,led2灯亮
	if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==RESET)//B3按下为低电平
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==RESET)
		{
			//写功能
			led(2,1);
		}
		while(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==RESET);
	}
	//按下B4键,led2灯灭
	if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==RESET)//B4按下为低电平
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==RESET)
		{
			//写功能
			led(2,0);
		}
		while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==RESET);
	}
}

3.在key.h中

void key(void);

4.在main.c中

5.在main.c while(1)中调用函数功能

五、key函数的封装

#define  KEY_STATE		GPIO_PIN_RESET
#define  KEY_UNSTATE		GPIO_PIN_SET

#define  KEY1_GPIO	GPIOB
#define  KEY1_PIN		GPIO_PIN_1

#define  KEY2_GPIO	GPIOA
#define  KEY2_PIN		GPIO_PIN_7

#define  KEY3_GPIO	GPIOA
#define  KEY3_PIN		GPIO_PIN_5

#define  KEY4_GPIO	GPIOA
#define  KEY4_PIN		GPIO_PIN_3

int keynum()
{
	int KeyNum=0;
	if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_PIN)==KEY_STATE)
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_PIN)==KEY_STATE)
		{
			KeyNum=1;

		}
		while(HAL_GPIO_ReadPin(KEY1_GPIO,KEY1_PIN)==KEY_STATE);
	}

	if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_PIN)==KEY_STATE)
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_PIN)==KEY_STATE)
		{

			KeyNum=2;

		}
		while(HAL_GPIO_ReadPin(KEY2_GPIO,KEY2_PIN)==KEY_STATE);
	}

	if(HAL_GPIO_ReadPin(KEY3_GPIO,KEY3_PIN)==KEY_STATE)
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(KEY3_GPIO,KEY3_PIN)==KEY_STATE)
		{

			KeyNum=3;

		}
		while(HAL_GPIO_ReadPin(KEY3_GPIO,KEY3_PIN)==KEY_STATE);
	}
	
	if(HAL_GPIO_ReadPin(KEY4_GPIO,KEY4_PIN)==KEY_STATE)
	{
		HAL_Delay(5);
		if(HAL_GPIO_ReadPin(KEY4_GPIO,KEY4_PIN)==KEY_STATE)
		{

			KeyNum=4;

		}
		while(HAL_GPIO_ReadPin(KEY4_GPIO,KEY4_PIN)==KEY_STATE);
	}


	return KeyNum;
}

注意事项:在函数调用的时候,一定要先写int key=keynum();再做判断!

实例:

void keyTask(void *argument)
{
	while(1)
	{
		int key=keynum();
		if( key== 1 )
		{/* K2 被按下 */
		  printf("恢复LED任务!\r\n");
		  vTaskResume(xledTaskHandle);/* 恢复LED任务! */
		  printf("恢复LED任务成功!\r\n");
		}
		if( key== 2 )
		{/* K1 被按下 */
		  printf("挂起LED任务!\r\n");
		  vTaskSuspend(xledTaskHandle);/* 挂起LED任务 */
		  printf("挂起LED任务成功!\r\n");
		} 
		vTaskDelay(20);/* 延时20个tick */
	}
}

作者:Comedy_宁

物联沃分享整理
物联沃-IOTWORD物联网 » 快速入门STM32 G431 HAL库开发——GPIO输入与按键检测

发表评论