STC8H 两个按键组合按下的逻辑实现

在STC8H单片机上实现两个按键组合按下的逻辑,可以采用以下几种方法:

方法一:基本状态检测法

c
复制
#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);
            }
        }
    }
}

方法二:状态机实现法(更可靠)

c
复制
#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占用
    }
}

方法三:标志位法(适合长按组合键)

c
复制
#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单独按下
            // ...
        }
    }
}

组合键实现要点

  1. 消抖处理:必须加入软件消抖,通常10-20ms延时

  2. 按键释放检测:避免重复触发

  3. 状态区分:明确区分单独按键和组合按键

  4. 优先级处理:确定组合键和单键的优先级关系

  5. 响应时间:根据需求调整按键检测的响应速度

扩展功能

如果需要实现"先按KEY1再按KEY2"这样的顺序组合键,可以这样实现:

c
复制
#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单独按下
            }
        }
        
        // 其他按键检测...
    }
}

以上方法可以根据实际需求进行组合和调整,建议使用状态机方法,它结构清晰且易于扩展。

posted @ 2025-04-14 12:17  FBshark  阅读(124)  评论(0)    收藏  举报