STC8H 两个按键组合按下的逻辑实现
在STC8H单片机上实现两个按键组合按下的逻辑,可以采用以下几种方法:
方法一:基本状态检测法
#include "stc8h.h"
#define KEY1 P30
#define KEY2 P31
void delay_ms(unsigned int ms) {
unsigned int i, j;
for(i=0; i<ms; i++)
for(j=0; j<1000; j++);
}
void main() {
P3M0 = 0x00; // 设置P3口为准双向口
P3M1 = 0x00;
while(1) {
// 检测组合键(KEY1+KEY2同时按下)
if(KEY1 == 0 && KEY2 == 0) {
delay_ms(10); // 消抖
if(KEY1 == 0 && KEY2 == 0) {
// 执行组合键功能
// ...
// 等待按键释放
while(KEY1 == 0 || KEY2 == 0);
}
}
// 检测KEY1单独按下
else if(KEY1 == 0) {
delay_ms(10);
if(KEY1 == 0) {
// 执行KEY1功能
// ...
while(KEY1 == 0);
}
}
// 检测KEY2单独按下
else if(KEY2 == 0) {
delay_ms(10);
if(KEY2 == 0) {
// 执行KEY2功能
// ...
while(KEY2 == 0);
}
}
}
}
方法二:状态机实现法(更可靠)
#include "stc8h.h"
typedef enum {
NO_KEY,
KEY1_PRESSED,
KEY2_PRESSED,
BOTH_KEYS_PRESSED
} KeyState;
KeyState checkKeys() {
static unsigned char key1_cnt = 0, key2_cnt = 0;
// KEY1检测(假设低电平有效)
if(P30 == 0) {
if(key1_cnt < 20) key1_cnt++;
} else {
key1_cnt = 0;
}
// KEY2检测
if(P31 == 0) {
if(key2_cnt < 20) key2_cnt++;
} else {
key2_cnt = 0;
}
// 状态判断
if(key1_cnt >= 20 && key2_cnt >= 20) {
return BOTH_KEYS_PRESSED;
}
else if(key1_cnt >= 20) {
return KEY1_PRESSED;
}
else if(key2_cnt >= 20) {
return KEY2_PRESSED;
}
else {
return NO_KEY;
}
}
void main() {
P3M0 = 0x00; // 设置P3口为准双向口
P3M1 = 0x00;
while(1) {
switch(checkKeys()) {
case KEY1_PRESSED:
// 处理KEY1单独按下
// ...
break;
case KEY2_PRESSED:
// 处理KEY2单独按下
// ...
break;
case BOTH_KEYS_PRESSED:
// 处理组合键
// ...
break;
case NO_KEY:
default:
break;
}
delay_ms(10); // 适当延时,减少CPU占用
}
}
方法三:标志位法(适合长按组合键)
#include "stc8h.h"
bit key1_pressed = 0;
bit key2_pressed = 0;
bit combo_processed = 0;
void checkKeys() {
// KEY1检测
if(P30 == 0) {
delay_ms(10);
if(P30 == 0) {
key1_pressed = 1;
}
} else {
key1_pressed = 0;
combo_processed = 0;
}
// KEY2检测
if(P31 == 0) {
delay_ms(10);
if(P31 == 0) {
key2_pressed = 1;
}
} else {
key2_pressed = 0;
combo_processed = 0;
}
// 组合键检测
if(key1_pressed && key2_pressed && !combo_processed) {
combo_processed = 1;
// 执行组合键功能
// ...
}
}
void main() {
P3M0 = 0x00;
P3M1 = 0x00;
while(1) {
checkKeys();
// 单独按键处理
if(key1_pressed && !key2_pressed) {
// 处理KEY1单独按下
// ...
}
if(key2_pressed && !key1_pressed) {
// 处理KEY2单独按下
// ...
}
}
}
组合键实现要点
-
消抖处理:必须加入软件消抖,通常10-20ms延时
-
按键释放检测:避免重复触发
-
状态区分:明确区分单独按键和组合按键
-
优先级处理:确定组合键和单键的优先级关系
-
响应时间:根据需求调整按键检测的响应速度
扩展功能
如果需要实现"先按KEY1再按KEY2"这样的顺序组合键,可以这样实现:
#include "stc8h.h"
#define KEY1 P30
#define KEY2 P31
bit key1_first = 0;
unsigned int combo_timeout = 0;
void main() {
P3M0 = 0x00;
P3M1 = 0x00;
while(1) {
// 检测KEY1先按下
if(KEY1 == 0 && !key1_first) {
delay_ms(10);
if(KEY1 == 0) {
key1_first = 1;
combo_timeout = 500; // 设置500ms内按下KEY2才视为组合键
}
}
// 在超时时间内检测KEY2按下
if(key1_first && KEY2 == 0 && combo_timeout > 0) {
delay_ms(10);
if(KEY2 == 0) {
// 执行顺序组合键功能
// ...
key1_first = 0;
combo_timeout = 0;
while(KEY1 == 0 || KEY2 == 0); // 等待按键释放
}
}
// 超时处理
if(combo_timeout > 0) {
delay_ms(1);
combo_timeout--;
if(combo_timeout == 0) {
key1_first = 0;
// 可以在这里处理KEY1单独按下
}
}
// 其他按键检测...
}
}
以上方法可以根据实际需求进行组合和调整,建议使用状态机方法,它结构清晰且易于扩展。

浙公网安备 33010602011771号