历史上的今天

今天是:2024年11月12日(星期二)

2021年11月12日 | 51单片机实现矩阵键盘的组合按键触发

发布者:MysticalSoul 来源: eefocus关键字:51单片机  矩阵键盘 手机看文章 扫描二维码
随时随地手机看文章

一、使用proteus绘制简单的电路图,用于后续仿真

二、编写程序


/********************************************************************************************************************

---- @Project: Matrix-KEY

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200514

---- @ModifiedTime: 20200514

---- @Description: 16个按键中,每按一个按键都能触发一次蜂鸣器发出“滴”的一声。在同时按下S1和S16按键时,将会点亮一个LED灯。在同时按下S4和S13按键时,将会熄灭一个LED灯。

---- 单片机:AT89C52

********************************************************************************************************************/

#include "reg52.h"

/*——————宏定义——————*/

#define FOSC 11059200L

#define T1MS (65536-FOSC/12/1000)   /*1ms timer calculation method in 12Tmode*/

 

#define const_voice_short  80   /*蜂鸣器短叫的持续时间*/

 

/* 

*  注意:组合按键的去抖动延时const_key_time_comb千万不能等于单击按键

*  的去抖动延时const_key_time,否则组合按键会覆盖单击按键的触发。

*/

#define const_key_time  24    /*按键去抖动延时的时间*/

#define const_key_time_comb  28    /*组合按键去抖动延时的时间*/

/*——————变量函数定义及声明——————*/

/*行*/

sbit Key1 = P0^0; /*第一行输入*/

sbit Key2 = P0^1; /*第二行输入*/

sbit Key3 = P0^2; /*第三行输入*/

sbit Key4 = P0^3; /*第四行输入*/

 

/*列*/

sbit Key5 = P0^4; /*第一列输入*/

sbit Key6 = P0^5; /*第二列输入*/

sbit Key7 = P0^6; /*第三列输入*/

sbit Key8 = P0^7; /*第四列输入*/

 

/*定义蜂鸣器*/

sbit BUZZER = P2^7;

 

/*LED灯*/

sbit LED = P3^5;

 

unsigned char ucKeyStep = 1;   /*按键扫描步骤变量*/

 

unsigned char ucKeySec = 0;   /*被触发的按键编号*/

 

unsigned int  uiKeyTimeCnt[16] = 0; /*16个按键去抖动延时计数器*/

unsigned char ucKeyLock[16] = 0; /*16按键触发后自锁的变量标志*/

 

unsigned int  uiKeyTimeCnt_01_16 = 0; /*S1和S16组合按键去抖动延时计数器*/

unsigned char ucKeyLock_01_16 = 0; /*S1和S16组合按键触发后自锁的变量标志*/

 

unsigned int  uiKeyTimeCnt_04_13 = 0; /*S4和S13组合按键去抖动延时计数器*/

unsigned char ucKeyLock_04_13 = 0; /*S4和S13组合按键触发后自锁的变量标志*/

 

unsigned char ucRowRecord = 1; /*记录当前扫描到第几列了*/

 

unsigned int  uiVoiceCnt = 0;  /*蜂鸣器鸣叫的持续时间计数器*/

 

unsigned int uiKeyStatus = 0xffff; /*此变量每一位代表一个按键的状态,共16个按键。1代表没有被按下,0代表被按下。*/

 

/**

* @brief  定时器0初始化函数

* @param  无

* @retval 初始化T0

**/

void Init_T0(void)

{

TMOD = 0x01;                    /*set timer0 as mode1 (16-bit)*/

TL0 = T1MS;                     /*initial timer0 low byte*/

TH0 = T1MS >> 8;                /*initial timer0 high byte*/

}

/**

* @brief  外围初始化函数

* @param  无

* @retval 初始化外围

**/

void Init_Peripheral(void)

{

ET0 = 1;/*允许定时中断*/

TR0 = 1;/*启动定时中断*/

EA = 1;/*开总中断*/

 

}

 

/**

* @brief  初始化函数

* @param  无

* @retval 初始化单片机

**/

void Init(void)

{

BUZZER = 1;

LED = 0;

Init_T0();

}

/**

* @brief  扫描按键函数

* @param  无

* @retval 详细过程:

*  第一步:先把16个按键翻译成独立按键。

*  第二步: 再按独立按键的去抖动方式进行按键识别。

**/

void Key_Scan(void)

{

switch(ucKeyStep)

{

case 1: /*把16个按键的状态快速记录在uiKeyStatus变量的每一位中,相当于把矩阵键盘翻译成独立按键。*/

for(ucRowRecord = 1; ucRowRecord < 5; ucRowRecord ++)

{

if(ucRowRecord == 1) /*第一列输出低电平*/

{

Key5 = 0;

Key6 = 1;

Key7 = 1;

Key8 = 1;

/*如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态*/

if(Key1 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfffe; /*S1*/

}

if(Key2 == 0)

{

uiKeyStatus = uiKeyStatus & 0xffef; /*S5*/

}

if(Key3 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfeff; /*S9*/

}

if(Key4 == 0)

{

uiKeyStatus = uiKeyStatus & 0xefff; /*S13*/

}

}

else if(ucRowRecord == 2) /*第二列输出低电平*/

{

Key5 = 1;

Key6 = 0;

Key7 = 1;

Key8 = 1;

/*如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态*/

if(Key1 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfffd; /*S2*/

}

if(Key2 == 0)

{

uiKeyStatus = uiKeyStatus & 0xffdf; /*S6*/

}

if(Key3 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfdff; /*S10*/

}

if(Key4 == 0)

{

uiKeyStatus = uiKeyStatus & 0xdfff; /*S14*/

}

}

else if(ucRowRecord == 3) /*第三列输出低电平*/

{

Key5 = 1;

Key6 = 1;

Key7 = 0;

Key8 = 1;

/*如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态*/

if(Key1 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfffb; /*S3*/

}

if(Key2 == 0)

{

uiKeyStatus = uiKeyStatus & 0xffbf; /*S7*/

}

if(Key3 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfbff; /*S11*/

}

if(Key4 == 0)

{

uiKeyStatus = uiKeyStatus & 0xbfff; /*S15*/

}

}

else /*第四列输出低电平*/

{

Key5 = 1;

Key6 = 1;

Key7 = 1;

Key8 = 0;

/*如果是薄膜按键或者走线比较长的按键,此处应该加几个空延时,等待列输出信号稳定再判断输入的状态*/

if(Key1 == 0)

{

uiKeyStatus = uiKeyStatus & 0xfff7; /*S4*/

}

if(Key2 == 0)

{

uiKeyStatus = uiKeyStatus & 0xff7f; /*S8*/

}

if(Key3 == 0)

{

uiKeyStatus = uiKeyStatus & 0xf7ff; /*S12*/

}

if(Key4 == 0)

{

uiKeyStatus = uiKeyStatus & 0x7fff; /*S16*/

}

}

}

ucKeyStep = 2; /*切换到下一个运行步骤*/

break;

case 2: /*像独立按键一样进行去抖动和翻译。*/

if((uiKeyStatus & 0x0001) == 0x0001) /*说明1号键没有被按下来*/

{

uiKeyTimeCnt[0] = 0;

ucKeyLock[0] = 0;

}

else if(ucKeyLock[0] == 0)

{

uiKeyTimeCnt[0] ++;

if(uiKeyTimeCnt[0] > const_key_time)

{

uiKeyTimeCnt[0] = 0;

ucKeyLock[0] =1;

ucKeySec = 1;

}

}

if((uiKeyStatus & 0x0002) == 0x0002) /*说明2号键没有被按下来*/

{

uiKeyTimeCnt[1] = 0;

ucKeyLock[1] = 0;

}

else if(ucKeyLock[1] == 0)

{

uiKeyTimeCnt[1] ++;

if(uiKeyTimeCnt[1] > const_key_time)

{

uiKeyTimeCnt[1] = 0;

ucKeyLock[1] =1;

ucKeySec = 2;

}

}

if((uiKeyStatus & 0x0004) == 0x0004) /*说明3号键没有被按下来*/

{

uiKeyTimeCnt[2] = 0;

ucKeyLock[2] = 0;

}

else if(ucKeyLock[2] == 0)

{

uiKeyTimeCnt[2] ++;

if(uiKeyTimeCnt[2] > const_key_time)

{

uiKeyTimeCnt[2] = 0;

ucKeyLock[2] =1;

ucKeySec = 3;

}

}

if((uiKeyStatus & 0x0008) == 0x0008) /*说明4号键没有被按下来*/

{

uiKeyTimeCnt[3] = 0;

ucKeyLock[3] = 0;

}

else if(ucKeyLock[3] == 0)

{

uiKeyTimeCnt[3] ++;

if(uiKeyTimeCnt[3] > const_key_time)

{

uiKeyTimeCnt[3] = 0;

ucKeyLock[3] =1;

ucKeySec = 4;

}

}

if((uiKeyStatus & 0x0010) == 0x0010) /*说明5号键没有被按下来*/

{

uiKeyTimeCnt[4] = 0;

ucKeyLock[4] = 0;

}

else if(ucKeyLock[4] == 0)

{

uiKeyTimeCnt[4] ++;

if(uiKeyTimeCnt[4] > const_key_time)

{

uiKeyTimeCnt[4] = 0;

ucKeyLock[4] =1;

ucKeySec = 5;

}

}

if((uiKeyStatus & 0x0020) == 0x0020) /*说明6号键没有被按下来*/

{

uiKeyTimeCnt[5] = 0;

ucKeyLock[5] = 0;

}

else if(ucKeyLock[5] == 0)

{

uiKeyTimeCnt[5] ++;

if(uiKeyTimeCnt[5] > const_key_time)

{

uiKeyTimeCnt[5] = 0;

ucKeyLock[5] =1;

ucKeySec = 6;

}

}

if((uiKeyStatus & 0x0040) == 0x0040) /*说明7号键没有被按下来*/

{

uiKeyTimeCnt[6] = 0;

ucKeyLock[6] = 0;

}

else if(ucKeyLock[6] == 0)

{

uiKeyTimeCnt[6] ++;

if(uiKeyTimeCnt[6] > const_key_time)

{

uiKeyTimeCnt[6] = 0;

ucKeyLock[6] =1;

ucKeySec = 7;

}

}

if((uiKeyStatus & 0x0080) == 0x0080) /*说明8号键没有被按下来*/

{

uiKeyTimeCnt[7] = 0;

ucKeyLock[7] = 0;

}

else if(ucKeyLock[7] == 0)

{

uiKeyTimeCnt[7] ++;

if(uiKeyTimeCnt[7] > const_key_time)

{

uiKeyTimeCnt[7] = 0;

ucKeyLock[7] =1;

ucKeySec = 8;

}

}

if((uiKeyStatus & 0x0100) == 0x0100) /*说明9号键没有被按下来*/

{

uiKeyTimeCnt[8] = 0;

ucKeyLock[8] = 0;

}

else if(ucKeyLock[8] == 0)

{

uiKeyTimeCnt[8] ++;

if(uiKeyTimeCnt[8] > const_key_time)

{

uiKeyTimeCnt[8] = 0;

ucKeyLock[8] =1;

ucKeySec = 9;

}

}

if((uiKeyStatus & 0x0200) == 0x0100) /*说明10号键没有被按下来*/

{

uiKeyTimeCnt[9] = 0;

ucKeyLock[9] = 0;

}

else if(ucKeyLock[9] == 0)

{

uiKeyTimeCnt[9] ++;

if(uiKeyTimeCnt[9] > const_key_time)

{

uiKeyTimeCnt[9] = 0;

ucKeyLock[9] =1;

ucKeySec = 10;

}

}

if((uiKeyStatus & 0x0400) == 0x0400) /*说明11号键没有被按下来*/

{

uiKeyTimeCnt[10] = 0;

ucKeyLock[10] = 0;

}

else if(ucKeyLock[10] == 0)

{

uiKeyTimeCnt[10] ++;

if(uiKeyTimeCnt[10] > const_key_time)

{

uiKeyTimeCnt[10] = 0;

ucKeyLock[10] =1;

ucKeySec = 11;

}

}

if((uiKeyStatus & 0x0800) == 0x0800) /*说明12号键没有被按下来*/

{

uiKeyTimeCnt[11] = 0;

ucKeyLock[11] = 0;

}

else if(ucKeyLock[11] == 0)

{

uiKeyTimeCnt[11] ++;

if(uiKeyTimeCnt[11] > const_key_time)

{

uiKeyTimeCnt[11] = 0;

ucKeyLock[11] =1;

ucKeySec = 12;

}

}

if((uiKeyStatus & 0x1000) == 0x1000) /*说明13号键没有被按下来*/

{

uiKeyTimeCnt[12] = 0;

ucKeyLock[12] = 0;

}

else if(ucKeyLock[12] == 0)

{

uiKeyTimeCnt[12] ++;

if(uiKeyTimeCnt[12] > const_key_time)

{

uiKeyTimeCnt[12] = 0;

ucKeyLock[12] =1;

ucKeySec = 13;

}

}

if((uiKeyStatus & 0x2000) == 0x2000) /*说明14号键没有被按下来*/

{

uiKeyTimeCnt[13] = 0;

ucKeyLock[13] = 0;

}

else if(ucKeyLock[13] == 0)

{

uiKeyTimeCnt[13] ++;

if(uiKeyTimeCnt[13] > const_key_time)

{

uiKeyTimeCnt[13] = 0;

ucKeyLock[13] =1;

ucKeySec = 14;

}

}

if((uiKeyStatus & 0x4000) == 0x4000) /*说明15号键没有被按下来*/

{

uiKeyTimeCnt[14] = 0;

ucKeyLock[14] = 0;

}

else if(ucKeyLock[14] == 0)

{

uiKeyTimeCnt[14] ++;

if(uiKeyTimeCnt[14] > const_key_time)

{

uiKeyTimeCnt[14] = 0;

ucKeyLock[14] =1;

ucKeySec = 15;

}

}

if((uiKeyStatus & 0x8000) == 0x8000) /*说明16号键没有被按下来*/

{

uiKeyTimeCnt[15] = 0;

ucKeyLock[15] = 0;

}

else if(ucKeyLock[15] == 0)

{

uiKeyTimeCnt[15] ++;

if(uiKeyTimeCnt[15] > const_key_time)

{

uiKeyTimeCnt[15] = 0;

ucKeyLock[15] =1;

ucKeySec = 16;

}

}

if((uiKeyStatus & 0x8001) == 0x0000) /*S1和S16的组合键盘被按下。*/

{

if(ucKeyLock_01_16 == 0)

{

uiKeyTimeCnt_01_16 ++;

if(uiKeyTimeCnt_01_16 > const_key_time_comb)

{

uiKeyTimeCnt_01_16 = 0;

ucKeyLock_01_16 = 1;

ucKeySec = 17;

}

}

}

else

{

uiKeyTimeCnt_01_16 = 0; /*S1和S16组合按键去抖动延时计数器*/

[1] [2]
关键字:51单片机  矩阵键盘 引用地址:51单片机实现矩阵键盘的组合按键触发

上一篇:51单片机实现两片联级74HC595驱动16个LED灯
下一篇:51单片机实现矩阵键盘的单个触发

推荐阅读

”对于创业公司,第一要务是活下去,做这件事情有些忐忑。但是这是一个很重要的事情,量力而为,努力做好。”依图医疗总裁倪浩说。11月9日,医疗人工智能企业依图医疗在北京宣布启动“AI防癌地图”项目,计划在未来5年内投入1亿元项目资金,联合数百家医疗机构,覆盖19个省市自治区,以AI应用提升医疗机构服务供给能力。倪浩表示:“随着医疗AI在医疗机构...
基于最新版NI LabVIEW图形化系统设计软件,LabVIEW Robotics 环境继续提供工业级系统设计软件的能力。结合LabVIEWRobotics与LabVIEW 2010,新的编译器技术和优化得以实现,您可以自动受益于20倍的平均运行时间性能的提升。诸如导航,定位和视觉处理等计算密集型算法将可以更快地实现,提高您的机器人的性能。感知传感器驱动对任何自主或半自主的系统来说...
合格证的事情我稍作说明,由于管理办法调整后面确实很难获取。电池的数据可能需要更多的参考汽协信息发布会的数据(中国汽车动力电池产业创新联盟),从 10 月来看,总体的动力电池产量 9.9GWh,装车量 5.9GWh,这里面有着很大的差异。我们仔细来看看这个月的数据。01、月度信息的亮点10 月产量共计 9.9GWh,同比增长 47.9%,环比增长 14.5%。在这...
示波器对于电子工程师来说再熟悉不过了,纹波测试,检查频率,查看信号质量,测量上升时间、下降时间和过冲,并行总线解码分析等等它都能用到, 被誉为电子工程师的“眼睛”,而其中泰克品牌的示波器更是众多电子工程师备受青睐的品牌了,任何仪器使用久了,难免会生病,今天安泰测试就给大家分享一下泰克示波器出现黑屏原因及解决方法。泰克示波器出现黑...

史海拾趣

问答坊 | AI 解惑

HT1380串行时钟芯片

HT1380串行时钟芯片一般来说,HT系列的芯片在串行口的应用一直以来就是很好的在单片机 这个领域,串行时钟一直占着很重要的位置…

查看全部问答∨

毕业设计资料---气体检测

毕业设计资料---气体检测…

查看全部问答∨

Introduction to NI VeriStand

Introduction to NI VeriStand…

查看全部问答∨

奇怪了,请大家看下做标记的那几行代码

请大家看下下面打问号几行代码,抛开其功能不说,真的是奇怪了,我都看了又看,头都大了,就是不知道为什么,请朋友们指点下 #include<reg52.h>                     &nbs ...…

查看全部问答∨

显示驱动字体问题

各位,我的LCD屏换了片选脚后,凡是在打出字的部分,都有白色方框,这是什么问题,据说是什么透明度,什么没把数据写进去之类的原因,大家可否告诉我吗?…

查看全部问答∨

si4010有没有人用过,求探讨

si4010有没有人用过,求探讨,开发软件,调试软件,烧录工具等等…

查看全部问答∨

STM32的驱动库好用吗?效率高吗?优化的吗?准备上STM32

    N多年没买过开发板了,也没用过仿真器了。都是用软件编译调试好,直接ISP,然后通过串口命令开启调试信息的输出。    昨天买了块STM32F103全功能型开发板,他们的办事效率真低(深圳到广州通常当 ...…

查看全部问答∨

最适用于图像处理的TI公司DSP

请问用哪款TI的DSP板做图像处理比较好,要可以和Matlab连接使用,且可通过Real Time Work Shop工具箱自动生成代码,要是版本新一些就更好了 最近需要买一块板子,请大家多多给建议啊 谢谢…

查看全部问答∨

求IAR Embedded Workbench for MCS-51 完整版

各位高手,小弟求IAR Embedded Workbench for MCS-51完整版,有哪位高人有,能否分享一下。我的邮箱jinghongchen@126.com…

查看全部问答∨

猎头招聘

世界500强招聘压力传感器SAE,如有兴趣可发简历至:aerie.song@seek-jobs.com.cn 要求:至少五年以上相关工作经验,英文流利。…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved