STM32学习·HAL库速通篇(五)·GPIO输入与按键控制LED灯开关

目录
1. GPIO 概述
GPIO(General Purpose Input Output)即通用输入输出端口,是 STM32 芯片可直接控制的引脚。通过将 GPIO 引脚与外部设备连接,可实现与外部设备的通讯、控制及数据采集等功能。所有 GPIO 引脚均具备基本的输入和输出能力:
| 功能类型 | 原理 | 核心作用 | 典型应用 |
| 输出 | 由 STM32 控制引脚输出高、低电平,实现开关控制 | 控制外部设备通断 / 状态 | LED 驱动、继电器 / 三极管控制 |
| 输入 | 检测外部输入的电平信号,通过电平高低区分不同状态。 | 检测外部电平 / 状态 | 按键检测、传感器信号采集 |
本章只介绍GPIO输入功能,详细可以参考:
2. 原理图
本章除了三颗LED灯还需要用到按键,我们开发板上按键原理图如下:

3. 按键
按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,使用按键时会产生图按键抖动说明图中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。可以利用电容充放电的延时,消除了波纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可。

4. 工程创建
创建工程可以参考:
这里直接沿用上一章的3颗LED灯实验,不需要再去重复声明了,只需要对两个按键进行声明,找到.ioc文件,打开:

找到GPIO配置的地方,将三颗LED灯的初始电平设为高电平,也就是初始处于熄灭状态:

然后找到PA0和PC13将其设置为输入模式:

然后将其引脚配置为下拉模式:

然后重新生成代码:

可以看到此时gpio.c的初始化函数中增加了按键的初始化代码:
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = KEY2_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(KEY2_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pin : PtPin */
GPIO_InitStruct.Pin = KEY1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLDOWN;
HAL_GPIO_Init(KEY1_GPIO_Port, &GPIO_InitStruct);
/*Configure GPIO pins : PBPin PBPin PBPin */
GPIO_InitStruct.Pin = LED_G_Pin|LED_B_Pin|LED_R_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
5. 函数讲解
这里主要用到读取GPIO状态的函数:
/**
* @brief 读取指定输入端口引脚的电平状态。
* @param GPIOx: x可以是(根据所用器件而定,取值为A..G),用于选择GPIO外设
* @param GPIO_Pin: 指定要读取的端口位。
* 此参数可以是GPIO_PIN_x,其中x可以是(0..15)。
* @retval 输入端口引脚的电平值。
*/
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
{
GPIO_PinState bitstatus; // 用于存储引脚电平状态的变量
/* 检查参数合法性 */
assert_param(IS_GPIO_PIN(GPIO_Pin));
// 判断读取到的引脚电平是否为高电平
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
{
bitstatus = GPIO_PIN_SET; // 引脚为高电平
}
else
{
bitstatus = GPIO_PIN_RESET; // 引脚为低电平
}
return bitstatus; // 返回引脚电平状态
}
你可以把它理解成:给单片机发一个 “指令”,问它 “某个 GPIO 引脚现在是高电平(3.3V)还是低电平(0V)?”,这个函数会返回明确的答案,是单片机获取外部硬件信号(比如按键、传感器)的核心接口。
6. 代码编写
来到主函数,通过检测KEY1和KEY2按键是否被按下,来控制所有LED灯的亮灭:
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
if(HAL_GPIO_ReadPin(GPIOA, KEY1_Pin) == GPIO_PIN_SET)//检测KEY1按键是否被按下
{
HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_RESET);//点亮所有LED灯
}
else if(HAL_GPIO_ReadPin(GPIOC, KEY2_Pin) == GPIO_PIN_SET)//检测KEY2按键是否被按下
{
HAL_GPIO_WritePin(GPIOB, LED_G_Pin|LED_B_Pin|LED_R_Pin, GPIO_PIN_SET);//关闭所有LED灯
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}

完整代码:


更多推荐
所有评论(0)