传统按键检测方法

直接接地连接

在最简单的按键电路中,每个按键直接连接到单片机的一个I/O口和地线。当按键按下时,对应I/O口被拉低,单片机检测到低电平即可判断按键按下。

优点:电路简单,编程容易
缺点:每个按键占用一个I/O口,不适合按键数量多的场景

矩阵键盘扫描

当按键数量增多时,采用矩阵扫描方式可以显著减少I/O口的使用。

text

    列0 列1 列2
行0 键1 键2 键3
行1 键4 键5 键6
行2 键7 键8 键9

ps:忽略以上按键的内容,随便在自己做过的项目上截的图

问题引入:外接键盘的困境

想象这样一个场景:你需要设计一个外接键盘,通过线缆连接到主控板。如果采用传统的矩阵扫描方式,假设有10个按键,采用4×3矩阵需要7根线(4行+3列),如果直接连接还要包括地线!

问题来了

1.难道我们要为了一个简单的键盘外接这么多根线吗?线材成本、连接器尺寸、可靠性都会成为问题。

2.难道我们要做个键盘似的复杂协议?或者通过外接控制芯片?一方面我们也不要很多按键,功能也不需要复杂,另一方面进行成本考虑。

创新解决方案:双线ADC按键检测

今天我要介绍一种只需要两根信号线(没错就是只有两根线)就能检测多个按键的巧妙方法!

方法一:独立电阻网络

电路原理

每个按键串联一个不同阻值的电阻,所有电阻的一端连接地,另一端分别通过按键接到ADC检测点。

工作原理
  • 没有按键按下时:ADC检测到VCC电压(通过上拉电阻)

  • 按键SW1按下:ADC电压 = VCC × (R2) / (R2 + R1)

  • 按键SW2按下:ADC电压 = VCC × (R3) / (R3 + R1)

  • ...

  • 每个按键对应一个独特的电压值

电阻值选择

电压范围间隔=Vcc/(n-1)

比如6个按键那就是:0,1/6Vcc,2/6Vcc...5/6Vcc。

(上图没有画出,就是最后一个只有按键没有串联电阻)

选择适当的电阻值,确保每个按键按下时产生明显不同的电压值,按上图阻值计算:

没有按下:adc电压=Vcc
按键1: R2 = 5kΩ  -> 电压 = 5/6Vcc
按键2: R3 = 2kΩ  -> 电压 = 4/6Vcc
按键3: R4 = 1kΩ -> 电压 = 3/6Vcc
...
代码实现

c

#define ADC_THRESHOLD_1 900   // 按键1的ADC阈值
#define ADC_THRESHOLD_2 1600  // 按键2的ADC阈值
#define ADC_THRESHOLD_3 2200  // 按键3的ADC阈值
// ... 更多阈值

uint8_t read_adc_key(void) {
    uint16_t adc_value = read_adc(ADC_CHANNEL);
    
    if (adc_value < ADC_THRESHOLD_1) {
        return 1;  // 按键1
    } else if (adc_value < ADC_THRESHOLD_2) {
        return 2;  // 按键2
    } else if (adc_value < ADC_THRESHOLD_3) {
        return 3;  // 按键3
    }
    // ... 更多判断
    
    return 0;  // 无按键
}

注意:单次只能识别一个按键按下,如果同时按下两个会导致电压变化,导致按键无法识别,或者错判按键,另外按键增多,分压电阻也要做相应变化,可能会超出常用电阻范围。

方法二:电阻分压网络

电路原理

使用相同阻值的电阻串联形成分压网络,每个按键连接到电阻串的不同节点。

工作原理
  • 按键SW1按下:ADC检测VCC电压

  • 按键SW2按下:ADC检测VCC × R2 / (R1+R2)

  • 按键SW3按下:ADC检测VCC × (R2+R3) / (R1+R2+R3)

  • 每个按键产生不同的分压比

电阻值选择

        按键的串联电阻相同

        上图中的上拉电阻 = 各串联电阻阻值和的一半

        R1 =(R2+R3+R4+R5+R6)  / 2

        这样做的目的可以占用整个ADC量程,上图按键数量不多,故就简单选半个量程

优势
  • 所有电阻值相同,便于采购和匹配

  • 电压分布均匀,便于ADC识别

  • 支持更多按键数量

实际应用考虑

硬件设计要点

  1. 电阻精度:建议使用1%精度的电阻以保证检测准确性

  2. ADC分辨率:12位ADC可以支持更多按键

  3. 去抖动处理:软件中需要添加按键去抖动逻辑

  4. 抗干扰:长线传输时考虑添加滤波电容

软件优化

c

// 带去抖动的ADC按键检测
uint8_t debounced_adc_key_read(void) {
    static uint8_t stable_count = 0;
    static uint16_t last_value = 0;
    static uint8_t last_key = 0;
    
    uint8_t current_key = read_adc_key();
    
    if (current_key == last_key) {
        stable_count++;
        if (stable_count >= 5) {  // 连续5次相同认为稳定
            return current_key;
        }
    } else {
        stable_count = 0;
        last_key = current_key;
    }
    
    return 0;  // 按键状态未稳定
}

总结

通过ADC检测电压来识别多个按键的方法,极大地简化了外接键盘的设计:

  • 线材数量:从7+根减少到2根

  • 成本:电阻成本远低于多芯电缆,逻辑芯片和连接器

  • 可靠性:减少连接点,提高系统可靠性

  • 扩展性:通过精心设计电阻值,可以支持更多按键

这种方法特别适合遥控器、简单键盘、控制面板等需要外接多个按键的应用场景。希望这个设计思路对您的项目有所启发!


注:实际电阻值需要根据具体的VCC电压和ADC分辨率进行计算调整。建议在实际硬件上测试并校准阈值。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐