硬件设计:
按键机械触点断开、闭合时,由于触点的弹性作用,按键开关不会马上稳定接通或一下子断开,使用按键时会产生下图中的带波纹信号,需要用软件消抖处理滤波,不方便输入检测。,它利用电容充放电的延时,消除了波纹,从而简化软件的处理,软件只需要直接检测引脚的电平即可,但是本实验用的是软件消抖。、
高从按键的原理图可知,这些按键在没有被按下的时候,GPIO引脚的输入状态为低电平,当按键按下时,GPIO引脚的输入状态为低电平。只要我们检测引脚的输入电平,即可判断按键是否被按下。
在配置的时候将PB0、PB1、PB2、PA0设置为GPIO_Input,其余参数默认即可
软件设计:
key.c
#include "key.h"
/*
* @函数名称:KEY_GPIO_Init(void)
* @入口参数: void
* @出口参数: void
* @函数作用: 初始化KEY各引脚
**/
void KEY_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin : PA0 */
GPIO_InitStruct.Pin = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pins : PB0 PB1 PB2 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/*
* @函数名称:KEY_Scan(void)
* @入口参数: void
* @出口参数: key_value
* @函数作用: 识别按键
**/
unsigned char KEY_Scan(void)
{
unsigned char key_value=0;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_0)==GPIO_PIN_RESET)
key_value=1;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_1)==GPIO_PIN_RESET)
key_value=2;
if(HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_2)==GPIO_PIN_RESET)
key_value=3;
if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
key_value=4;
return key_value;
}
/*
* @函数名称:void KEY_Distinguish(void)
* @入口参数: void
* @出口参数: void
* @函数作用: 扫描按键 是 上升沿 下降沿
**/
/* USER CODE BEGIN PV */
__IO uint32_t uwTick_last;
unsigned char key_Val,key_Dwon,key_Up,key_last,key_Status;
/* USER CODE END PV */
void KEY_Distinguish(void)
{
if(uwTick-uwTick_last<100) return ;//减速函数每隔多少时间扫描一下
uwTick_last=uwTick;
//判断连续两次间隔的状态
key_Val=KEY_Scan();
key_Dwon=key_Val & (key_last ^ key_Val);
key_Up=~key_Val & (key_last ^ key_Val);
key_last=key_Val;
if((key_Up==0&&key_Dwon!=0&&key_last==0)||
(key_Up==0&&key_Dwon==0&&key_last!=0))//情况一:
{
key_Status=0;
}
if((key_Up!=0&&key_Dwon==0&&key_last!=0)||
(key_Up==0&&key_Dwon==0&&key_last==0))//情况二:
{
key_Status=1;
}
}
* @函数名称:void KEY_Distinguish(void) 函数解释是uwTick:全局变量,主要作用是滴答定时器每进入中断一次umTick就会增加一次
同理可以说umTick每增加一个数,就计数1ms。(具体为什么是一毫秒请了解滴答定时器)
if(uwTick-uwTick_last<100);每隔100ms扫描一次,长按短按就在定义一个变量每次扫描的时候加一然后对此判断。
扫描按键算法解读:以按下按键4为例子
key_Val=KEY_Scan();
key_Dwon=key_Val & (key_last ^ key_Val);
key_Up=~key_Val & (key_last ^ key_Val);
key_last=key_Val;
//情景一:两次连续扫描,按键得到的结果从0(都没按下)到4得到了低电平
// key_Val=4(0000 0100)
// key_Dwon=0000 0100(4) & (0000 0000 ^ 0000 0100(4))=0000 0100(4) & 0000 0100=0000 0100(4)
// key_Up=1111 1011 & (0000 0000 ^ 0000 0100)= 1111 1011 & 0000 0100=0000 0000(0)
// key_last=0000 0100(4)
//情景2:产生下降沿的时候,按键一直按着
// key_Val=4(0000 0100)
// key_Dwon=0000 0100 & (0000 0100 ^ 0000 0100)=0000 0100 & 0000 0000=0000 0000(0)
// key_Up=1111 1011 & (0000 0100 ^ 0000 0100)= 1111 1011 & 0000 0000=0000 0000(0)
// key_last=0000 0100(4)
//情景3:一直按着随后抬起
// key_Val=0(0000 0000)
// key_Dwon=0000 0000 & (0000 0100 ^ 0000 0000)=0000 0000 & 0000 0100=0000 0000 (0)
// key_Up=1111 1111 & (0000 0100 ^ 0000 0000)= 1111 1111 & 0000 0100=0000 0100(4)
// key_last=0000 0000(0)