基于乐育的按键框架
可消抖,单触发,可同时执行按下和抬起两个事件
移植代码
ProcKeyOne.h
#ifndef _PROC_KEY_ONE_H_
#define _PROC_KEY_ONE_H_
#include "main.h"
void InitProcKeyOne(void); //初始化ProcKeyOne模块
void ProcKeyDownKey1(void); //处理按键按下的事件,即按键按下的响应函数
void ProcKeyUpKey1(void); //处理按键弹起的事件,即按键弹起的响应函数
void ProcKeyDownKey2(void); //处理按键按下的事件,即按键按下的响应函数
void ProcKeyUpKey2(void); //处理按键弹起的事件,即按键弹起的响应函数
#endif //_PROC_KEY_ONE_H_
ProcKeyOne.c
#include "ProcKeyOne.h"
#include "usart.h" //自行添加,这里以串口打印任务为例
void InitProcKeyOne(void)
{
}
void ProcKeyDownKey1(void)
{
PrintfDebug("KEY1 PUSH DOWN\r\n"); //打印按键状态
}
void ProcKeyUpKey1(void)
{
PrintfDebug("KEY1 RELEASE\r\n"); //打印按键状态
}
void ProcKeyDownKey2(void)
{
PrintfDebug("KEY2 PUSH DOWN\r\n"); //打印按键状态
}
void ProcKeyUpKey2(void)
{
PrintfDebug("KEY2 RELEASE\r\n"); //打印按键状态
}
KeyOne.h
#ifndef _KEY_ONE_H_
#define _KEY_ONE_H_
#include "main.h"
//根据自己的按键使用的GPIO更改
//也可以把这部分注释了,用CubeMX配置
#define KEY1_Port GPIOA
#define KEY1_Pin GPIO_PIN_0
#define KEY2_Port GPIOC
#define KEY2_Pin GPIO_PIN_13
//低电平触发方式
#define KEY_DOWN_LEVEL_KEY1 0x00 //0x00表示按下为低电平
#define KEY_DOWN_LEVEL_KEY2 0x00 //0x00表示按下为低电平
//高电平触发方式
#define KEY_UP_LEVEL_KEY1 0xFF //0xFF表示按下为高电平
#define KEY_UP_LEVEL_KEY2 0xFF //0xFF表示按下为高电平
//更多按键自行添加
#define TRUE 1
#define FALSE 0
typedef enum
{
KEY_NAME_KEY1 = 0, //按键1
KEY_NAME_KEY2, //按键2
//更多按键自行添加
KEY_NAME_MAX
}EnumKeyOneName;
void InitKeyOne(void);
void ScanKeyOne(uint8_t keyName, void(*OnKeyOneUp)(void), void(*OnKeyOneDown)(void));//每10ms调用一次
#endif //_KEY_ONE_H_
KeyOne.c
#include "KeyOne.h"
#define KEY1 (HAL_GPIO_ReadPin(KEY1_Port , KEY1_Pin ))
#define KEY2 (HAL_GPIO_ReadPin(KEY2_Port , KEY2_Pin ))
static uint8_t s_arrKeyDownLevel[KEY_NAME_MAX]; //使用前要在InitKeyOne函数中进行初始化
void InitKeyOne(void)
{
//高电平触发方式配置为0xff,低电平触发方式配置为0x00
s_arrKeyDownLevel[KEY_NAME_KEY1] = KEY_UP_LEVEL_KEY1; //按键KEY1按下时为高电平
s_arrKeyDownLevel[KEY_NAME_KEY2] = KEY_UP_LEVEL_KEY2; //按键KEY2按下时为高电平
}
void ScanKeyOne(uint8_t keyName, void(*OnKeyOneUp)(void), void(*OnKeyOneDown)(void))
{
static uint8_t s_arrKeyVal[KEY_NAME_MAX]; //用于存放按键的数值
static uint8_t s_arrKeyFlag[KEY_NAME_MAX]; //用于存放按键的标志位
s_arrKeyVal[keyName] = s_arrKeyVal[keyName] << 1; //左移一位
switch (keyName)
{
case KEY_NAME_KEY1:
s_arrKeyVal[keyName] = s_arrKeyVal[keyName] | KEY1; //按下/弹起时,KEY1为0/1
break;
case KEY_NAME_KEY2:
s_arrKeyVal[keyName] = s_arrKeyVal[keyName] | KEY2; //按下/弹起时,KEY2为0/1
break;
default:
break;
}
//按键标志位的值为TRUE时,判断是否有按键有效按下
if(s_arrKeyVal[keyName] == s_arrKeyDownLevel[keyName] && s_arrKeyFlag[keyName] == TRUE)
{
(*OnKeyOneDown)(); //执行按键按下的响应函数
s_arrKeyFlag[keyName] = FALSE; //表示按键处于按下状态,按键标志位的值更改为FALSE
}
//按键标志位的值为FALSE时,判断是否有按键有效弹起
else if(s_arrKeyVal[keyName] == (uint8_t)(~s_arrKeyDownLevel[keyName]) && s_arrKeyFlag[keyName] == FALSE)
{
(*OnKeyOneUp)(); //执行按键弹起的响应函数
s_arrKeyFlag[keyName] = TRUE; //表示按键处于弹起状态,按键标志位的值更改为TRUE
}
}
main.c
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"
#include "KeyOne.h"
#include "ProcKeyOne.h"
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM13_Init();
MX_USART1_UART_Init();
InitKeyOne();
while (1)
{
Proc2msTask();
}
}
static void Proc2msTask(void) //2ms任务
{
static int16_t s_iCnt5 = 0;
if(Get2msFlag())
{
if(s_iCnt5 >= 4)
{
ScanKeyOne(KEY_NAME_KEY1, ProcKeyUpKey1, ProcKeyDownKey1);
ScanKeyOne(KEY_NAME_KEY2, ProcKeyUpKey2, ProcKeyDownKey2);
s_iCnt5 = 0;
}
else
{
s_iCnt5++;
}
Clr2msFlag();
}
}