接4×4矩阵键盘
扫描二维码
随时随地手机看文章
如图4.14.2所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序号。对应的按键的序号排列如图4.14.1所示
500)this.width=500'>300)this.width=300" border=0>
图4.14.1
2.硬件电路原理图
500)this.width=500'>300)this.width=300" border=0>
图4.14.2
3.系统板上硬件连线
(1. 把“单片机系统“区域中的P3.0-P3.7端口用8芯排线连接到“4X4行列式键盘”区域中的C1-C4 R1-R4端口上;
(2. 把“单片机系统”区域中的P0.0/AD0-P0.7/AD7端口用8芯排线连接到“四路静态数码显示模块”区域中的任一个a-h端口上;要求:P0.0/AD0对应着a,P0.1/AD1对应着b,……,P0.7/AD7对应着h。
4.程序设计内容
(1. 4×4矩阵键盘识别处理
(2. 每个按键有它的行值和列值 ,行值和列值的组合就是识别这个按键的编码。矩阵的行线和列线分别通过两并行接口和CPU通信。每个按键的状态同样需变成数字量“0”和“1”,开关的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么;还要消除按键在闭合或断开时的抖动。两个并行口中,一个输出扫描码,使按键逐行动态接地,另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
5.程序框图
500)this.width=500'>300)this.width=300" border=0>
2楼 Juliet发表于2006-5-10 11:22:00 设计中你是否遇到过这样的问题:你的产品上要求有几十个按键,处理器IO口很少,PCB的面积又有严格限制,或者你要严格控制成本,无法使用象7219那样的扩展芯片,怎么解决这个问题?
下面有个方法,大家都见过遥控器吧,上面不但有几十个按键,而且功能还挺多什么去抖动,同时按键处理都有了,最最重要的是控制芯片体积小,价格便宜(也就1,2块钱),外围器件少。。不过具体实现起来有点小麻烦,这类芯片的信号一般是PPM输出的,通常为了有更远的遥控距离,按键编码调制在一个38k左右的载波上。所以我们不得不再为这个方案多花上1块钱,加一个有烂运放做的低通滤波器,将载波滤除后在接到单片机的IO脚上,由于两个频率相差较多,这个滤波器并不难做。我使用LM324做的。其中有两级低通,一个比较器。
当你的示波器上出现一串可爱的几百赫兹的方波时,你的硬件就成功啦。既然只用一条IO就扩展了几十个按键,软件上自然会多费些事,此类芯片发码都是有引导头,同步部分,用户码,键码等部分组成,有三十多个位,具体可参照sc6121资料。下面时一个完整的接收程序,针对的芯片是sc6121,处理器89c51
///////////////////////////////////////////////////////////////////////////////
/*定时器1中断服务程序*/
/*
每100us中断一次,定时检测HangSignal线上的电平状态,根据6121的砝码格式译出用户码键码.\
ib_KeyCode[0] 用户码低位
,ib_KeyCode[1]用户码高位
,ib_KeyCode[2]键码
,ib_KeyCode[3]键码的反码
*/
/////////////////////////////////////////////////////////////////////////////////////
void HandIn() interrupt 3 using 3 {
unsigned char tempbit=0;
bit Hbit;
Hbit=HandSignal; /*采样信号线*/
if (NewKey==FALSE){ /*如果上一次按键事件已经北处理*/
switch (ib_HandState){ /*根据接收状态散转*/
case LEAD: /*引导头接收情况*/
if (Hbit){ /*如果信号线是高电平*/
if ((ib_LowTime>MIN_LeadTime)&&(ib_LowTime ib_HandState=START; /*正确进入同步头接收状态*/ else ib_HandState=RESTART; /*否则复位接收程序*/ ib_LowTime=0; /*清除低电平时间计数*/ } else{ /*如果信号是低电平*/ ib_LowTime++; /*增加低电平时间计数器*/ if (ib_LowTime>MAX_LeadTime) /*判断低电平时间是否超时*/ ib_HandState=RESTART; /*是的话复位接收程序*/ } break; case START: /*同步头接收情况*/ if(Hbit){ /*如果信号线是高电平*/ ib_HighTime++; /*高电平时间计数器加一*/ if (ib_HighTime>MAX_SynTime) /*如果高电平时间超长,复位接收程序*/ ib_HandState=RESTART; } else{