矩阵键盘原理图 (2)
简易计算器(1602加矩阵键盘)
一、原理图:二、程序#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件#include<math.h>sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚sbit E=P2^2; //使能信号位,将E位定义为P2.2引脚sbit BF=P1^7; //忙碌标志位,#define NO_KEY_PRESS 0xff/********************************************************************************************************/unsigned char code tab[]={0xb7,0xee,0xde,0xbe,0xed,0xdd,0xbd,0xeb,0xdb,0xbb};unsigned long num1,num2,alg;unsigned char flag;void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<15;j++);}/********************************************************************************************************/void delay(unsigned char n){unsigned char i;for(i=0;i<n;i++)delay1ms();}/*****************************************************函数功能:判断液晶模块的忙碌状态返回值:result。
4×4矩阵式键盘按键
一、实验目的1.掌握4×4矩阵式键盘程序识别原理2.掌握4×4矩阵式键盘按键的设计方法二、设计原理(1)如图14.2所示,用单片机的并行口P3连接4×4矩阵键盘,并以单片机的P3.0-P3.3各管脚作输入线,以单片机的P3.4-P3.7各管脚作输出线,在数码管上显示每个按键“0-F”的序号(2)键盘中对应按键的序号排列如图14.1所示三、参考电路740)this.width=740" border=undefined>图14.2 4×4矩阵式键盘识别电路原理图740)this.width=740" border=undefined>图14.1 4×4键盘0-F显示740)this.width=740" border=undefined>图14.3 4×4矩阵式键盘识别程序流程图四、电路硬件说明(1)在“单片机系统”区域中,把单片机的P3.0-P3.7端口通过8联拨动拨码开关JP3连接到“4×4行列式键盘”区域中的M1-M4,N1-N4端口上(2)在“单片机系统”区域中,把单片机的P0.0-P0.7端口连接到“静态数码显示模块”区域中的任何一个a-h端口上;要求:P0.0对应着a,P0.1对应着b,……,P0.7对应着h五、程序设计内容(1)4×4矩阵键盘识别处理(2)每个按键都有它的行值和列值,行值和列值的组合就是识别这个按键的编码矩阵的行线和列线分别通过两并行接口和CPU通信键盘的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么?还要消除按键在闭合或断开时的抖动两个并行口中,一个输出扫描码,使按键逐行动态接地;另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能六、程序流程图(如图14.3所示)七、汇编源程序;;;;;;;;;;定义单元;;;;;;;;;;COUNT EQU 30H;;;;;;;;;;入口地址;;;;;;;;;;ORG 0000HLJMP STARTORG 0003HRETIORG 000BHRETIORG 0013HRETIORG 001BHRETIORG 0023HRETIORG 002BHRETI;;;;;;;;;;主程序入口;;;;;;;;;;ORG 0100HSTART: LCALL CHUSHIHUA LCALL PANDUANLCALL XIANSHILJMP START ;;;;;;;;;;初始化程序;;;;;;;;;; CHUSHIHUA: MOV COUNT#00H RET;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;; PANDUAN: MOV P3#0FFHCLR P3.4MOV A P3ANL A#0FHXRL A#0FHJZ SW1LCALL DELAY10MSJZ SW1MOV A P3ANL A#0FHCJNE A#0EH K1MOV COUNT#0LJMP DKK1: CJNE A#0DH K2MOV COUNT#4LJMP DKK2: CJNE A#0BH K3 MOV COUNT#8 LJMP DKK3: CJNE A#07H K4 MOV COUNT#12K4: NOPLJMP DKSW1: MOV P3#0FFH CLR P3.5MOV A P3ANL A#0FHXRL A#0FHJZ SW2LCALL DELAY10MS JZ SW2MOV A P3ANL A#0FHCJNE A#0EH K5 MOV COUNT#1 LJMP DKK5: CJNE A#0DH K6 MOV COUNT#5 LJMP DKK6: CJNE A#0BH K7 MOV COUNT#9 LJMP DKK7: CJNE A#07H K8 MOV COUNT#13K8: NOPLJMP DKSW2: MOV P3#0FFH CLR P3.6MOV A P3ANL A#0FHXRL A#0FHJZ SW3LCALL DELAY10MS JZ SW3MOV A P3ANL A#0FHCJNE A#0EH K9 MOV COUNT#2 LJMP DKK9: CJNE A#0DH KA MOV COUNT#6 LJMP DKKA: CJNE A#0BH KB MOV COUNT#10 LJMP DKKB: CJNE A#07H KC MOV COUNT#14 KC: NOPLJMP DKSW3: MOV P3#0FFH CLR P3.7MOV A P3ANL A#0FHXRL A#0FHJZ SW4LCALL DELAY10MSJZ SW4MOV A P3ANL A#0FHCJNE A#0EH KDMOV COUNT#3LJMP DKKD: CJNE A#0DH KE MOV COUNT#7LJMP DKKE: CJNE A#0BH KF MOV COUNT#11LJMP DKKF: CJNE A#07H KG MOV COUNT#15KG: NOPLJMP DKSW4: LJMP PANDUAN DK: RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A COUNT MOV DPTR#TABLE MOVC A@A+DPTRMOV P0 ALCALL DELAYSK: MOV A P3ANL A#0FHXRL A#0FHJNZ SKRET ;;;;;;;;;;10ms延时程序;;;;;;;;;;DELAY10MS: MOV R6#20D1: MOV R7#248DJNZ R7$DJNZ R6D1RET;;;;;;;;;;200ms延时程序;;;;;;;;;;DELAY: MOV R5#20LOOP: LCALL DELAY10MSDJNZ R5LOOPRET;;;;;;;;;;共阴码表;;;;;;;;;;TABLE: DB 3FH06H5BH4FH66H6DH7DH07H DB 7FH6FH77H7CH39H5EH79H71H ;;;;;;;;;;结束标志;;;;;;;;;;END八、C语言源程序#include<AT89X51.H>unsigned char code table[]={0x3f0x660x7f0x390x060x6d0x6f0x5e0x5b0x7d0x770x790x4f0x070x7c0x71};void main(void){ unsigned char i j k key;while(1){ P3=0xff; //给P3口置1//P3_4=0; //给P3.4这条线送入0//i=P3;i=i&0x0f; //屏蔽低四位//if(i!=0x0f) //看是否有按键按下//{ for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);if(i!=0x0f) //再次判断按键是否按下//{ switch(i) //看是和P3.4相连的四个按键中的哪个// { case 0x0e:key=0;break;case 0x0d:key=1;break;case 0x0b:key=2;break;case 0x07:key=3;break;}P0=table[key]; //送数到P0口显示//}}P3=0xff;P3_5=0; //读P3.5这条线//i=P3;i=i&0x0f; //屏蔽P3口的低四位//if(i!=0x0f) //读P3.5这条线上看是否有按键按下// { for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);i=P3; //再看是否有按键真的按下//i=i&0x0f;if(i!=0x0f){ switch(i) //如果有显示相应的按键//{ case 0x0e:key=4;break;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}P0=table[key]; //送入P0口显示//}}P3=0xff;P3_6=0; //读P3.6这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=8;break;key=9;break;case 0x0b:key=10;break;case 0x07:key=11;break;}P0=table[key];}}P3=0xff;P3_7=0; //读P3.7这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=12;break;case 0x0d:key=13;break;key=14;break;case 0x07:key=15;break;}P0=table[key];}}}}九、注意事项在硬件电路中,要把8联拨动拨码开关JP2拨下,把8联拨动拨码开关JP3拨上去。
矩阵按键原理图
矩阵按键原理图
键盘分编码键盘和非编码键盘。
键盘上闭合键的识别由专用的硬件编码器实现,并产生键编码号或键值的称为编码键盘,如计算机键盘。
而靠软件编程来识别的称为非编码键盘。
在一般嵌入式应用中,用的最多的是非编码键盘,也有用到编码键盘的。
非编码键盘又分为独立键盘和行列式(又称为矩阵式)键盘。
所谓独立式键盘,即嵌入式CPU(或称MCU)的一个GPIO口对应一个按键输入,这个输入值的高低状态就是键值。
矩阵键盘用于采集键值的GPIO是复用的,一般分为行和列采集,例如4*4矩阵键盘就只需要行列各4个按键就可以了,矩阵键盘的控制较独立键盘要复杂得多,本实验未涉及,所以对其原理不做详细介绍。
独立按键一般有2组管脚,虽然市面上我们常常看到有4个管脚的按键,但它们一般是两两导通的,这2组管脚在按键未被按下时是断开的,在按键被按下时则是导通的。
基于此原理,我们一般会把按键的一个管脚接地,另一个管脚上拉到VCC,并且也连接到GPIO。
这样,在按键未被按下时,GPIO的连接状态为上拉到VCC,则键值为1;按键被按下时,GPIO虽然还是上拉到VCC,但同时被导通的另一个管脚拉到地了,所以它的键值实际上是0。
矩阵及下三角键盘
矩阵键盘设计一、原理图图1 4*4矩阵键盘分布图2 4*4键码显示模块图3 下三角键盘分布图3 下三角键盘小写模式显示图3 下三角键盘大写模式显示图3 下三角键盘数字模式显示二、C程序(一) 4*4键盘C程序#include<reg51.h>//51头文件#defineucharunsignedchar#defineuintunsignedint ucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F字型码voiddelay(ucharz)//延时1ms函数{uinti,j;for(i=z;i>0;i--)for(j=110;j>0;j--);}voidkeyscan()//键盘扫描函数{ucharhang,lie;//定义行列值变量P1=0x0f;//准备读行值hang=P1&0x0f;//读入行值if(hang!=0x0f)//先检测有无按键按下{delay(5);//去抖hang=P1&0x0f;//读入行值if(hang!=0x0f){P1=0xf0;//准备读列值lie=P1&0xf0;//读入列值lie=lie+hang;//确定显示点while(P1!=0xf0);{P1=P1&0xf0;}}}switch(lie){case0x7e:P0=table[0];break;//0显示按键值case0xbe:P0=table[1];break;//1case0xde:P0=table[2];break;//2case0xee:P0=table[3];break;//3case0x7d:P0=table[4];break;//4case0xbd:P0=table[5];break;//5case0xdd:P0=table[6];break;//6case0xed:P0=table[7];break;//7case0x7b:P0=table[8];break;//8case0xbb:P0=table[9];break;//9case0xdb:P0=table[10];break;//acase0xeb:P0=table[11];break;//bcase0x77:P0=table[12];break;//ccase0xb7:P0=table[13];break;//dcase0xd7:P0=table[14];break;//ecase0xe7:P0=table[15];break;//f}}voidmain(){P0=0x00;//初始黑屏while(1){keyscan();//调用键盘扫描,}}(二)下三角键盘C程序#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit rs=P2^6;sbit lcden=P2^7;sbit k2=P3^7;sbit xx=P3^0;sbit dx=P3^1;sbit sz=P3^2;uchar code table[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q', 'r','s','t','u','v','w','x','y','z', 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q', 'R','S','T','U','V','W','X','Y','Z', '0','1','2','3','4','5','6','7','8','9'} ;uchar data table1[50];uchar num=69,num1,j=0,k1=0,k=0;void delay(uint z){int i,j;for(i=z;i>0;i--)for(j=110;j>0;j--);}void write_com(uchar com)// {rs=0;lcden=0;P0=com;delay(1);lcden=1;delay(1);lcden=0;}void write_date(uchar date)// {rs=1;lcden=0;P0=date;delay(1);lcden=1;delay(1);lcden=0;}uchar keyboard()//{uchar temp;if(k2==0){delay(5);if(k2==0){++k1;while(!k2);//判断键盘是否松开if(k1==3)k1=0;}if(k1==0){xx=1;dx=0;sz=0;}if(k1==1){xx=0;dx=1;sz=0;}if(k1==2){xx=0;dx=0;sz=1;}}if(k1==0){xx=1;P1=0xfe;temp=P1;temp=temp&0xfe;while(temp!=0xfe){delay(5);temp=P1;temp=temp&0xfe;while(temp!=0xfe){temp=P1;switch(temp){// case 0xfc:k1=51;break;case 0xfa:num=0;;break;case 0xf6:num=1;break;case 0xee:num=2;break;case 0xde:num=3;break;case 0xbe:num=4;break;case 0x7e:num=5;break;}while(temp!=0xfe){temp=P1;temp=temp&0xfe;}}}P1=0xfd;temp=P1;temp=temp&0xfd;while(temp!=0xfd){delay(5);temp=P1;temp=temp&0xfd;while(temp!=0xfd){temp=P1;switch(temp){// case 0xfc:k1=51;break;case 0xf9:num=6;break;case 0xf5:num=7;break;case 0xed:num=8;break;case 0xdd:num=9;break;case 0x7d:num=11;break;}while(temp!=0xfd){temp=P1;temp=temp&0xfd;}}}P1=0xfb;temp=P1;temp=temp&0xfb;while(temp!=0xfb){delay(5);temp=P1;temp=temp&0xfb;while(temp!=0xfb){temp=P1;switch(temp){case 0xf3:num=12;break;case 0xeb:num=13;break;case 0xdb:num=14;break;case 0xbb:num=15;break;case 0x7b:num=16;break;}while(temp!=0xfb){temp=P1;temp=temp&0xfb;}}}P1=0xf7;temp=P1;temp=temp&0xf7;while(temp!=0xf7){delay(5);temp=P1;temp=temp&0xf7;while(temp!=0xf7){temp=P1;switch(temp){case 0xe7:num=17;break;case 0xd7:num=18;break;case 0xb7:num=19;break;case 0x77:num=20;break;}while(temp!=0xf7){temp=P1;temp=temp&0xf7;}}}P1=0xef;temp=P1;temp=temp&0xef;while(temp!=0xef){delay(5);temp=P1;temp=temp&0xef;while(temp!=0xef){temp=P1;switch(temp){case 0xcf:num=21;break;case 0xaf:num=22;break;case 0x6f:num=23;break;}while(temp!=0xef){temp=P1;temp=temp&0xef;}}}P1=0xdf;temp=P1;temp=temp&0xdf;while(temp!=0xdf)delay(5);temp=P1;temp=temp&0xdf;while(temp!=0xdf){temp=P1;switch(temp){case 0x9f:num=24;break;case 0x5f:num=25;break;}while(temp!=0xdf){temp=P1;temp=temp&0xdf;}}}P1=0xbf;temp=P1;temp=temp&0xbf;while(temp!=0xbf)delay(5);temp=P1;temp=temp&0xbf;while(temp!=0xbf){temp=P1;switch(temp){case 0x3f:num=69;break;//case 0x5f:num=25;break;}while(temp!=0xbf){temp=P1;temp=temp&0xbf;}}}}if(k1==1){//dx=1;P1=0xfe;temp=P1;temp=temp&0xfe;while(temp!=0xfe){delay(5);temp=P1;temp=temp&0xfe;while(temp!=0xfe){temp=P1;switch(temp){// case 0xfc:k1=51;break;case 0xfa:num=26;;break;case 0xf6:num=27;break;case 0xee:num=28;break;case 0xde:num=29;break;case 0xbe:num=30;break;case 0x7e:num=31;break;}while(temp!=0xfe){temp=P1;temp=temp&0xfe;}}}P1=0xfd;temp=P1;temp=temp&0xfd;while(temp!=0xfd){delay(5);temp=P1;temp=temp&0xfd;while(temp!=0xfd){temp=P1;switch(temp){// case 0xfc:k1=51;break;case 0xf9:num=32;break;case 0xf5:num=33;break;case 0xed:num=34;break;case 0xdd:num=35;break;case 0xbd:num=36;break;case 0x7d:num=37;break;}while(temp!=0xfd){temp=P1;temp=temp&0xfd;}}}P1=0xfb;temp=P1;temp=temp&0xfb;while(temp!=0xfb){delay(5);temp=P1;temp=temp&0xfb;while(temp!=0xfb){temp=P1;switch(temp){case 0xf3:num=38;break;case 0xeb:num=39;break;case 0xdb:num=40;break;case 0xbb:num=41;break;case 0x7b:num=42;break;}while(temp!=0xfb){temp=P1;temp=temp&0xfb;}}}P1=0xf7;temp=P1;temp=temp&0xf7;while(temp!=0xf7){delay(5);temp=P1;temp=temp&0xf7;while(temp!=0xf7){temp=P1;switch(temp){case 0xe7:num=43;break;case 0xd7:num=44;break;case 0xb7:num=45;break;case 0x77:num=46;break;}while(temp!=0xf7){temp=P1;temp=temp&0xf7;}}}P1=0xef;temp=P1;temp=temp&0xef;while(temp!=0xef){delay(5);temp=P1;temp=temp&0xef;while(temp!=0xef){temp=P1;switch(temp){case 0xcf:num=47;break;case 0xaf:num=48;break;case 0x6f:num=49;break;}while(temp!=0xef){temp=P1;temp=temp&0xef;}}}P1=0xdf;temp=P1;temp=temp&0xdf;while(temp!=0xdf)delay(5);temp=P1;temp=temp&0xdf;while(temp!=0xdf){temp=P1;switch(temp){case 0x9f:num=50;break;case 0x5f:num=51;break;}while(temp!=0xdf){temp=P1;temp=temp&0xdf;}}}P1=0xbf;temp=P1;temp=temp&0xbf;while(temp!=0xbf)delay(5);temp=P1;temp=temp&0xbf;while(temp!=0xbf){temp=P1;switch(temp){case 0x3f:num=69;break;}while(temp!=0xbf){temp=P1;temp=temp&0xbf;}}}}if(k1==2){//sz=1;P1=0xfe;temp=P1;temp=temp&0xfe;while(temp!=0xfe){delay(5);temp=P1;temp=temp&0xfe;while(temp!=0xfe){temp=P1;switch(temp){// case 0xfc:k1=51;break;case 0xfa:num=52;;break;case 0xf6:num=53;break;case 0xee:num=54;break;case 0xde:num=55;break;case 0xbe:num=56;break;case 0x7e:num=57;break;}while(temp!=0xfe){temp=P1;temp=temp&0xfe;}}}P1=0xfd;temp=P1;temp=temp&0xfd;while(temp!=0xfd){delay(5);temp=P1;temp=temp&0xfd;while(temp!=0xfd){temp=P1;switch(temp){case 0xf9:num=58;break;case 0xf5:num=59;break;case 0xed:num=60;break;case 0xdd:num=61;break;//case 0xbd:num=62;break;}while(temp!=0xfd){temp=P1;temp=temp&0xfd;}}}}// table1[k]=num;k++;return(num);}/*void display(){ int i,a,b;for(i=0;i<80;i++){a=keyboard();table1[i]=a;write_com(0x80+i);write_date(table[table1[i]]);a=69;delay(100);}}*/void init()//{xx=0;dx=0;sz=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);// write_com(0x80);}void main(){ int i=0,j=0;init();while(1){ //table1[k]=keybord();k++;if(k==10)k=0;delay(100);write_com(0x80+0x00);//for(k=0;k<20;k++){write_date(table[keyboard()]);}//for(k=0;k<20;k++)//{write_date(table[table1[k]]);delay(100);}// for(i=0;i<10;i++)/*{ write_date(table[i]);i++;j++;delay(100);}if(i==20)j=0;write_com(0x80+0x40+j);for(k=0;k<20;k++){ write_date(table[i]);i++;j++;delay(100);}if(i==40)j=0;write_com(0x80+0x14+j);for(k=0;k<20;k++){ write_date(table[i]);i++;j++;delay(100);}if(i==60)j=0;write_com(0x80+0x54+j);for(k=0;k<20;k++){ write_date(table[i]);i++;j++;delay(100);}if(i>62)while(1);*/// write_com(0x80+0x40);// for(k=0;k<10;k++)// {write_date(table[keyboard()]);delay(100);}// write_com(0x80+0x40);//for(k=0;k<10;k++)//write_date(table[keyboard()]);// write_com(0x80+0x14);//for(k=0;k<10;k++)//write_date(table[keyboard()]);// write_com(0x80+0x54);//for(k=0;k<10;k++)//write_date(table[keyboard()]);}}此程序对初学者相当有效,且易于学习掌握。
单片机实验报告——矩阵键盘数码管显示
单片机实验报告信息处理实验实验二矩阵键盘专业:电气工程及其自动化指导老师:***组员:明洪开张鸿伟张谦赵智奇学号:152703117 \152703115\152703118\152703114室温:18 ℃日期:2017 年10 月25日矩阵键盘一、实验内容1、编写程序,做到在键盘上每按一个键(0-F)用数码管将该建对应的名字显示出来。
按其它键没有结果。
二、实验目的1、学习独立式按键的查询识别方法。
2、非编码矩阵键盘的行反转法识别方法。
3、掌握键盘接口的基本特点,了解独立键盘和矩阵键盘的应用方法。
4、掌握键盘接口的硬件设计方法,软件程序设计和贴士排错能力。
5、掌握利用Keil51软件对程序进行编译。
6、会根据实际功能,正确选择单片机功能接线,编制正确程序。
对实验结果能做出分析和解释,能写出符合规格的实验报告。
三、实验原理1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。
2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。
3、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。
这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。
由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。
单片机4×4矩阵键盘设计方案
1、设计原理(1)如图14.2所示,用单片机的并行口P3连接4×4矩阵键盘,并以单片机的P3.0-P3.3各管脚作输入线,以单片机的P3.4-P3.7各管脚作输出线,在数码管上显示每个按键“0-F”的序号。
(2)键盘中对应按键的序号排列如图14.1所示。
2、参考电路图14.2 4×4矩阵式键盘识别电路原理图3、电路硬件说明(1)在“单片机系统”区域中,把单片机的P3.0-P3.7端口通过8联拨动拨码开关JP3连接到“4×4行列式键盘”区域中的M1-M4,N1-N4端口上。
(2)在“单片机系统”区域中,把单片机的P0.0-P0.7端口连接到“静态数码显示模块”区域中的任何一个a-h端口上;要求:P0.0对应着a,P0.1对应着b,……,P0.7对应着h。
4、程序设计内容(1)4×4矩阵键盘识别处理。
(2)每个按键都有它的行值和列值,行值和列值的组合就是识别这个按键的编码。
矩阵的行线和列线分别通过两并行接口和CPU通信。
键盘的一端(列线)通过电阻接VCC,而接地是通过程序输出数字“0”实现的。
键盘处理程序的任务是:确定有无键按下,判断哪一个键按下,键的功能是什么?还要消除按键在闭合或断开时的抖动。
两个并行口中,一个输出扫描码,使按键逐行动态接地;另一个并行口输入按键状态,由行扫描值和回馈信号共同形成键编码而识别按键,通过软件查表,查出该键的功能。
5、程序流程图(如图14.3所示)6、汇编源程序;;;;;;;;;;定义单元;;;;;;;;;;COUNT EQU 30H;;;;;;;;;;入口地址;;;;;;;;;;ORG 0000HLJMP STARTORG 0003HRETIORG 000BHRETIORG 0013HRETIORG 001BHRETIORG 0023HRETIORG 002BHRETI;;;;;;;;;;主程序入口;;;;;;;;;;ORG 0100HSTART: LCALL CHUSHIHUALCALL PANDUANLCALL XIANSHILJMP START;;;;;;;;;;初始化程序;;;;;;;;;;CHUSHIHUA: MOV COUNT,#00HRET;;;;;;;;;;判断哪个按键按下程序;;;;;;;;;;PANDUAN: MOV P3,#0FFHCLR P3.4MOV A,P3ANL A,#0FHJZ SW1LCALL DELAY10MS JZ SW1MOV A,P3ANL A,#0FHCJNE A,#0EH,K1 MOV COUNT,#0 LJMP DKK1: CJNE A,#0DH,K2 MOV COUNT,#4 LJMP DKK2: CJNE A,#0BH,K3 MOV COUNT,#8 LJMP DKK3: CJNE A,#07H,K4 MOV COUNT,#12K4: NOPLJMP DKSW1: MOV P3,#0FFH CLR P3.5MOV A,P3ANL A,#0FHJZ SW2LCALL DELAY10MS JZ SW2MOV A,P3ANL A,#0FHCJNE A,#0EH,K5 MOV COUNT,#1 LJMP DKK5: CJNE A,#0DH,K6 MOV COUNT,#5 LJMP DKK6: CJNE A,#0BH,K7 MOV COUNT,#9 LJMP DKK7: CJNE A,#07H,K8 MOV COUNT,#13K8: NOPLJMP DKSW2: MOV P3,#0FFH CLR P3.6MOV A,P3ANL A,#0FHJZ SW3LCALL DELAY10MS JZ SW3MOV A,P3ANL A,#0FHCJNE A,#0EH,K9 MOV COUNT,#2 LJMP DKK9: CJNE A,#0DH,KA MOV COUNT,#6 LJMP DKKA: CJNE A,#0BH,KB MOV COUNT,#10 LJMP DKKB: CJNE A,#07H,KC MOV COUNT,#14 KC: NOPLJMP DKSW3: MOV P3,#0FFH CLR P3.7MOV A,P3ANL A,#0FHJZ SW4LCALL DELAY10MSJZ SW4MOV A,P3ANL A,#0FHCJNE A,#0EH,KDMOV COUNT,#3LJMP DKKD: CJNE A,#0DH,KE MOV COUNT,#7LJMP DKKE: CJNE A,#0BH,KF MOV COUNT,#11 LJMP DKKF: CJNE A,#07H,KG MOV COUNT,#15KG: NOPLJMP DKSW4: LJMP PANDUAN DK: RET ;;;;;;;;;;显示程序;;;;;;;;;; XIANSHI: MOV A,COUNTMOV DPTR,#TABLEMOVC A,@A+DPTRMOV P0,ALCALL DELAYSK: MOV A,P3ANL A,#0FHXRL A,#0FHJNZ SKRET;;;;;;;;;;10ms延时程序;;;;;;;;;;DELAY10MS: MOV R6,#20D1: MOV R7,#248DJNZ R7,$DJNZ R6,D1RET;;;;;;;;;;200ms延时程序;;;;;;;;;;DELAY: MOV R5,#20LOOP: LCALL DELAY10MSDJNZ R5,LOOPRET;;;;;;;;;;共阴码表;;;;;;;;;;TABLE: DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H;;;;;;;;;;结束标志;;;;;;;;;;END7、C语言源程序#includeunsigned char code table[]={0x3f,0x66,0x7f,0x39,0x06,0x6d,0x6f,0x5e,0x5b,0x7d,0x77,0x79,0x4f,0x07,0x7c,0x71};void main(void){ unsigned char i,j,k,key;while(1){ P3=0xff; //给P3口置1//P3_4=0; //给P3.4这条线送入0//i=P3;i=i&0x0f; //屏蔽低四位//if(i!=0x0f) //看是否有按键按下//{ for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);if(i!=0x0f) //再次判断按键是否按下//{ switch(i) //看是和P3.4相连的四个按键中的哪个// { case 0x0e:key=0;break;case 0x0d:key=1;break;case 0x0b:key=2;break;case 0x07:key=3;break;}P0=table[key]; //送数到P0口显示//}}P3=0xff;P3_5=0; //读P3.5这条线//i=P3;i=i&0x0f; //屏蔽P3口的低四位//if(i!=0x0f) //读P3.5这条线上看是否有按键按下// { for(j=50;j>0;j--) //延时//for(k=200;k>0;k--);i=P3; //再看是否有按键真的按下//i=i&0x0f;if(i!=0x0f){ switch(i) //如果有,显示相应的按键//{ case 0x0e:key=4;break;case 0x0d:key=5;break;case 0x0b:key=6;break;case 0x07:key=7;break;}P0=table[key]; //送入P0口显示//}}P3=0xff;P3_6=0; //读P3.6这条线上是否有按键按下// i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--)for(k=200;k>0;k--);i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=8;break;case 0x0d:key=9;break;case 0x0b:key=10;break;case 0x07:key=11;break;}P0=table[key];}}P3=0xff;P3_7=0; //读P3.7这条线上是否有按键按下//i=P3;i=i&0x0f;if(i!=0x0f){ for(j=50;j>0;j--) for(k=200;k>0;k--); i=P3;i=i&0x0f;if(i!=0x0f){ switch(i){ case 0x0e:key=12;break;case 0x0d:key=13;break;case 0x0b:key=14;break;case 0x07:key=15;break;}P0=table[key];}}}}8、注意事项在硬件电路中,要把8联拨动拨码开关JP2拨下,把8联拨动拨码开关JP3拨上去。
矩阵式键盘实验报告
矩阵键盘实验报告佘成刚学号2010302001班级08041202时间2016.01.20一、实验目的1.学习矩列式键盘工作原理;2.学习矩列式接口的程序设计。
二、实验设备普中HC6800ESV20开发板三、实验要求要现:用4*4矩阵键盘,用按键形式输入学号,在数码管上显示对应学号。
四、实验原理工作原理:矩阵式由行线和列线组成,按键位于行、列的交叉点上。
如图所示,一个4*4 的行、列结构可以构成一个由16 个按键的键盘。
很明显,在按键数量较多的场合,矩阵式键盘与独立式键盘相比,要节省很多的I/0 口。
(1)矩阵式键盘工作原理按键设置在行、列交节点上,行、列分别连接到按键开关的两端。
行线通过下拉电阻接到GND 上。
平时无按键动作时,行线处于低电平状态,而当有按键按下时,行线电平状态将由与此行线相连的列线电平决定。
列线电平如果为低,行线电平为高,列线电平如果为高,则行线电平则为低。
这一点是识别矩阵式键盘是否被按下的关键所在。
因此,各按键彼此将相互发生影响,所以必须将行、列线信号配合起来并作适当的处理,才能确定闭合键的位置。
(2)按键识别方法下面以3 号键被按下为例,来说明此键是如何被识别出来的。
前已述及,键被按下时,与此键相连的行线电平将由与此键相连的列线电平决定,而行线电平在无键按下时处于高电平状态。
如果让所有列线处于高电平那么键按下与否不会引起行线电平的状态变化,始终是高电平,所以,让所有列线处于高电平是没法识别出按键的。
现在反过来,让所有列线处于低电平,很明显,按下的键所在行电平将也被置为低电平,根据此变化,便能判定该行一定有键被按下。
但我们还不能确定是这一行的哪个键被按下。
所以,为了进一步判定到底是哪—列的键被按下,可在某一时刻只让一条列线处于低电平,而其余所有列线处于高电平。
当第1 列为低电平,其余各列为高电平时,因为是键3 被按下,所以第1 行仍处于高电平状态;当第2 列为低电平,其余各列为高电平时,同样我们会发现第1 行仍处于高电平状态,直到让第4 列为低电平,其余各列为高电平时,因为是3 号键被按下,所以第1 行的高电平转换到第4 列所处的低电平,据此,我们确信第1 行第4 列交叉点处的按键即3 号键被按下。
4X4矩阵键盘及显示电路设计
4X4矩阵键盘与显示电路设计FPGA在数字系统设计中的广泛应用,影响到了生产生活的各个方面。
在FPGA 的设计开发中,VHDL语言作为一种主流的硬件描述语言,具有设计效率高,可靠性好,易读易懂等诸多优点。
作为一种功能强大的FPGA数字系统开发环境,Altera公司推出的Quar-tUSⅡ,为设计者提供了一种与结构无关的设计环境,使设计者能方便地进行设计输入、快速处理和器件编程,为使用VHDL语言进行FPGA设计提供了极大的便利。
矩阵键盘作为一种常用的数据输入设备,在各种电子设备上有着广泛的应用,通过7段数码管将按键数值进行显示也是一种常用的数据显示方式。
在设计机械式矩阵键盘控制电路时,按键防抖和按键数据的译码显示是两个重要方面。
本文在QuartusⅡ开发环境下,采用VHDL语言设计了一种按键防抖并能连续记录并显示8次按键数值的矩阵键盘与显示电路。
一、矩阵键盘与显示电路设计思路矩阵键盘与显示电路能够将机械式4×4矩阵键盘的按键值依次显示到8个7段数码管上,每次新的按键值显示在最右端的第O号数码管上,原有第0~6号数码管显示的数值整体左移到第1~7号数码管上显示,见图1。
总体而言,矩阵键盘与显示电路的设计可分为4个局部:(1)矩阵键盘的行与列的扫描控制和译码。
该设计所使用的键盘是通过将列扫描信号作为输入信号,控制行扫描信号输出,然后根据行与列的扫描结果进行译码。
(2)机械式按键的防抖设计。
由于机械式按键在按下和弹起的过程中均有5~10 ms的信号抖动时间,在信号抖动时间内无法有效判断按键值,因此按键的防抖设计是非常关键的,也是该设计的一个重点。
(3)按键数值的移位存放。
由于该设计需要在8个数码管上依次显示前后共8次按键的数值,因此对已有数据的存储和调用也是该设计的重点所在。
(4)数码管的扫描和译码显示。
由于该设计使用了8个数码管,因此需要对每个数码管进行扫描控制,并根据按键值对每个数码管进行7段数码管的译码显示。
4×4矩阵键盘在单片机中的应用(Proteus)
4×4矩阵键盘原理及其在单片机中的简单应用基于Proteus仿真1、4×4矩阵键盘的工作原理如下图所示,4×4矩阵键盘由4条行线和4条列线组成,行线接P3.0-P3.3,列线接P3.4-P3.7,按键位于每条行线和列线的交叉点上。
按键的识别可采用行扫描法和线反转法,这里采用简单的线反转法,只需三步。
第一步,执行程序使X0~X3均为低电平,此时读取各列线Y0~Y3的状态即可知道是否有键按下。
当无键按下时,各行线与各列线相互断开,各列线仍保持为高电平;当有键按下时,则相应的行线与列线通过该按键相连,该列线就变为低电平,此时读取Y0Y1Y2Y3的状态,得到列码。
第二步,执行程序使Y0~Y3均为低电平,当有键按下时,X0~X3中有一条行线为低电平,其余行线为高电平,读取X0X1X2X3的状态,得到行码。
第三步,将第一步得到的列码和第二步得到的行码拼合成被按键的位置码,即Y0Y1Y2Y3X0X1X2X3(因为行线和列线各有一条为低电平,其余为高电平,所以位置码低四位和高四位分别只有一位低电平,其余为高电平)。
当0键按下时,行线X0和列线Y0为低电平,其余行列线为高电平,于是可以得到0键的位置码Y0Y1Y2Y3X0X1X2X3为0111 0111,即0X77。
当5键按下时,行线X1和列线Y1为低电平,其余行列线为高电平,于是可得到5键的位置码Y0Y1Y2Y3X0X1X2X3为1011 1011,即0XBB。
全部矩阵键盘的位置码如下:2、4×4矩阵键盘在单片机的简单应用举例(一)如下图所示,运行程序时,按下任一按键,数码管会显示它在矩阵键盘上的序号0~F,并且蜂鸣器发出声音,模拟按键的声音。
此处采用线反转法识别按键。
C程序如下:#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit buzzer=P1^0;uchar code dis[]= //0~9,A~F的共阳显示代码{0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0X88,0X83,0XC6,0XA1,0X86,0X8E};uchar code tab[]= //矩阵键盘按键位置码{0x77,0xb7,0xd7,0xe7,0x7b,0xbb,0xdb,0xeb,0x7d,0xbd,0xdd,0xed,0x7e,0xbe,0xde,0xee};void delay(uint x) //延时函数{uchar i;while(x--)for(i=0;i<120;i++);}uchar scan() //矩阵键盘扫描函数,得到按键号,采用线反转法{uchar a,b,c,i;P3=0XF0; //P3口输出11110000a=P3; //读取列码delay(10); //防抖延时10msP3=0X0F; //P3口输出00001111b=P3; //读取行码c=a+b; //得到位置码for(i=0;i<16;i++)if(c==tab[i])return i; //查表得到按键序号并返回return -1; //无按键,则返回-1}void beep() //蜂鸣器发出声音,模拟按键的声音{ uchar i;for(i=0;i<100;i++){buzzer=~buzzer;delay(1);}buzzer=0;}void main(){uchar key;buzzer=0; //关闭蜂鸣器while(1){key=scan(); //得到按键号if(key!=-1) //有按键则显示,并且蜂鸣器发出声音{P0=dis[key];beep();delay(100);}}}Proteus仿真运行结果如下:3、4×4矩阵键盘在单片机的简单应用举例(二)如下图所示,运行程序时,按下的按键键值越大,点亮的LED灯越多,例如,按下1号键时,点亮一只LED灯,按下2号键时,点亮两只LED灯,按下16号键时,点亮全部LED 灯。
实验四:矩阵按键与数码管显示
switch(P2) { case(0X70): KeyValue=3;break; case(0XB0): KeyValue=2;break; case(0XD0): KeyValue=1;break; case(0XE0): KeyValue=0;break; } //测试行 P2=0X0F; switch(P2) { case(0X07): KeyValue=KeyValue+12;break; case(0X0B): KeyValue=KeyValue+8;break; case(0X0D): KeyValue=KeyValue+4;break; case(0X0E): KeyValue=KeyValue;break; } //此处是流程图中所缺少的部分请尝试理解与运用 while((a<50)&&(P2!=0x0F)) { Delay(1000); a++; } } } return KeyValue; }
图 4 数码管动态显示
实例:
B C D E F G H
RP1
RESPACK-8 P0.0 P0.1 P0.2 P0.3 P0.7 P0.6 P0.5 P0.4 P1.3 P1.2 P1.1 P1.0
C2
100pF
1 1
U1 X1
19 XTAL1 CRYSTAL P0.0/AD0 P0.1/AD1 P0.2/AD2 P0.3/AD3 P0.4/AD4 P0.5/AD5 P0.6/AD6 P0.7/AD7 P2.0/A8 P2.1/A9 P2.2/A10 P2.3/A11 P2.4/A12 P2.5/A13 P2.6/A14 P2.7/A15 P3.0/RXD P3.1/TXD P3.2/INT0 P3.3/INT1 P3.4/T0 P3.5/T1 P3.6/WR P3.7/RD 39 38 37 36 35 34 33 32 21 22 23 24 25 26 27 28 10 11 12 13 14 15 16 17
矩阵键盘原理
单片机引脚高电平是路端电压是5V,低电平是地0V,为什么不会发生短路呢。
因为脚高电平电压5V不是电源的5V,是经过了一个上拉电阻后的5V,当高低电平端接是,高电平端就被接地,就有电流流过上拉电阻,所以不短路。
单片机IO口电路其实就是一个NPN三极管,集电极与电源之间接一个上拉电阻。
你所提到的高电平所测到的电压是集电极电压。
不知道楼主明白没有呢矩阵键盘在单片机中就是两个端口短接,都变为低电平,再取查询判断低电平的位置,得知是哪个键按下,再取执行相应的程序呵呵,是有点尴尬,搞了这么几年,到现在竟然矩阵键盘都不会!不过也不意外,毕竟之前并不能把所有的知识都学到!比如串口,本科的时候就没仔细研究过,后来做GSM,没办法,还是一点一点的去深入理解它,才毕竟通了!矩阵键盘也是一样,现在实习有个项目,要用到矩阵键盘,就现在熟悉下原理,哈哈!在按键数目比较多、I/O资源有限的情况下,有几种方法实现多按键检测:•端口扩展:采用端口扩展芯片实现单片机I/O口的扩展;•使用专门的键盘芯片;•使用矩阵键盘。
其中矩阵键盘是一种比较常用的方法。
矩阵键盘的电路图如下:矩阵式键盘由行线和列线组成,按键位于行、列的交叉点上。
当键被按下时,其交点的行线和列线接通,相应的行线或列线上的电平发生变化,单片机通过检测行或列线上的电平变化可以确定哪个按键被按下。
矩阵键盘不仅在连接上比单独式按键复杂,它的按键识别方法也比单独式按键复杂。
矩阵键盘的检测方法有多种,常见的有:逐点扫描法、逐行扫描法、全局扫描法。
在本实例中我们采用逐行扫描法来实现按键检测,其中PD0-PD3作为列线,PD4-PD7作为行线。
识别过程如下:1、判断键盘中是否有键按下。
设置所有行线为输出口,并输出低电平;设置列线为输入口,读取列线上的电平状态,只要有一列的电平为低,就表示有按键按下,并且被按下的键位于电平为低的列线与4跟行线相交叉的4个按键中,若所有列线都为高电平,表示没有按键按下;2、判断被按下按键所在的位置。
矩阵键盘资料(在实验五十中)
TECHISHINE
有了表 50-2,要写出键盘译码电路的 VHDL 程序就非常容易了,尤其针对有表可以对照
的电路设计,只要使用 CASE-WHEN 或 WHNE-ELSE 语句,便可轻松完成设计。
表 50-2 键盘参数表
SEL2~SEL0 KIN3~KIN0
对应的 键盘译 按键功 按键 码输出 能
010
1101
REG 10010 功能键
1011
C
01100 字母 C
表 50-1 按键位置与数码关系
122
Beijing Techshine Technology Co.
TECHISHINE
SEL2~SEL0 000
KIN3~KIN0 1110 1101 1011
对应的按键 0 6
LAST
0111
CTRL
1110
1
1101
7
001
1011
STEP
0111
EMPTY1
5
1101
B
111
1011
ENTER
0111
NONE
光靠矩阵键盘是无法正确地完成输入工作的,另外还需搭配以下几个电路模块: 1、 时钟产生电路
当一个系统中使用不同操作频率的脉冲波形时,最方便的方法就是利用一个自由计数器 来产生各种频率。本电路中就使用三种不同频率的工作脉冲波形。它们分别是:系统时钟(它 是系统内部所有时钟的提供者,频率最高)、弹跳消除取样信号、键盘扫描信号和七段显示器 扫描信号。在很多的电路设计中,键盘扫描信号和七段显示器扫描信号可以使用相同的时钟 信号,本设计也采用此方法。
Beijing Techshine Technology Co.
矩阵键盘实验说明
#define TIMER_DEVICE_ID
XPAR_XSCUTIMER_0_DEVICE_ID
#define INTC_DEVICE_ID
XPAR_SCUGIC_SINGLE_DEVICE_ID
XScuGic_InterruptHandler
/*
* The following constants define the positions of the buttons and LEDs
each
* channel of the GPIO
*/
#define LEDS_ALL_ON
0x00
#define LEDS_ALL_OFF
三.源代码说明
3.1 头文件说明
Matrix_Keyboard.h 文件源代码 /********************************************************************** *******/ /** * @file Matrix_Keyboard.h * * 该文件包含矩阵键盘项目所包含的库文件、宏定义、常数、全局变量、函数定义 * * <pre> * MODIFICATION HISTORY: * * Ver Who Date Changes * ----- ---- -------- -----------------------------------------------------* 1.0 lj 07/28/06 创建该文件fine HIGH_MASK 0xF0
/*
* The following constants define the GPIO channel that is used for the
一种矩阵键盘的扫描定位的方法(编码方式)
图1是本发明方法的键盘扫描定位原理框图,图2是说明本发明方法的一个实施例的电路图,所述方法通过嵌入式设备和键盘扫描定位程序来实现,所述的嵌入式设备包括键盘和微控制器,所述的键盘扫描定位程序在微控制器中运行。
图1图2中,键盘的4个按键以2×2的矩阵形式排列,所有的行线与列线都通过上拉电阻接至电源+VCC,并连接至微控制器的I/O接口。
本实施例要求利用4个按键实现以下操作:操作0:键盘从有键按下恢复到没有任何键按下后,时间达到2min时,执行一次操作0;操作1:按键S1单键按下操作时,执行一次操作1;操作2:按键S2单键按下操作时,执行一次操作2;按键S2单键按下时间持续3s以上后,每隔0.1s执行一次操作2,直到S2释放(或者键盘状态发生其他改变);操作3:按键S3单键按下时间持续2s以上后,执行一次操作3;操作4:按键S3单键释放操作时,执行一次操作4;操作5:按键S4单键按下后,再按下按键S3的组合键操作,执行一次操作5。
如图1所示的键盘进行初始化,主要是前后读入2次键值,分别作为前态键值与现态键值保存,组合成状态码,同时作为前态状态码和现态状态码保存。
如图1所示的等待键盘扫描时间到,等待时间周期T为10~50ms之间的一个固定值,本实施例选择等待时间为20ms,微控制器采用周期扫描的方式对键盘的当前状态进行读取采样。
如图1所示的采样读取现态键值,本实施例中,图2所示键盘的键值为4位二进制码。
例如,没有键按下的键值是1111,S1按下的键值是0101,S1、S2同时按下的键值是0100。
采样读取键值的方法为反转法。
首先在所有行线输出低电平,采样读取列线状态作为键值的高2位;再在所有列线输出低电平,采样读取行线状态作为键值的低2位;组合键值的高2位和低2位,得到4位键值。
在采样读取现态键值前,将上一次采样读取的键值保存为前态键值。
如图1所示的键盘状态是否稳定判断,用于确定键盘是否处于稳定状态,如果前后两次键盘采样的键值相同,即现态键值等于前态键值,键盘处于稳定状态,进入下一步骤;如果前后两次键盘采样的键值不同,现态键值不等于前态键值,则返回等待下一次键盘扫描时间到。
013、4×4矩阵式键盘识别技术
13.4×4矩阵式键盘识别技术1.实验任务如图4.13.2所示,用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序号。
对应的按键的序号排列如图4.13.1所示图4.13.12.硬件电路原理图图4.13.23.系统板上硬件连线(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.程序框图图4.13.36.汇编源程序KEYBUFEQU30HORG00HSTART:MOVKEYBUF,#2 WAIT:MOVP3,#0FFHCLRP3.4MOVA,P3ANLA,#0FHXRLA,#0FH JZNOKEY1 LCALLDELY10MS MOVA,P3ANLA,#0FHXRLA,#0FH JZNOKEY1MOVA,P3ANLA,#0FH CJNEA,#0EH,NK1 MOVKEYBUF,#0 LJMPDK1NK1:CJNEA,#0DH,NK2 MOVKEYBUF,#1 LJMPDK1NK2:CJNEA,#0BH,NK3 MOVKEYBUF,#2 LJMPDK1NK3:CJNEA,#07H,NK4 MOVKEYBUF,#3 LJMPDK1NK4:NOPDK1:MOVA,KEYBUF MOVDPTR,#TABLE MOVCA,@A+DPTR MOVP0,ADK1A:MOVA,P3 ANLA,#0FHXRLA,#0FHJNZDK1ANOKEY1:MOVP3,#0FFHCLRP3.5MOVA,P3ANLA,#0FHXRLA,#0FH JZNOKEY2 LCALLDELY10MS MOVA,P3ANLA,#0FHXRLA,#0FH JZNOKEY2MOVA,P3ANLA,#0FH CJNEA,#0EH,NK5 MOVKEYBUF,#4LJMPDK2NK5:CJNEA,#0DH,NK6 MOVKEYBUF,#5 LJMPDK2NK6:CJNEA,#0BH,NK7 MOVKEYBUF,#6 LJMPDK2NK7:CJNEA,#07H,NK8 MOVKEYBUF,#7 LJMPDK2NK8:NOPDK2:MOVA,KEYBUF MOVDPTR,#TABLE MOVCA,@A+DPTRMOVP0,ADK2A:MOVA,P3ANLA,#0FHXRLA,#0FHJNZDK2ANOKEY2:MOVP3,#0FFHCLRP3.6MOVA,P3ANLA,#0FHXRLA,#0FHJZNOKEY3 LCALLDELY10MS MOVA,P3ANLA,#0FHXRLA,#0FHJZNOKEY3MOVA,P3ANLA,#0FHCJNEA,#0EH,NK9 MOVKEYBUF,#8 LJMPDK3NK9:CJNEA,#0DH,NK10 MOVKEYBUF,#9 LJMPDK3NK10:CJNEA,#0BH,NK11 MOVKEYBUF,#10 LJMPDK3NK11:CJNEA,#07H,NK12 MOVKEYBUF,#11 LJMPDK3NK12:NOPDK3:MOVA,KEYBUF MOVDPTR,#TABLE MOVCA,@A+DPTRMOVP0,ADK3A:MOVA,P3ANLA,#0FHXRLA,#0FHJNZDK3ANOKEY3:MOVP3,#0FFHCLRP3.7MOVA,P3ANLA,#0FHXRLA,#0FHJZNOKEY4 LCALLDELY10MS MOVA,P3ANLA,#0FHXRLA,#0FHJZNOKEY4MOVA,P3ANLA,#0FHCJNEA,#0EH,NK13 MOVKEYBUF,#12 LJMPDK4NK13:CJNEA,#0DH,NK13 MOVKEYBUF,#13 LJMPDK4NK13:CJNEA,#0BH,NK15 MOVKEYBUF,#13 LJMPDK4NK15:CJNEA,#07H,NK16 MOVKEYBUF,#15 LJMPDK4NK16:NOPDK4:MOVA,KEYBUF MOVDPTR,#TABLEMOVCA,@A+DPTRMOVP0,ADK4A:MOVA,P3ANLA,#0FHXRLA,#0FHJNZDK4ANOKEY4:LJMPWAITDELY10MS:MOVR6,#10D1:MOVR7,#248DJNZR7,$DJNZR6,D1RETTABLE:DB3FH,06H,5BH,4FH,66H,6DH,7DH,07HDB7FH,6FH,77H,7CH,39H,5EH,79H,71HEND7.C语言源程序#include<AT89X51.H>unsignedcharcodetable[]={0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};unsignedchartemp;unsignedcharkey;unsignedchari,j;voidmain(void){while(1){P3=0xff;P3_4=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--)for(j=200;j>0;j--);temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f; switch(temp){case0x0e:key=7;break;case0x0d:key=8;break;case0x0b:key=9;break;case0x07:key=10;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_5=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f;switch(temp){case0x0e:key=4;break;case0x0d:key=5;break;case0x0b:key=6;break;case0x07:key=11;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_6=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f; switch(temp){case0x0e:key=1;break;case0x0d:key=2;break;case0x0b:key=3;break;case0x07:key=12;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f;}}}P3=0xff;P3_7=0;temp=P3;temp=temp&0x0f;if(temp!=0x0f){for(i=50;i>0;i--) for(j=200;j>0;j--); temp=P3;temp=temp&0x0f;if(temp!=0x0f){temp=P3;temp=temp&0x0f; switch(temp){case0x0e:key=0;break;case0x0d:key=13;break;case0x0b:key=13;break;case0x07:key=15;break;}temp=P3;P1_0=~P1_0;P0=table[key]; temp=temp&0x0f; while(temp!=0x0f) {temp=P3;temp=temp&0x0f; }}}}}。
数码管显示及键盘检测
数码管的显示数码管的显示原理同流水灯,都是通过控制单片机输出的的高低电平控制发光二极管的点亮和熄灭。
使用LED 显示器时,要注意区分这两种不同的接法。
为了显示数字或字符,必须对数字或字符进行编码。
七段数码管加上一个小数点,共计8段。
因此为LED 显示器提供的编码正好是一个字节。
TX 实验板用共阴LED 显示器,根据电路连接图显示16进制数的编码已列在下表。
共阴数码管码表▪ 0x3f , 0x06 , 0x5b , 0x4f , 0x66 , 0x6d , ▪ 0 1 23 4 5▪ 0x7d , 0x07 , 0x7f , 0x6f , 0x77 , 0x7c , ▪ 6 7 8 9 A B ▪ 0x39 , 0x5e , 0x79 , 0x71 , 0x00 ▪ C D E F 无显示静态显示方式LED 显示器工作方式有两种:静态显示方式和动态显示方式。
静态显示的特点是每个数码管的段选必须接一个8位数据线来保持显示的字形码。
当送入一次字形码后,显示字形可一直保持,直到送入新字形码为止。
这种方法的优点是占用CPU 时间少,显示便于监测和控制。
缺点是硬件电路比较复杂,成本较高。
动态显示动态显示的特点是将所有位数码管的段选线并联在一起,由位选线控制是哪一位数码管有效。
这样一来,就没有必要每一位数码管配一个锁存器,从而大大地简化了硬件电路。
选亮数码管采用动态扫描显示。
所谓动态扫描显示即轮流向各位数码管送出字形码和相应的位选,利用发光管的余辉和人眼视觉暂留作用,使人的感觉好像各位数码管同时都在显示。
动态显示的亮度比静态显示要差一些,所以在选择限流电阻时应略小于静态显示电路中的。
动态显示实例 :原理图:cd e GND dpa b c d e f g f d b(a ) b )例:利用动态显示在数码管上显示1,2,3,4;#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit dula=P0;sbit wela=P2;uchar num;uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//字符数组uchar code s[]={1,2,4,8};//位选数码管1,2,3,4 void delay(uint z);void main(){wela=1;//11101010P0=0xea;wela=0;//初始化while(1){for(num=1;num<5;num++){P0=table[num];delay(1000);P2=s[num-1];}}}void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}*数码管动态显示注意事项1,动态显示需注意延时的时间,延时的时间决定数码管的亮度2,多个数码管显示时扫描的频率,保证显示不闪烁下面做一个数码管显示实验,利用静态显示在数码管上显示1;源程序:#include<reg52.h>#define uint unsigned int#define uchar unsigned charsbit dula=P0;sbit wela=P2;void main(){wela=1;//选择第一个数码管P0=0x06;//显示编码1}静态显示会浪费很多的IO口,所以常用动态显示键盘检测1、键盘的分类●键盘分编码键盘和非编码键盘。
独立键盘和矩阵键盘-PPT
图8.2 矩阵式键盘接口
特点:电路连接复杂,但提高了 I/O口利用率,软件编程较复 杂。适用于需使用大量按键 得场合。
U1
P10 1 P11 2 P12 3 P13 4 P14 5 P15 6 P16 7 P17 8
P10 P11 P12 P13 P14 P15 P16 P17
P00 P01 P02 P03 P04 P05 P06 P07
设第2行第 4列键按下
89C51 P1.0 P1.1 P1.2 P1.3 P1.4 11 11 11 1011 P1.5 P1.6 P1.7
+5V
101 110 110 01
行线输出 列线输入
0111 1011 1101 1110
1111 1110 1111 1111
(2)线反转法。 线反转法也就是识别闭合键得一种常用方法, 该 法比行扫描速度快, 但在硬件上要求行线与列线外 接上拉电阻。 先将行线作为输出线, 列线作为输入线, 行线输出 全“0”信号, 读入列线得值, 那么在闭合键所在得列 线上得值必为0;然后从列线输出全“0”信号,再读取 行线得输入值,闭合键所在得行线值必为 0。这样, 当一个键被按下时, 必定可读到一对唯一得行列值。 再由这一对行列值可以求出闭合键所在得位置。
独立键盘和矩阵键盘
通常,键盘有编码与非编码两种。编码键盘通过 硬件电路产生被按按键得键码与一个选通脉冲。选 通脉冲可作为CPU得中断请求信号。这种键盘使用 方便,所需程序简单,但硬件电路复杂,常不被单片机采 用。
非编码键盘按组成结构又可分为独立式键盘与 矩阵式键盘。独立式键盘得工作过程与矩阵式键盘 类似,无论就是硬件结构还就是软件设计都比较简单,。
…… else if (表达式n-1) (语句n-1;) else {语句n}
矩阵键盘原理
距阵键盘矩阵键盘是单片机编程中所使用的键盘.1.矩阵式键盘的结构与工作原理在键盘中按键数量较多时,为了减少I/O口的占用,通常将按键排列成矩阵形式,如图1所示。
在矩阵式键盘中,每条水平线和垂直线在交叉处不直接连通,而是通过一个按键加以连接。
这样,一个端口(如P1口)就可以构成4*4=16个按键,比之直接将端口线用于键盘多出了一倍,而且线数越多,区别越明显,比如再多加一条线就可以构成20键的键盘,而直接用端口线则只能多出一键(9键)。
由此可见,在需要的键数比较多时,采用矩阵法来做键盘是合理的。
矩阵式结构的键盘显然比直接法要复杂一些,识别也要复杂一些,上图中,列线通过电阻接正电源,并将行线所接的单片机的I/O口作为输出端,而列线所接的I/O口则作为输入。
这样,当按键没有按下时,所有的输出端都是高电平,代表无键按下。
行线输出是低电平,一旦有键按下,则输入线就会被拉低,这样,通过读入输入线的状态就可得知是否有键按下了。
具体的识别及编程方法如下所述。
2、矩阵式键盘的按键识别方法确定矩阵式键盘上何键被按下介绍一种“行扫描法”。
行扫描法行扫描法又称为逐行(或列)扫描查询法,是一种最常用的按键识别方法,如上图所示键盘,介绍过程如下。
1、判断键盘中有无键按下将全部行线Y0-Y3置低电平,然后检测列线的状态。
只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。
若所有列线均为高电平,则键盘中无键按下。
2、判断闭合键所在的位置在确认有键按下后,即可进入确定具体闭合键的过程。
其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。
在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。
若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
下面给出一个具体的例子:图仍如上所示。
8031单片机的P1口用作键盘I/O口,键盘的列线接到P1口的低4位,键盘的行线接到P1口的高4位。