基于CubeMX 学习 按键输入实验

基于CubeMX 学习 按键输入实验



前言

按键在当今社会用到的领域甚广,特别是电子产品中,比如电视机的电源键、音量键等,每按一下可实现音量加或者减。


1、硬件部分

1.1 按键原理

在这里插入图片描述

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

在这里插入图片描述
按下时工作过程分三个阶段,按下抖动-稳定-弹起抖动。这个抖动对于人类肉眼来说是几乎感觉不到的,但对于单片机体统而言则是完全可以感应到的,因为单片机处理的速度在微秒级的,而按键抖动的时间至少在毫秒级。在单片机工作过程中如果对按键进行检测按键的通断状态,则会导致判断出错(即一次按下到释放可能被错误认为是多次操作)。因此,为了确保单片机对一次按键动作只作—次响应,就必须对按键进行消除动处理,一般MCU延时10~20ms之间就可以消除抖动。

但是有些情况是不用考虑这个抖动的,比如电视剧遥控器,频道加减和音量加减等,按下就可以连续触发一直加,不需要每次按一次加一的频繁操作。

1.2 硬件连接

MCU 引脚对应外设连接分配表

外设单片机IO接口
LED0PB5
LED1PE5
KEY0PE4
KEY1PE3
KEY2PE2
KEY_UPPA0
BEEPPB8

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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作为输入功能,检测外部电平信号从而进行一系列指令操作。


版权声明:本文为weixin_53944340原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。