如图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{ /*如果信号线是低电平*/ if ((ib_HighTime>MIN_SynTime)&&(ib_HighTime ib_HandState=WAIT_HIGH; else ib_HandState=RESTART; /*否则复位接收程序*/ ib_HighTime=0; } break; case WAIT_HIGH: /*等待数据位的上升沿的情况*/ if (Hbit){ /*如果检测到一个上升沿*/ if ((ib_LowTime>MIN_L_Time)&&(ib_LowTime ib_HandState=WAIT_LOW; } else ib_HandState=RESTART; /*否则复位接收程序*/ ib_LowTime=0; } else{ /*如果仍为低电平*/ ib_LowTime++; /*低电平时间计数器加一*/ if (ib_LowTime>MAX_L_Time) /*如果低电平时间超长,则复位寄售程序*/ ib_HandState=RESTART; } break; case WAIT_LOW: /*等待数据下降沿的情况*/ if (Hbit){ /*如果仍是高电平*/ ib_HighTime++; /*高电平数据计数器加一*/ if (ib_HighTime>MAX_H_Time) /*如果高电平实际超长,则复位接收程序*/ ib_HandState=RESTART; } else{ /*如果收到一个下降沿*/ ib_KeyCode[ib_KeyPoint]>>=1; /*接收数据字节右移一位*/ if ((ib_HighTime>MIN_B1TIME)&&(ib_HighTime ib_KeyCode[ib_KeyPoint]+=0x80; } ib_BitCount++; /*接收数据位计数器加一*/ if (ib_BitCount>7) { /*如果接收满一个字节*/ ib_BitCount=0; /*清空位计数器*/ ib_KeyPoint++; /*指向下一个字节*/ if (ib_KeyPoint>3) /*如果接收完整个数据*/ { //unsigned char i; NewKey=TRUE; /*置有新键按下标志*/ //for (i=0;i<4;i++){ //TI=0; //SBUF=ib_KeyCode; //while(!TI); //TI=0; //} //ib_HandState=RESTART; } } ib_HighTime=0; /*将高电平时间计数器清零*/ ib_HandState=WAIT_HIGH; /*设定系统为等待上升沿状态*/ } break; default:break; } } if (ib_HandState==RESTART){ /*如果程序处于复位状态*/ ib_LowTime=0; /*复位各项参数*/ ib_HighTime=0; ib_HandState=LEAD; ib_KeyCode[0]=0; ib_KeyCode[1]=0; ib_KeyCode[2]=0; ib_KeyCode[3]=0; ib_KeyPoint=0; ib_BitCount=0; NewKey=FALSE; } } 好多遥控器(无线,红外)发射数据都是PPM调制的,以上程序稍微改动后可以应用于各种PPM调制信号的场合。软件区提供了一个压缩包下载,其中有sc6121的中文数据手册,上面程序的头文件和初始化部分. |
上一篇:c51脉宽测量法实现无线遥控解码
下一篇:12864液晶显示C语言程序设计实例
推荐阅读最新更新时间:2024-03-16 15:21