0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

单片机矩阵按键的扫描、消抖及动作分离编程

2oON_changxuemc 来源:未知 作者:佚名 2017-12-31 09:13 次阅读

矩阵按键相当于4 组每组各4 个按键,一共是16个按键。那我们如何区分这些按键呢?想一下我们生活所在的地球,要想确定我们所在的位置,就要借助经纬线,而矩阵按键就是通过行线和列线来确定哪个按键被按下的。那么在程序中我们又如何进行这项操作呢?

前边讲过,按键按下通常都会保持 100ms 以上,如果在按键扫描中断中,我们每次让矩阵按键的一个 KeyOut 输出低电平,其它三个输出高电平,判断当前所有 KeyIn 的状态,下次中断时再让下一个 KeyOut 输出低电平,其它三个输出高电平,再次判断所有 KeyIn,通过快速的中断不停的循环进行判断,就可以最终确定哪个按键按下了,这个原理是不是跟数码管动态扫描有点类似?数码管我们在动态赋值,而按键这里我们在动态读取状态。至于扫描间隔时间和消抖时间,因为现在有 4 个 KeyOut 输出,要中断 4 次才能完成一次全部按键的扫描,显然再采用 2ms 中断判断 8 次扫描值的方式时间就太长了(2*4*8=64ms),那么我们就改用 1ms 中断判断 4 次采样值,这样消抖时间还是 16ms(1*4*4)。下面就用程序实现出来,程序循环扫描板子上的 K1~K16 这 16 个矩阵按键,分离出按键动作并在按键按下时把当前按键的编号显示在一位数码管上(用 0~F 表示,显示值=按键编号-1)。

#include

sbit ADDR0 = P1^0;

sbit ADDR1 = P1^1;

sbit ADDR2 = P1^2;

sbit ADDR3 = P1^3;

sbit ENLED = P1^4;

sbit KEY_IN_1 = P2^4;

sbit KEY_IN_2 = P2^5;

sbit KEY_IN_3 = P2^6;

sbit KEY_IN_4 = P2^7;

sbit KEY_OUT_1 = P2^3;

sbit KEY_OUT_2 = P2^2;

sbit KEY_OUT_3 = P2^1;

sbit KEY_OUT_4 = P2^0;

unsigned char code LedChar[] = { //数码管显示字符转换表

0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,

0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x8E

};

unsigned char KeySta[4][4] = { //全部矩阵按键的当前状态

{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}

};

void main(){

unsigned char i, j;

unsigned char backup[4][4] = { //按键值备份,保存前一次的值

{1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}, {1, 1, 1, 1}

};

EA = 1; //使能总中断

ENLED = 0; //选择数码管 DS1 进行显示

ADDR3 = 1;

ADDR2 = 0;

ADDR1 = 0;

ADDR0 = 0;

TMOD = 0x01; //设置 T0 为模式 1

TH0 = 0xFC; //为 T0 赋初值 0xFC67,定时 1ms

TL0 = 0x67;

ET0 = 1; //使能 T0 中断

TR0 = 1; //启动 T0

P0 = LedChar[0]; //默认显示 0

while (1){

for (i=0; i<4; i++){ //循环检测 4*4 的矩阵按键

for (j=0; j<4; j++){

if (backup[i][j] != KeySta[i][j]){ //检测按键动作

if (backup[i][j] != 0){ //按键按下时执行动作

P0 = LedChar[i*4+j]; //将编号显示到数码管

}

backup[i][j] = KeySta[i][j]; //更新前一次的备份值

}

}

}

}

}

/* T0 中断服务函数,扫描矩阵按键状态并消抖 */

void InterruptTimer0() interrupt 1{

unsigned char i;

static unsigned char keyout = 0; //矩阵按键扫描输出索引

static unsigned char keybuf[4][4] = { //矩阵按键扫描缓冲区

{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF},

{0xFF, 0xFF, 0xFF, 0xFF}, {0xFF, 0xFF, 0xFF, 0xFF}

};

TH0 = 0xFC; //重新加载初值

TL0 = 0x67;

//将一行的 4 个按键值移入缓冲区

keybuf[keyout][0] = (keybuf[keyout][0] << 1) | KEY_IN_1;

keybuf[keyout][1] = (keybuf[keyout][1] << 1) | KEY_IN_2;

keybuf[keyout][2] = (keybuf[keyout][2] << 1) | KEY_IN_3;

keybuf[keyout][3] = (keybuf[keyout][3] << 1) | KEY_IN_4;

//消抖后更新按键状态

for (i=0; i<4; i++){ //每行 4 个按键,所以循环 4 次

//连续 4 次扫描值为 0,即 4*4ms 内都是按下状态时,可认为按键已稳定的按下

if ((keybuf[keyout][i] & 0x0F) == 0x00){

KeySta[keyout][i] = 0;

//连续 4 次扫描值为 1,即 4*4ms 内都是弹起状态时,可认为按键已稳定的弹起

}else if ((keybuf[keyout][i] & 0x0F) == 0x0F){

KeySta[keyout][i] = 1;

}

}

//执行下一次的扫描输出

keyout++; //输出索引递增

keyout = keyout & 0x03; //索引值加到 4 即归零

//根据索引,释放当前输出引脚,拉低下次的输出引脚

switch (keyout){

case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;

case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;

case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;

case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;

default: break;

}

}这个程序完成了矩阵按键的扫描、消抖、动作分离的全部内容,希望大家认真研究一下,彻底掌握矩阵按键的原理和应用方法。在程序中还有两点值得说明一下。

首先,可能你已经发现了,中断函数中扫描 KeyIn 输入和切换 KeyOut 输出的顺序与前面提到的顺序不同,程序中我首先对所有的 KeyIn 输入做了扫描、消抖,然后才切换到了下一次的 KeyOut 输出,也就是说我们中断每次扫描的实际是上一次输出选择的那行按键,这是为什么呢?因为任何信号从输出到稳定都需要一个时间,有时它足够快而有时却不够快,这取决于具体的电路设计,我们这里的输入输出顺序的颠倒就是为了让输出信号有足够的时间(一次中断间隔)来稳定,并有足够的时间来完成它对输入的影响,当你的按键电路中还有硬件电容消抖时,这样处理就是绝对必要的了,虽然这样使得程序理解起来有点绕,但它的适应性是最好的,换个说法就是,这段程序足够“健壮”,足以应对各种恶劣情况。

其次,是一点小小的编程技巧。注意看 keyout = keyout & 0x03;这一行,在这里我是要让keyout 在 0~3 之间变化,加到 4 就自动归零,按照常规你可以用前面讲过的 if 语句轻松实现,但是你现在看一下这样程序是不是同样可以做到这一点呢?因为 0、1、2、3 这四个数值正好占用 2 个二进制的位,所以我们把一个字节的高 6 位一直清零的话,这个字节的值自然就是一种到 4 归零的效果了。看一下,这样一句代码比 if 语句要更为简洁吧,而效果完全一样。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6031

    文章

    44509

    浏览量

    632528
  • 编程
    +关注

    关注

    88

    文章

    3585

    浏览量

    93560
  • 矩阵按键
    +关注

    关注

    0

    文章

    28

    浏览量

    8359

原文标题:单片机矩阵按键扫描程序

文章出处:【微信号:changxuemcu,微信公众号:畅学单片机】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    单片机编程语言有哪些选择

    单片机(Microcontroller Unit,MCU)编程是指为单片机编写程序的过程,这些程序控制单片机的行为和功能。单片机广泛应用于嵌
    的头像 发表于 11-01 14:13 309次阅读

    基于FPGA实现按键处理

    引言: 按键在电子产品中经常用到,由于按键的机械特性,按键在闭合或松开的瞬间伴随着一连串的抖动,这样的抖动将直接影响设计系统的稳定性。因此,必须对抖动进行处理。本文介绍如何在FPGA中实现按键
    的头像 发表于 10-24 14:54 153次阅读
    基于FPGA实现<b class='flag-5'>按键</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>处理

    两种常见的硬件实现方式

    由于机械按键在操作过程中会产生抖动现象,这种抖动信号如果不加以处理,就可能导致单片机等电子设备误判按键状态,从而引发错误操作。本文将详细介绍两种常见的硬件
    的头像 发表于 09-25 16:54 762次阅读
    两种常见的硬件<b class='flag-5'>消</b><b class='flag-5'>抖</b>实现方式

    为什么按键那么重要

    按键稳定性和可靠性对于整个系统的性能至关重要。然而,由于机械触点的弹性作用,按键在闭合和断开时往往伴随着抖动现象。这种抖动虽然对人类来说微不足道,但对于高速运行的单片机而言,却可能导致严重的误判
    的头像 发表于 09-25 16:50 396次阅读
    为什么<b class='flag-5'>按键</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>那么重要

    如何在FPGA中实现按键

    在FPGA(现场可编程门阵列)中实现按键是一个重要的设计环节,特别是在处理用户输入时,由于物理按键的机械特性和电气特性,
    的头像 发表于 08-19 18:15 1349次阅读

    怎么做按键

    大家是怎么做按键的 我是用一定时器做20ms定时,定时到在中断里设专门标志(20ms是否到,初始化为0),在主循环里当按键按下时在判断此标志,为0,就开启定时中断,而后返回主流程,
    发表于 04-28 07:39

    AVR单片机外接16M晶振和STM32F103外接8MHZ运行速度哪一个更快?

    同样的程序进行比较: AVR单片机外接16M晶振:运行程序是矩阵按键扫描采用定时器中断100ms扫描一次、还有串口接收中断程序1S接收一次运
    发表于 04-23 07:43

    stm8触摸感应按键是怎样扫描的?

    stm8触摸感应 按键是怎样扫描,和怎样
    发表于 04-01 06:17

    fpga编程单片机编程的区别

    FPGA编程单片机编程的主要区别体现在以下几个方面。
    的头像 发表于 03-14 17:16 920次阅读

    为什么要进行按键按键抖动的原理 按键的方法

    按键通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也
    的头像 发表于 02-17 17:07 1.7w次阅读
    为什么要进行<b class='flag-5'>按键</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>?<b class='flag-5'>按键</b>抖动的原理 <b class='flag-5'>按键</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的方法

    单片机编程实例总结

    单片机编程实例总结
    的头像 发表于 01-16 09:17 978次阅读

    单片机如何读取键盘数据

    单片机作为一种嵌入式系统,往往需要与外部设备进行交互。其中之一的重要环节就是通过键盘读取输入的数据。在本文中,我们将详细介绍如何使用单片机读取键盘数据,包括键盘的原理、扫描方式、连接方式以及
    的头像 发表于 01-04 17:09 1560次阅读

    单片机按键的原理和方法详解

    通常的按键所用开关为机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断开时也不会一下子断开。因而在闭合及断开的瞬间均伴随有一连串的抖动,为了不产生这种现象而作的措施就是按键
    的头像 发表于 12-22 10:06 8416次阅读
    <b class='flag-5'>单片机</b><b class='flag-5'>按键</b><b class='flag-5'>消</b><b class='flag-5'>抖</b>的原理和方法详解

    单片机按键切换模式命令

    单片机按键切换模式命令是指在单片机系统中,通过按下按键来切换系统工作模式的命令。这种命令通常用于控制系统的状态和功能,使系统能够根据用户的需求进行灵活的切换,提供多种工作模式选择。本文
    的头像 发表于 12-15 10:31 2804次阅读

    单片机按键切换模式怎么设置

    单片机作为一种微处理器,在各种嵌入式系统中扮演着核心控制器的角色。其中,按键输入作为单片机控制中常见的交互方式,实现模式切换是常见的需求。本文将详细介绍如何在单片机中实现
    的头像 发表于 12-13 11:07 3733次阅读