基于CubeMX 学习 按键输入实验
前言
按键在当今社会用到的领域甚广,特别是电子产品中,比如电视机的电源键、音量键等,每按一下可实现音量加或者减。
1、硬件部分
1.1 按键原理

本实验用到的是机械按键,存在抖动现象,当机械按键的触点闭合和松开时,就会产生抖动,为了保证系统能正确识别按键的开关,就必须对按键的抖动进行消除抖动处理,按键工作过程如下图:

按下时工作过程分三个阶段,按下抖动-稳定-弹起抖动。这个抖动对于人类肉眼来说是几乎感觉不到的,但对于单片机体统而言则是完全可以感应到的,因为单片机处理的速度在微秒级的,而按键抖动的时间至少在毫秒级。在单片机工作过程中如果对按键进行检测按键的通断状态,则会导致判断出错(即一次按下到释放可能被错误认为是多次操作)。因此,为了确保单片机对一次按键动作只作—次响应,就必须对按键进行消除动处理,一般MCU延时10~20ms之间就可以消除抖动。
但是有些情况是不用考虑这个抖动的,比如电视剧遥控器,频道加减和音量加减等,按下就可以连续触发一直加,不需要每次按一次加一的频繁操作。
1.2 硬件连接
MCU 引脚对应外设连接分配表
| 外设 | 单片机IO接口 |
|---|---|
| LED0 | PB5 |
| LED1 | PE5 |
| KEY0 | PE4 |
| KEY1 | PE3 |
| KEY2 | PE2 |
| KEY_UP | PA0 |
| BEEP | PB8 |






2、CubeMX配置
那些基础配置的就不再赘述了,前面的文章教程有详细说明。
这里 LED、BEEP 作为输出功能,KEY作为输入功能配置。

LED0、LED1 端口默认初始电平为高电平、推挽输出、无上下拉、输出速度为低速。
BEEP 端口默认初始电平为低电平、推挽输出、无上下拉、输出速度为低速。



根据前面的电原理图可知 KEY0、KEY1、KEY2接GND,需要低电平才能触发、KEY_UP接VCC,需要低电平才能触发。所以这里按键要配置为输入功能才能检测电平状态,KEY0、KEY1、KEY2配置为输入模式、上拉、KEY_UP配置为输入、下拉。




整体配置如下:

工程输出建议生成独立的.c/.h文件:

3、程序编写
3.1 简单处理方法
初学时直接对端口进行操作,操作通俗易懂
示例代码如下:
while(1)
{
HAL_Delay(10); //延时消抖
if(HAL_GPIO_ReadPin(KEY0_GPIO_Port,KEY0_Pin)==0) //KEY0按下
{
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET); //点亮LED0
}
else if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==0) //KEY2按下
{
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET); //点亮LED1
}
else if(HAL_GPIO_ReadPin(KEYUP_GPIO_Port,KEYUP_Pin)==1) //KEYUP按下
{
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET); //打开蜂鸣器
}
else if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==0) //KEY1按下
{
HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET); //熄灭LED0
HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET); //熄灭LED1
HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET); //关闭蜂鸣器
}
}
3.2 高级处理方法
示例代码如下:
采取了宏定义的方式,用起来比较直观,易调用。
/* LED、BEEP 端口定义 */
#define LED0(n) (n?HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET))
#define LED0_Toggle (HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin)) //LED0电平翻转
#define LED1(n) (n?HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET))
#define LED1_Toggle (HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin)) //LED1电平翻转
#define BEEP(n) (n?HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_SET):HAL_GPIO_WritePin(BEEP_GPIO_Port,BEEP_Pin,GPIO_PIN_RESET))
#define BEEP_Toggle (HAL_GPIO_TogglePin(BEEP_GPIO_Port, BEEP_Pin)) //BEEP电平翻转
/* KEY端口定义 */
#define KEY0 HAL_GPIO_ReadPin(KEY0_GPIO_Port, KEY0_Pin)
#define KEY1 HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin)
#define KEY2 HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin)
#define KEYUP HAL_GPIO_ReadPin(KEYUP_GPIO_Port,KEYUP_Pin)
while(1)
{
HAL_Delay(10); //延时消抖
if(KEY0==RESET) //KEY0按下
{
LED0(0); //点亮LED0
}
else if(KEY2==RESET) //KEY2按下
{
LED1(0); //点亮LED1
}
else if(KEYUP==!RESET)//KEYUP按下
{
BEEP(1); //打开蜂鸣器
}
else if(KEY1==RESET) //KEY1按下
{
LED0(1); //熄灭LED0
LED1(1); //熄灭LED1
BEEP(0); //关闭蜂鸣器
}
}
4、下载验证
编译下载程序,按下KEY0,LED0点亮、按下KEY2,LED1点亮、按下KEYUP,BEEP响亮、按下KEY1,LED0、LED1、BEEP都关闭。本实验比较基础,MCU作为输入功能,检测外部电平信号从而进行一系列指令操作。