上一篇博客我们介绍了如何使用GPIO配置跑马灯,根据GPIO的基本结构图,我们能够发现,他肯定不单单有输出的功能,肯定可以检测IO上的电平变化,实际上就是输入的功能。
1.按键
在大多数情况下,按键是一种简单的开关,当按下时会改变电路连接,从而改变电平状态。按键通常与一个上拉电阻或下拉电阻连接,以确保在未按下时,输入引脚处于已知的高电平或低电平。
值得一提的是,这种按键并不是理想的开关,在按下和松开的过程中,电平的变化往往不是理想的,而是伴随着尖峰、抖动。
2. 硬件连接
假设我们使用一个带上拉电阻的按键,连接方式为,一个引脚连接到STM32的GPIO输入引脚,另一个引脚连接到地(GND),同时,在输入引脚与VCC之间连接一个上拉电阻。
当按下按键时,GPIO引脚的电平从高变为低;当松开按键时,引脚电平保持高电平。下图并没有画出上拉电阻,实际上在单片机内部就有。
3. 去抖动
机械按键在按下和释放时,电平可能会在高低之间快速波动,产生“抖动”现象。为了解决这个问题,我们需要在软件中进行去抖动处理,可以通过计时器或延时来实现。
此外,我们还可以通过硬件的方式,来消除“抖动”的影响,可以在按键电路的上拉电阻或者下拉电阻两侧并联电容,消除电压尖峰。
4. STM32上的按键输入配置
接下来,我们将以STM32的标准库为例详细介绍如何在STM32上配置按键输入,假设按键连接在PE3引脚上。
4.1GPIO初始化
我们通常会使用一个函数来配置GPIO引脚的模式、速度、上下拉电阻等属性。下面我们详细解释一下GPIO_Config函数。
void GPIO_Config(void)
{
// 启动GPIOC的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
// 配置PC13为输入模式,带上拉电阻
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 输入模式,带上拉
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}
4.2启动GPIO端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
在STM32中,每个外设(包括GPIO端口)都需要通过时钟来驱动。在使用某个GPIO端口之前,必须先启用对应的时钟,否则后续对该端口的配置和操作将无效。
RCC_APB2PeriphClockCmd:这是一个用于管理APB2总线上的外设时钟的函数。
RCC_APB2Periph_GPIOC:这个宏定义代表GPIOC端口对应的时钟。
4.3结构体参数
GPIO_Pin_3:表示要配置的引脚号。STM32的每个GPIO端口有多个引脚(通常编号为0到15),GPIO_Pin_3表示PE3引脚。
GPIO_Mode_IPU:表示输入模式,带上拉电阻。
GPIO_Speed_2MHz:用于设置GPIO引脚的速度,实际上是引脚的切换速率。对于输入引脚,速度设置一般没有影响,更多的是在输出模式下有意义。
4.4初始化
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_Init:这个函数将前面配置好的GPIO_InitTypeDef结构体中的参数应用到指定的GPIO端口。
5. 读取按键状态
在主循环中,我们可以通过读取GPIO引脚的状态来判断按键是否被按下:
while (1)
{
if (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) == 0)
{
// 按键按下时执行的操作
}
else
{
// 按键未按下时的操作
}
}
注意,有些程序并不是简简单单的向上面那样,还会使用宏定义,简化程序。但对初学者不友好。
6. 去抖动处理
按键抖动可能导致误触发,因此我们可以在软件中添加去抖动处理。以下是一个简单的去抖动处理示例:
#define DEBOUNCE_DELAY 50 // 50毫秒去抖动延时
while (1)
{
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET)
{
Delay(DEBOUNCE_DELAY); // 延时去抖动
if (GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_13) == Bit_RESET)
{
// 按键按下且去抖动后执行的操作
}
}
}
拓展
为了提高响应速度并减少CPU占用,我们可以将按键引脚配置为外部中断(EXTI),当按键状态变化时,触发中断处理函数。
通过计时器,我们可以实现对按键的长按和短按识别,从而执行不同的操作。