感谢iceasy商城,感谢灵动微 冬天里送来的温暖
一段按键逻辑代码,
状态机单击,多击, 以及 单击加长按
void Key_Scan(void){
// static u8 KeyState = 0; // 按键状态机
static uint8_t KeyTime = 0; // 计时器
static uint8_t KeyPressCount = 0; // 按键次数计数(用于多击判断)
static uint8_t ReleaseDebounceTime = 0; // 松手消抖计时器
switch (keyState){
case STATE_IDLE: // 初始状态:等待按键按下
KeyPressCount = 0; // 强制清零按键计数
FLAG_CLR(flag,FLAG_dojiflag);
FLAG_CLR(flag, FLAG_last_long_press); // +++ 在这里重置长按标记 +++
if (!KEY_PIN) {
keyState = STATE_DB_PRESS; // 进入消抖确认状态
KeyTime = 0; // 消抖计时器重置
}else {
KeyPressCount = 0;
}
break;
//---------------------------------------
case STATE_DB_PRESS: // 消抖确认状态
if (!KEY_PIN) {
if(KeyTime<DEBOUNCE_TIME) {
KeyTime++;
}else{
KeyTime = 0;
keyState = STATE_PRESSED; // 进入"短按/长按"判断
KeyPressCount = 0;
}
}else{
keyState = STATE_IDLE; // 返回初始状态(抖动忽略)
KeyPressCount = 0;
}
break;
//---------------------------------------
case STATE_PRESSED: // 短按/长按判断
if (KEY_PIN) { // 按键已松开
keyState = STATE_DB_RELEASE; // 进入"多击判断"状态
ReleaseDebounceTime = 0; // 松手消抖计时器
}else {
if (++KeyTime >= LONG_PRESS_TIME){ // 长按判定时间(例如300ms) 长按长按长按
// FLAG_CLR(flag,FLAG_dojiflag);
if(!FLAG_GET(flag,FLAG_suodingflag)){
}else{
}
// 如果是第一次按下(KeyPressCount==0),判定为长按
if(KeyPressCount == 0) {
keyEvent = KEY_LONG_PRESS;
} else {
keyState = STATE_WAIT_MULTI;
}
}
}
break;
//---------------------------------------
case STATE_DB_RELEASE: // 多击判断(单击/双击/三击)
if (!KEY_PIN){ // 再次按下
if (ReleaseDebounceTime >= DEBOUNCE_TIME){ // 松手消抖处理
if (KeyTime >= DEBOUNCE_TIME){ // 消抖处理
if (KeyTime < 6) { // 连击间隔小于50ms,忽略此次按键
KeyPressCount--; // 回退按键计数
}else{
KeyPressCount++; // 增加按键次数
}
KeyTime = 0;
keyState = STATE_WAIT_MULTI; // 进入"多击长按"判断
}
}
}else { // 未按下
if (++ReleaseDebounceTime >= DEBOUNCE_TIME) // 松手消抖计时
{
if (++KeyTime >= MULTI_PRESS_INTERVAL) // 多击间隔时间(例如250ms)
{
// 根据计数确定最终按键值
switch (KeyPressCount)
{
case 1: keyEvent = KEY_SINGLE_CLICK; // 单击
GPIO_WriteBit(GPIOA,GPIO_Pin_11,Bit_SET);
break;
case 2: keyEvent = KEY_DOUBLE_CLICK; // 双击
GPIO_WriteBit(GPIOA,GPIO_Pin_11,Bit_RESET);
break;
case 3: keyEvent = KEY_TRIPLE_CLICK; // 三击
break;
case 4: keyEvent = KEY_QUAD_CLICK; // 4击
break;
case 5: keyEvent = KEY_QUINTUPLE_CLICK; // 5击
break;
case 6: keyEvent = KEY_SEXTUPLE_CLICK; // 6击
if(!FLAG_GET(flag,FLAG_kgflag)){ //关机状态下查看电量
}else{
}
break;
case 7: keyEvent = KEY_SEPTUPLE_CLICK; break; // 7击
case 8: keyEvent = KEY_OCTUPLE_CLICK; break; // 8击
case 9: keyEvent = KEY_NONUPLE_CLICK; break; // 9击
case 10: keyEvent = KEY_TEN_CLICK; // 10击
break;
default: keyEvent = KEY_NONE; break; // 其他情况
}
KeyPressCount = 0;
keyState = STATE_IDLE; // 返回初始状态
KeyTime=0;
}
}
}
break;
case STATE_WAIT_MULTI: // 多击后的长按判断
if (KEY_PIN) { // 按键松开
ReleaseDebounceTime = 0; // 重置松手消抖计时器
keyState = STATE_DB_RELEASE; // 返回多击判断(继续等待后续点击)
}else{ // 按键仍按下
FLAG_SET(flag,FLAG_dojiflag);
if (++KeyTime >= LONG_PRESS_TIME){ // 长按判定时间
// 根据当前点击次数判断长按类型
switch (KeyPressCount)
{
// case 1: Key_value = KEY_CLICK_LONG; printf("1+1"); break; // 单击加长按
case 2: keyEvent = KEY_SINGLE_THEN_LONG; // 1击加长按
if(FLAG_GET(flag,FLAG_kgflag)){ //开机状态下档位+1
}else {
}
break;
case 3: keyEvent = KEY_DOUBLE_THEN_LONG; // 2击加长按
if(FLAG_GET(flag,FLAG_kgflag)){ //开机状态下档位-1
}else {
}
break;
case 4: keyEvent = KEY_TRIPLE_THEN_LONG; // 3击加长按
break;
case 5: keyEvent = KEY_QUAD_THEN_LONG; // 4击加长按
break;
case 6: keyEvent = KEY_QUINTUPLE_THEN_LONG; // 5击加长按
break;
case 7: keyEvent = KEY_SEXTUPLE_THEN_LONG; break; // 6击加长按
case 8: keyEvent = KEY_SEPTUPLE_THEN_LONG; break; // 7击加长按
case 9: keyEvent = KEY_OCTUPLE_THEN_LONG; break; // 8击加长按
case 10: keyEvent = KEY_NONUPLE_THEN_LONG; break; // 9击加长按
case 11: keyEvent = KEY_TEN_THEN_LONG; break; // 10击加长按
default: keyEvent = KEY_NONE; break; // 其他情况
}
KeyPressCount = 0;
keyState = STATE_WAIT_IDLE; // 进入释放等待
}
}
break;
case STATE_WAIT_IDLE: // 释放等待状态
if(!FLAG_GET(flag,FLAG_suodingflag)){
// wuji();
}
if (KEY_PIN) {
KeyTime = 0;
KeyPressCount = 0; // 重置按键计数
}
break;
}
}
开源社区 


