历史上的今天

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

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

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

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

二、编写程序


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

---- @Project: Matrix-KEY

---- @File: main.c

---- @Edit: ZHQ

---- @Version: V1.0

---- @CreationTime: 20200508

---- @ModifiedTime: 20200513

---- @Description: 16个按键中,每按一个按键都能触发一次蜂鸣器发出“滴”的一声。

---- 单片机:AT89C52

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

#include "reg52.h"

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

#define FOSC 11059200L

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

 

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

 

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

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

/*行*/

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;

 

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

 

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

 

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

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

 

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

 

unsigned int  uiVoiceCnt = 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;

Init_T0();

}

/**

* @brief  扫描按键函数

* @param  无

* @retval 矩阵按键扫描的详细过程:

*  先输出某一列低电平,其它三列输出高电平,这个时候再分别判断输入的四行,

*  如果发现哪一行是低电平,就说明对应的某个按键被触发。依次分别输出另外三列

*  中的某一列为低电平,再分别判断输入的四行,就可以检测完16个按键。内部详细的

*  去抖动处理方法跟独立按键去抖动方法是一样的。

**/

void Key_Scan(void)

{

switch(ucKeyStep)

{

case 1: /*按键扫描输出第ucRowRecord列低电平*/

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

{

Key5 = 0;

Key6 = 1;

Key7 = 1;

Key8 = 1;

}

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

{

Key5 = 1;

Key6 = 0;

Key7 = 1;

Key8 = 1;

}

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

{

Key5 = 1;

Key6 = 1;

Key7 = 0;

Key8 = 1;

}

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

{

Key5 = 1;

Key6 = 1;

Key7 = 1;

Key8 = 0;

}

uiKeyTimeCnt = 0; /*按键延时计数器清零*/

ucKeyStep ++; /*切换到下一步*/

break;

case 2: /*此处的小延时用来等待刚才列输出信号稳定,再判断输入信号。不是去抖动延时。*/

uiKeyTimeCnt ++;

if(uiKeyTimeCnt > 1)

{

uiKeyTimeCnt = 0;

ucKeyStep ++; /*切换到下一步*/

}

break;

case 3: /*判断是否有键按下*/

if(Key1 == 1 && Key2 == 1 && Key3 == 1 && Key4 == 1) /*如果没有按键按下*/

{

ucKeyStep = 1; /*返回第一步,重新进行扫描*/

ucKeyLock = 0; /*自锁标志清零*/

uiKeyTimeCnt = 0; /*按键去抖动延时计数器清零*/

ucRowRecord ++; /*扫描下一列*/

if(ucRowRecord > 4)

{

ucRowRecord = 1; /*依次输出完四列之后,继续从第一列开始输出低电平*/

}

}

else if(ucKeyLock == 0) /*有按键按下,且是第一次触发*/

{

if(Key1 == 0 && Key2 == 1 && Key3 == 1 && Key4 == 1)

{

uiKeyTimeCnt ++;

if(uiKeyTimeCnt > const_key_time) /*去抖*/

{

uiKeyTimeCnt = 0;

ucKeyLock = 1; /*自锁按键置位,避免一直触发,只有松开按键,此标志位才会被清零*/

if(ucRowRecord == 1)

{

ucKeySec = 1; /*触发1号键*/

}

else if(ucRowRecord == 2)

{

ucKeySec = 2; /*触发2号键*/

}

else if(ucRowRecord == 3)

{

ucKeySec = 3; /*触发3号键*/

}

else

{

ucKeySec = 4; /*触发4号键*/

}

}

}

else if(Key1 == 1 && Key2 == 0 && Key3 == 1 && Key4 == 1)

{

uiKeyTimeCnt ++;

if(uiKeyTimeCnt > const_key_time) /*去抖*/

{

uiKeyTimeCnt = 0;

ucKeyLock = 1; /*自锁按键置位,避免一直触发,只有松开按键,此标志位才会被清零*/

if(ucRowRecord ==7)

{

ucKeySec = 5; /*触发5号键*/

}

else if(ucRowRecord == 2)

{

ucKeySec = 6; /*触发6号键*/

}

else if(ucRowRecord == 3)

{

ucKeySec = 7; /*触发7号键*/

}

else

{

ucKeySec = 8; /*触发8号键*/

}

}

}

else if(Key1 == 1 && Key2 == 1 && Key3 == 0 && Key4 == 1)

{

uiKeyTimeCnt ++;

if(uiKeyTimeCnt > const_key_time) /*去抖*/

{

uiKeyTimeCnt = 0;

ucKeyLock = 1; /*自锁按键置位,避免一直触发,只有松开按键,此标志位才会被清零*/

if(ucRowRecord == 1)

{

ucKeySec = 9; /*触发9号键*/

}

else if(ucRowRecord == 2)

{

ucKeySec = 10; /*触发10号键*/

}

else if(ucRowRecord == 3)

{

ucKeySec = 11; /*触发11号键*/

}

else

{

ucKeySec = 12; /*触发12号键*/

}

}

}

else if(Key1 == 1 && Key2 == 1 && Key3 == 1 && Key4 == 0)

{

uiKeyTimeCnt ++;

if(uiKeyTimeCnt > const_key_time) /*去抖*/

{

uiKeyTimeCnt = 0;

ucKeyLock = 1; /*自锁按键置位,避免一直触发,只有松开按键,此标志位才会被清零*/

if(ucRowRecord == 1)

{

ucKeySec = 13; /*触发13号键*/

}

else if(ucRowRecord == 2)

{

ucKeySec = 14; /*触发14号键*/

}

else if(ucRowRecord == 3)

{

ucKeySec = 15; /*触发15号键*/

}

else

{

ucKeySec = 16; /*触发16号键*/

}

}

}

}

break;

}

}

/**

* @brief  按键服务函数

* @param  无

* @retval 根据扫描得到的值,进行数据处理

**/

void key_Service(void)

{

switch(ucKeySec)

{

case 1: /*1号键*/

case 2: /*2号键*/

case 3: /*3号键*/

case 4: /*4号键*/

case 5: /*6号键*/

case 7: /*7号键*/

case 8: /*8号键*/

case 9: /*9号键*/

case 10: /*10号键*/

case 11: /*11号键*/

case 12: /*12号键*/

case 13: /*13号键*/

case 14: /*14号键*/

case 15: /*15号键*/

case 16: /*16号键*/

uiVoiceCnt = const_voice_short; /*按键声音触发,滴一声就停。*/

ucKeySec = 0; /*响应按键服务处理程序后,按键编号清零,避免一致触发*/

break;

}

}

/**

* @brief  定时器0中断函数

* @param  无

* @retval 无

**/

void ISR_T0(void) interrupt 1

{

TF0 = 0;  /*清除中断标志*/

  TR0 = 0; /*关中断*/

/*扫描按键*/

Key_Scan();

if(0 != uiVoiceCnt)

{

uiVoiceCnt --;

BUZZER = 0;

}

else

{

BUZZER = 1;

}

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

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

  TR0 = 1; /*开中断*/

}

/**

* @brief  延时函数

* @param  无

* @retval 无

**/

void Delay_Long(unsigned int uiDelayLong)

{

   unsigned int i;

   unsigned int j;

   for(i=0;i   {

      for(j=0;j<500;j++)  /*内嵌循环的空指令数量*/

          {

             ; /*一个分号相当于执行一条空语句*/

          }

   }

}

/*——————主函数——————*/

/**

* @brief  主函数

* @param  无

* @retval 实现LED灯闪烁

**/

void main()

{

/*单片机初始化*/

Init();

/*延时,延时时间一般是0.3秒到2秒之间,等待外围芯片和模块上电稳定*/

Delay_Long(100);

/*单片机外围初始化*/

Init_Peripheral();

while(1)

{

/*按键服务函数*/

key_Service();

}

}


三、仿真实现

关键字:51单片机  矩阵键盘  单个触发 引用地址:51单片机实现矩阵键盘的单个触发

上一篇:51单片机实现矩阵键盘的组合按键触发
下一篇:51单片机实现按住一个独立按键不松手的加速匀速触发

推荐阅读

据长江日报报道,10日,首家京东X未来餐厅在天津开业,从点餐、配菜、炒菜、传菜到用餐、结算,智能机器人和人工智能后台贯穿餐厅运营全过程。消费者点餐后,后台将炒菜任务分配给烹饪机器人,开始菜品的烹制,最后传菜机器人会将烹制好的菜品送到餐桌前,目前共有40多道菜可供选择。京东相关负责人表示,首家餐厅运营成熟后,将向包括武汉在内的其他城市...
  电磁流量计主要用于测量封闭管道中的导电液体和浆液中的体积流量。包括酸、碱、盐等强腐蚀性的液体。电磁流量计的正确选择是确保电磁流量计正常运行先决条件。但电磁流量计的正确接线也是至关重要的。下面我们讲解下电磁流量计接线方式图以及电磁流量计如何接线。  一体式电磁流量计接线图  分体式电磁流量计接线图  注:  弱采用分体安装,连...
宜普电源转换公司(EPC)宣布推出170 V、6.8 mΩ的EPC2059氮化镓场效应晶体管(eGaN®FET),与目前用于高性能48 V同步整流的器件相比,EPC为设计工程师提供更小型化、更高效、更可靠且成本更低的器件。 宜普电源转换公司是增强型硅基氮化镓(eGaN)功率场效应晶体管和集成电路的全球领先供应商,致力提高产品性能且降低可发货的氮化镓晶体管的成本,最...
这两周,松灵机器人持续上新新品! 可以看出,松灵机器人新发布的系列底盘都有共同的特点:性能升级,价格降低。车身和结构设计更加精简强悍,以及更加细分深耕于机器人应用的每一个复杂路况组合。 今天又给大家带来两款新品上新:尺寸更小的IP67防护级BUNKER ni和覆盖复杂城市路况和商业级速度的HUNR SE。 一起看看这两款新品有哪些新的不一样的惊...

史海拾趣

问答坊 | AI 解惑

HT1380串行时钟芯片

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

查看全部问答∨

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

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

查看全部问答∨

Introduction to NI VeriStand

Introduction to NI VeriStand…

查看全部问答∨

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

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

查看全部问答∨

evc托盘编程

使用evc4.0编写一个系统托盘,就是我的程序起来之后,不显示对话框,自动出现一个图标到右下角,通过双机图标,可以弹出对话框。 右键单击右下角图标,可以弹出一个菜单。 不知道如何实现这些功能,请兄弟姐妹们帮个忙!…

查看全部问答∨

si4010有没有人用过,求探讨

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

查看全部问答∨

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

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

查看全部问答∨

求IAR Embedded Workbench for MCS-51 完整版

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

查看全部问答∨

猎头招聘

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

查看全部问答∨

批评英蓓特,一个细节反映出的不认真

还是说说今天参加安富利的“ARM研讨会”,参观展台时,逛到了英蓓特(EMBEST)那里。大家可能知道,这家公司就是专门围绕ARM生存的,有很多ARM开发板。我在看到英蓓特展台的易拉宝时,楞了一下,原来上面罗列的产品线时,赫然有“Luminary系列”。 ...…

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

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

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

更多每日新闻
更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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