单片机行列式键盘的工作原理 单片机学习第四课
- 需要判断是否有按键按下,如果有,那么进入下一个动作。
- 识别是哪一个按键被按下?并求出相应的键值。
- 根据键值找到相应的按键处理程序入口即可。
按键可以分为(独立按键,和矩阵键盘)
矩阵可以用做按键较多的案例。比如,计算器的编写
独立按键用来实现一些用到按键比较少的案例。
矩阵键盘
PCB板
二,键盘的工作原理键盘中的一个按键开关的两端分别连接在行线和列线上,列线接地,行线通过电阻接到 5v上。当开关的机械触点断开,闭合,其行线的电压输出波形如下图(图二)
电压输出波形图
在第二张图中,我们可以看到,t1和t3分别为按键的闭合与断开过程中的抖动时间段,而且呈现一看连串的负脉冲,我们注意到这个抖动时间的长短与开关的机械特性有关,一般在我们按下按键后年,一般为5-10ms的样子。t2为一个稳定的闭合时间段。注意:在设计时,应该考虑到消抖(软件和硬件)
三,按键的识别高电平(低电平有效)按键是否能够闭合,这与行线的输出电压有关系,其实就是反应在行线的输出电压的高电平还是低电平,单片机通过对行线电平的高低状态的检测,就可以确认按键是否按下与松开,为了确保单片机对一次按键发生的动作只确认一次按键有效,那么必须要消除抖动期的t1与t2的影响。
四,消除按键机械带来的抖动我们一般都是采用两种方案:
- 软件消抖
主要的一个思想还是:当检测到有按键按下时,对该键对应的行线为低电平,且执行一段延时函数,大约为10ms的延时,确认该行线电平是否为低电平,如果仍为低电平,那么我们就确认确实有按键按下了。当按键被松开时,行线的低电平变为高电平,执行一短延时10ms的程序后,检测该行线为高电平,说明按键确实已经松开。
2.采用专用的键盘/显示器接口芯片。处理电路中的抖动。
五,键盘扫描瑜工作原理
pcb原理图
具体原理说明:
六,行列式键盘实战
1.简单的操作
①、通过仿真电路中的行列式键盘输入任意6个按键,要求识别按键后实现在6位数码管上显示按键编号;
②、数码管显示利用动态扫描方法;
③、在按键检测处理程序中增加软件消抖部分。
2.仿真电路图
如何建立工程与仿真
慧净开发板的键盘展示
3.源代码
#include<reg51.h> #include<intrish.h> #define uchar unsigned char #define schar signed char sbit DUAN=P2^6; sbit WEI=P2^7; sbit L1=P1^0; sbit L2=P1^1; sbit L3=P1^2; sbit L4=P1^3; uchar data password[6] ; uchar data led[6]={16,16,16,16,16,16}; uchar data ledwei[6]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf}; uchar data displaytab[17]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; uchar n=0; void delay() { uchar x,y; for(x=2;x>0;x--) for(y=250;y>0;y--); } void delay10ms() { uchar x,y; for(x=20;x>0;x--) for(y=250;y>0;y--); } void display() { uchar i; for(i=0;i<6;i ) { P0=displaytab[led[i]]; DUAN=1; DUAN=0; P0=ledwei[i]; WEI=1; WEI=0; delay(); P0=0xff; WEI=1; WEI=0; } } void keyscan() { uchar temp,m; P1=0xef; for(m=0;m<=3;m ) { if(L1==0) { delay10ms(); if(L1==0) { password[n]= m*4 0; n ; while(!L1); delay10ms(); while(!L1) ; } } if(L2==0) { delay10ms(); if(L2==0) { password[n]=m*4 1; n ; while(!L2); delay10ms(); while(!L2); } } if(L3==0) {delay10ms(); if(L3==0) { password[n]=m*4 2; n ; while(!L3); delay10ms(); while(!L3); } } if(L4==0) {delay10ms(); if(L4==0) { password[n]=m*4 3; n ; while(!L4); delay10ms(); while(!L4) ; } } temp=P1; temp=temp|0x0f; temp=temp<<1; temp=temp|0x0f; P1=temp; } } void main() { uchar j; while(1) { display(); keyscan(); if(n==6) { n=0; for(j=0;j<=5;j ) { led[j]=password[j]; } } } }
4.运行程序后,随意按下键盘上的六个键,数码管上会显示相应的数值。附上计算器的源代码(大家可以试试)①原理图
②代码(注释乱码,其他正常)
main程序#include <reg52.h> #include "key.h" #include "smg.h" #include "timer.h" int main(void) { u8 ret = 0; Show_Number(0); while(1) { Smg_Dymainc( ); Jz_Key_Scan( ); } }
按键 key.c#include "key.h" u8 code KeyCode[16] = { 0x31, 0x32, 0x33, 0x26, 0x34, 0x35, 0x36, 0x25, 0x37, 0x38, 0x39, 0x28, 0x30, 0x1B, 0x0D, 0x27}; void Key_Delay(u16 n) { u16 x, y; for(x = 0; x < n; x ) { for(y = 0; y < 110; y ); } } u8 buf[5][3]; u8 Key_Scan(void) { static u8 key_sta = 0; static char i = 0; if((KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0) && (key_sta == 0)) { Key_Delay(10); if((KEY1 == 0 || KEY2 == 0 || KEY3 == 0 || KEY4 == 0) && (key_sta == 0)) { if(KEY1 == 0) { key_sta = 1; TR0 = !TR0; }else if(KEY2 == 0) { key_sta = 1; buf[i][0] = msec; buf[i][1] = sec; buf[i][2] = min; i ;//1 2 if(i >= 5) i = 0; }else if(KEY3 == 0) { key_sta = 1; i--; if(i < 0) i = 0; msec = buf[i][0]; sec = buf[i][1]; min = buf[i][2]; }else if(KEY4 == 0) { key_sta = 1; msec = 0; sec = 0; min = 0; } } } else if(KEY1 == 1 && KEY2 == 1 && KEY3 == 1 && KEY4 == 1)//û°´¼ü°´Ï { key_sta = 0; } return 0; } u8 Jz_Key_Scan(void) { u8 temp = 0xff; static u8 flag = 0; P1 = 0x0f; if((P1 != 0x0f) && (flag == 0)) { Key_Delay(10); if((P1 != 0x0f) && (flag == 0)) { flag = 1; switch(P1) { case 0x07: temp = 0; break; case 0x0b: temp = 1; break; case 0x0d: temp = 2; break; case 0x0e: temp = 3; break; } P1 = 0xf0; switch(P1) { case 0x70: temp = 0; break; case 0xb0: temp = 4; break; case 0xd0: temp = 8; break; case 0xe0: temp = 12; break; } Data_Control(KeyCode[temp]); } }else if(P1 == 0x0f) { flag = 0; } return temp; }
数码管显示#include "smg.h" u8 leddata[]={ 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71, 0x40, 0x00 }; u8 buff[8] = {0}; void Smg_Delay(u16 n) { u16 x, y; for(x = 0; x < n; x ) { for(y = 0; y < 110; y ); } } void Smg_Static(u8 number) { P0 = leddata[number]; } void Smg_Dymainc(void) { u8 i; for(i = 0; i < 8; i ) { P0 = 0x00; switch(i) { case 0: LA = 0; LB = 0; LC = 0; break; case 1: LA = 1; LB = 0; LC = 0; break; case 2: LA = 0; LB = 1; LC = 0; break; case 3: LA = 1; LB = 1; LC = 0; break; case 4: LA = 0; LB = 0; LC = 1; break; case 5: LA = 1; LB = 0; LC = 1; break; case 6: LA = 0; LB = 1; LC = 1; break; case 7: LA = 1; LB = 1; LC = 1; break; } Smg_Static(buff[i]); Smg_Delay(1); } } void Show_Number(u16 dis)//12 { u8 bf[8] = {0}; char i = 0; for(i = 0; i < 8; i ) { bf[i] = dis % 10;//bf[0] = 2 bf[1] = 1 bf[2] -- bf[7] = 0 dis = dis / 10; } for(i = 7; i >= 1; i--)//b[2] - bf[7] { if(bf[i] == 0) { buff[i] = 17; }else { break;//1 } } for(; i >= 0; i--) { buff[i] = bf[i]; } } void Data_Control(u8 dat)//12 5 { static u16 temp = 0; static u16 result = 0; static bit add_flag = 0; //¼Ó·¨±ê־λ static bit sub_flag = 0; //¼õ·¨±ê־λ static bit mul_flag = 0; //³Ë·¨±ê־λ static bit div_flag = 0; //³ý·¨±ê־λ if(dat >= 0x30 && dat <= 0x39)//°´¼ü°´ÏµÄÊÇÊý×Ö { temp = temp * 10 dat - '0'; //12 Show_Number(temp);//ÏÔʾÊý×Ö } else if(dat == 0x26) // ºÅ { result = temp; temp = 0; add_flag = 1; Show_Number(result);//ÏÔʾÊý×Ö } else if(dat == 0x25) // -ºÅ { if(result == 0 && temp != 0) { result = temp; }else { result -= temp; } sub_flag = 1; temp = 0; Show_Number(result);//ÏÔʾÊý×Ö } else if(dat == 0x28) // *ºÅ { if(result == 0 && temp != 0) { result = temp; }else if(result != 0 && temp == 0) { result = result; } else { result *= temp; } mul_flag = 1; temp = 0; Show_Number(result);//ÏÔʾÊý×Ö } else if(dat == 0x27) // /ºÅ { if(result == 0 && temp != 0) { result = temp; }else if(result != 0 && temp == 0) { result = result; } else { result /= temp; } div_flag = 1; temp = 0; Show_Number(result);//ÏÔʾÊý×Ö } else if(dat == 0x0D) // =ºÅ { if(add_flag == 1)//ÇóºÍ { add_flag = 0; result = temp; }else if(sub_flag == 1)//Çó²î { sub_flag = 0; result -= temp; } else if(mul_flag == 1)//Çó»ý { mul_flag = 0; result *= temp; } else if(div_flag == 1)//ÇóÉÌ { div_flag = 0; result /= temp; } temp = 0; Show_Number(result);//ÏÔʾÊý×Ö } else if(dat == 0x1b) // ÇåÁã { result = 0; temp = 0; Show_Number(result);//ÏÔʾÊý×Ö } }
timer.c#include "timer.h" //º¯Êý¹¦ÄÜ£º¶¨Ê±Æ÷³õʼ»¯ //º¯ÊýÐβΣºÎÞ //·µ»ØÖµ£ºÎÞ void Timer_Init(void) { TMOD &= 0xf0; // XXXX XXXX // 1111 0000 // XXXX 0000 TMOD |= 0x01; // XXXX 0000 // 0000 0001 // XXXX 0001 TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256; ET0 = 1; EA = 1; } u8 msec; u8 min; u8 sec; void Timer_interrupt(void) interrupt 1 //1ms { static u16 cnt = 0; TH0 = (65536 - 1000) / 256; TL0 = (65536 - 1000) % 256; cnt ; if(cnt >= 10) { cnt = 0; msec ; if(msec >= 100) { msec = 0; sec ; if(sec >= 60) { sec = 0; min ; if(min >= 60) min = 0; } } }
,免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com