独立按键?矩阵扫描?一个 IO 口也能实现的矩阵键盘?

1. 按键的分类

在嵌入式系统中,按键是最常见的人机交互接口之一。根据按键数量和硬件资源限制,可分为独立按键和矩阵按键两种类型。本文将从原理、硬件设计、软件实现、优缺点及应用场景等方面进行详细对比,并着重介绍如何使用一个GPIO即可实现矩阵键盘的功能。

着重介绍内容在3.2.3小节和第五章,文末提供本例程仿真与程序源码,不足之处还请指正!

2. 核心原理

2.1 独立按键

结构:每个按键独立连接一个IO口,采用共阴极或共阳极设计(习惯使用共阴)。

工作原理:

1. 未按键时,IO口通过上拉电阻保持高电平。

2. 按键按下时,IO口电平被拉低,触发中断或轮询检测。

2.2 矩阵按键

结构:由行线(Row)和列线(Column)交叉形成按键矩阵(如4x4=16键)。

工作原理:

1. 逐行置低电平,其余行置高。

2. 检测列线电平,若某列变低,则对应行和列的交点为按下的按键。

3. 硬件设计对比

3.1 独立按键电路


按键内部结构图

按键识别过程(按下>松开)

优点:接线简单,扫描程序相对简单,适合按键数≤8的场景。

缺点:存在机械抖动,在按下瞬间不稳定,需使用软件优化扫描程序,每个按键均需一个GPIO,实时系统中频繁的按键中断可能会出现失效,延迟响应等问题。

3.2独立按键的优化

独立按键在系统中使用的频率是远远大于矩阵键盘的,因此它的缺点我们无法忽略,所以给大家提供一个新思路,如何避开机械抖动与响应滞后的问题。

3.2.1外部中断

相信大家对外部中断都不陌生吧。外部中断是单片机的一种硬件机制,允许外部设备(如按键、传感器)通过特定引脚触发中断,暂停当前任务,优先执行中断服务程序(ISR)。

3.2.2外部中断的优势

 实时性:快速响应外部事件(如紧急停止)。

 低功耗:无需轮询,CPU空闲时可进入睡眠模式。

高效性:中断触发时才执行任务,减少CPU资源占用。

3.2.3外部中断的使用

仅需将按键接入外部中断引脚,在程序中配置中断即可使用。

示例代码:(STC89Cxx为例)

外部中断初始化配置

// 配置外部中断0为下降沿触发

IT0 = 1; // 触发方式选择(0:电平触发,1:下降沿触发)

EX0 = 1; // 使能外部中断0

EA = 1; // 总中断使能

//外部中断0服务程序

void INT0_ISR() interrupt 0 

{

    delay_ms(10); // 消抖

    if(KEY == 0) 

    {

        LED = !LED; // 切换LED状态

    }

}

如此便可利用外部中断的特性,及时响应按键的处理。

3.2.3进一步的优化

对于STC89Cxx的单片机来讲,仅提供两个外部中断源(INT0 INT1)来说,对于多数人来说是远远不够的!所以请看下图!

仅需增加一个与门电路即可实现多个按键共用一个外部中断!

原理:当有按键按下的时候同时会触发外部中断的电平反转,进而触发外部中断源

注意:按键接法需与外部中断触发方式对应,图中按键共阴接法,外部中断下降沿触发。

附:与门真值表方便大家理解其工作原理,以二输入为例(有输入为0时,输出即为0产生下降沿,否则输出为1)

 3.3 矩阵按键电路

优点:16键仅需8个IO口,节省资源。

缺点:扫描程序复杂,对新手不友好,同时相对于STC89C52来说,8个IO口的占用也是比较痛苦的

4. 软件实现对比

4.1 独立按键代码示例

// 检测按键是否按下(带消抖)

sbit KEY_PIN = P3^0;

void check_key() 

{

    if(KEY_PIN == 0)

 {

        delay_ms(10); // 消抖

        if(KEY_PIN == 0) 

       {

            // 执行按键功能

        }

    }while(KEY_PIN==0); //松手检测

}

4.2 矩阵按键代码示例

// 4x4矩阵键盘扫描

unsigned char Keyboard_Scan() 

{

    unsigned char row, col;

    for(row=0; row<4; row++) 

    {

        P1 = ~(1 << row); // 逐行置低

        _nop_(); _nop_(); // 消抖

        if(P1 & 0x10) col = 0;

        else if(P1 & 0x20) col = 1;

        else if(P1 & 0x40) col = 2;

        else if(P1 & 0x80) col = 3;

        else continue;

        while(P1 & 0xF0); // 等待释放

        return row*4 + col + 1; // 生成键值

    }

    return 0;

}

5.如何使用一个GPIO实现矩阵键盘

5.1实现原理图(该图来自官方手册,下文对应程序是根据介绍自行编写)

仿真排版后的仿真图(仿真中STC系列的单片机只有这款本身有ADC功能,如果你使用的单片机本身无ADC采集功能,也可使用外挂ADC,新手推荐ADC0832、PCF8591,精度8位)

各器件说明:

C1:滤波,避免抖动

R1:限流,防止电流过大

R2:下拉,无按键触发时提供一个稳定的采集值(官方取值200K,仿真时无法将电压下拉到很低,ADC值处于矩阵按键覆盖范围,对判断带来不便,因此降低阻值将电压值拉低到矩阵键值外。实际使用现场调试)

R3~R18:为每个按键提供一个分压值(最大电压值不得超过ADC输入最大值,可根据不同工作电压自行调整)

5.2原理

16个按键通过电阻分压使得每个按键触发后,接入ADC端口的电压值均不同,通过ADC采集后依次区分键值。

优点:仅需一个GPIO即可实现矩阵的功能,且无需消抖处理,响应速度极快,无任何迟滞。

缺点:需使用ADC功能,如本身无ADC功能需自行外挂ADC。程序处理略显麻烦,且需根据实时系统校准ADC键值。

5.3主要程序

ADC采集:

.c文件

.h文件

矩阵扫描:

.c文件

  

 .h文件

5.4仿真结果

按键1触发效果

按键5触发效果

6.总结

以上程序已在Proteus中测试验证成功,合理增键按键,可有效降低GPIO的使用率,提高程序效率,如果使用的单片机为3.3V供电,请将按键输入电压改为3.3V,以防损坏ADC。

如需完整工程链接,请关注点赞评论获取

如有不足,请指出!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值