51单片机 c语言 矩阵键盘1号
51单片机行列式键盘程序
扫描法:以4*4矩阵按键为例,将全部行线置低电平,然后检测列线的状态。
只要有一列的电平为低,则表示键盘中有键被按下,而且闭合的键位于低电平线与4根行线相交叉的4个按键之中。
若所有列线均为高电平,则键盘中无键按下。
判断闭合键所在的位置:在确认有键按下后,即可进入确定具体闭合键的过程。
其方法是:依次将行线置为低电平,即在置某根行线为低电平时,其它线为高电平。
在确定某根行线位置为低电平后,再逐行检测各列线的电平状态。
若某列为低,则该列线与置为低电平的行线交叉处的按键就是闭合的按键。
#include "reg52.h"#define uchar unsigned char#define uint unsigned intvoid Delay_1ms(uint i);uchar keyScan(void);void Main(void){uchar keyValue;//存放键值,第一行的第一个为1第二行第一个为5,依次排列while(1){P1 = 0xf0;if(P1 != 0xf0)//判断是否有键按下{Delay_1ms(20);//消除键抖动if(P1 != 0xf0)//在此判断是否有键按下{keyValue = keyScan(); //逐行扫描,判断是哪个按键按下}}//此处用于对不同键值做出不同反应}}uchar keyScan(void){uchar temp,i,j,lineSelect[4]={0xef, 0xdf, 0xbf, 0x7f}; //数组用于线选for(j=0;j<4;j++)//循环四次用于四个行线依次拉低{P1=lineSelect[j];//每根行线依次拉低temp=1;for(i=0;i<4;i++)//循环四次用于判断哪列有键按下{if(!(P1&temp))//判断此列是否有键按下return (i+j*4);//返回键值,行*4+列,行和列的交叉处temp<<=1;//将目标移为下一列}}}void Delay_1ms(uint i)//延时函数{uchar x,j;for(j=0;j<i;j++)for(x=0;x<=148;x++);}线翻转法:Step 1:将列线作为输出线,行线作为输入线。
51单片机矩阵键盘程序示例
;lab5_asm;vol1.0;zqy;2012/2/18;定义初始化LED_CHABIT PSW数码管显示标志位,为1显示十位,为0显示个位;数字0-9ORG 00HJMP STARTORG 000BHJMP INT_T0转到中断服务程序,更改数码管显示ORG 0100HLED_TAB1:DB 0BFH,86H,0DBH,0CFH,0E6H,0EDHDB 0FDH,87H,0FFH,0EFH,0BFHDB 86H,0DBH,0CFH,0E6H,0EDH,0FDHLED_TAB2:DB 0BFH,0BFH,0BFH,0BFH,0BFHDB 0BFH,0BFH,0BFH,0BFH,0BFHDB 86H,86H,86H,86HDB 86H,86H,86HSTART:;工作寄存器和某些数据单元的初始化MOV R0,#0;数码管显示初始化SETB LED_CHAMOVDPTR, #8300H位选地址赋给DPTR高八位P2 口,选中U13锁存器MOVA,#OFEH位选数据,选中个位数码管,置低为选中MOVX@DPTR,脸选数据,对片外I/O 口的外设芯片访问MOVDPTR,#8200H段选地址MOVA,#OBFH段选数据,个位显示0MOVX@DPTR, A;定时器初始化MOV IE,#82H开启定时器T0中断MOV TMOD,#01H设定定时器T0为模式1MOV TH0,#0D8HMOV TL0,#0F0H装入初值,10MS 延时12MHZSETB TRC启动定时器T0KEY:;按键处理LCALL KEY_START用判断有无键按下子程序JZ KEY无键按下,重新扫描LCALL KEY_DELAY键按下,延时去抖LCALL KEY_STARTJZ KEYLCALL KEY_NEXT断哪一个键被按下LCALL DECODED® 译码LCALL KEY_EN判断按键释放LJMP KEYKEY_START:MOV DPTR, #8000H键盘地址MOV A,#0F0HMOVX @DPTR,A亍全部输出0 NOPNOPNOPMOVX A,@DPTR3 描键盘CPL A取正逻辑,1为按下ANL A,#0FHRETKEY_NEXT:MOV R1,# 0扫描行计数器MOV R2,# 0扫描列计数器MOV R3,#0FEH首行扫描字送R3 MOV DPTR, #8000HMOV A,R3MOVX @DPTR,AMOVX A,@DPTRCPL AANL A,#0FHMOV R4,#4S0123: JNZ SKEY不;为全0,有键按下; 全为0,进行下一行扫描INC R1行计数器加1MOV A,R3RL AMOV R3,AMOV DPTR,#8000HMOVX @DPTR,ANOPNOPNOPMOVX A,@DPTRCPL AANL A,#0FHDJNZ R4,S0123LJMP KEYEKEY:RETSKEY 0列号译码JBACC.0,SKEY1JBACC.1,SKEY2JBACC.2,SKEY3JBACC.3,SKEY4SKEY1:M0V A,#00存列号0 MOV R2,AAJMP EKEYSKE Y2:M0V A,#01存列号1 MOV R2,AAJMP EKEYSKEY3:M0V A,#02存列号2 MOV R2,AAJMP EKEYSKEY4: MOV A,#03存列号3 MOV R2,AAJMP EKEYDECODE:;行号在R1列号在R2;键值译码MOV A,R1MOV B,#04HMUL ABADD A,R2INC AMOV R0,ARETKEY_END:MOV DPTR,#8000H键盘地址MOVX A,@DPTR3 描键盘CPL A取正逻辑,1为按下ANL A,#0FHJNZ KEY_ENDLCALL KEY_DELAYJNZ KEY_ENDRETKEY_DELAY:MOV R5,#10HDS1:MOV R6,#0FFHDS2:NOPDJNZ R6,DS2DJNZ R5,DS1RETINT_TO:;中断服务程序,更改数码管显示MOV R7,AJB LED_CHA,DISP检查数码管显示标志位CPL LED_CHAMOVDPTR, #8200H段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H位选地址赋给DPTR高八位P2 口,选中U13锁存器MOVA, #0FEH位选数据,选中个位数码管,置低为选中MOVX@DPTR, A位选数据,对片外I/O 口的外设芯片访问; 判断需要显示的个位数字MOV A,R0NOPMOV DPTR,#LED_TAB1NOPNOPMOVC A,@A+DPTRMOVDPTR, #82001■段选地址MOVX @DPTR,AJMP INT_EXITDISP_L:CPL LED_CHAMOVDPTR, #8200H段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H位选地址赋给DPTR高八位P2 口,选中U13锁存器MOVA, #0FDH位选数据,选中十位数码管,置低为选中MOVX@DPTR, A位选数据,对片外I/O 口的外设芯片访问;判断需要显示的十位数字0 或1MOV A,R0NOPMOV DPTR,#LED_TAB2MOVC A,@A+DPTRMOVDPTR, #8200H段选地址MOVX @DPTR,AINT_EXIT:MOV IE,#82HMOV TH0,#0D8HMOV TLO,#OFOH装入初值,10MS延时SETB TR0MOV A,R7MOV DPTR,#8000HRETIEND12MHZ。
51单片机矩阵键盘程序示例
;lab5_asm;vol1.0;zqy;2012/2/18;定义初始化LED_CHABIT PSW.5;数码管显示标志位,为1显示十位,为0显示个位;数字0-9ORG 00HJMP STARTORG 000BHJMP INT_T0;转到中断服务程序,更改数码管显示ORG 0100HLED_TAB1:DB 0BFH,86H,0DBH,0CFH,0E6H,0EDHDB 0FDH,87H,0FFH,0EFH,0BFHDB 86H,0DBH,0CFH,0E6H,0EDH,0FDHLED_TAB2:DB 0BFH,0BFH,0BFH,0BFH,0BFHDB 0BFH,0BFH,0BFH,0BFH,0BFHDB 86H,86H,86H,86HDB 86H,86H,86HSTART:;工作寄存器和某些数据单元的初始化MOV R0,#0;数码管显示初始化SETB LED_CHAMOVDPTR, #8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA,#0FEH;位选数据,选中个位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问MOVDPTR,#8200H;段选地址MOVA,#0BFH;段选数据,个位显示0MOVX@DPTR, A;定时器初始化MOV IE,#82H;开启定时器T0中断MOV TMOD,#01H;设定定时器T0为模式1MOV TH0,#0D8HMOV TL0,#0F0H;装入初值,10MS延时12MHZSETB TR0 ;启动定时器T0KEY:;按键处理LCALL KEY_START;调用判断有无键按下子程序JZ KEY;无键按下,重新扫描LCALL KEY_DELAY;有键按下,延时去抖LCALL KEY_STARTJZ KEYLCALL KEY_NEXT;判断哪一个键被按下LCALL DECODE;键值译码LCALL KEY_END;判断按键释放LJMP KEYKEY_START:MOV DPTR, #8000H;键盘地址MOV A,#0F0HMOVX @DPTR,A;行全部输出0NOPNOPNOPMOVX A,@DPTR;扫描键盘CPL A;取正逻辑,1为按下ANL A,#0FHRETKEY_NEXT:MOV R1,#0;扫描行计数器MOV R2,#0;扫描列计数器MOV R3,#0FEH;首行扫描字送R3 MOV DPTR, #8000HMOV A,R3MOVX @DPTR,AMOVX A,@DPTRCPL AANL A,#0FHMOV R4,#4S0123: JNZ SKEY0;不为全0,有键按下;全为0,进行下一行扫描INC R1;行计数器加1MOV A,R3RL AMOV R3,AMOV DPTR,#8000HMOVX @DPTR,ANOPNOPNOPMOVX A,@DPTRCPL AANL A,#0FHDJNZ R4,S0123LJMP KEYEKEY:RETSKEY0:;列号译码JBACC.0,SKEY1JBACC.1,SKEY2JBACC.2,SKEY3JBACC.3,SKEY4SKEY1:MOV A,#00H;存列号0 MOV R2,AAJMP EKEYSKEY2:MOV A,#01H;存列号1 MOV R2,AAJMP EKEYSKEY3:MOV A,#02H;存列号2MOV R2,AAJMP EKEYSKEY4: MOV A,#03H;存列号3 MOV R2,AAJMP EKEYDECODE:;行号在R1,列号在R2;键值译码MOV A,R1MOV B,#04HMUL ABADD A,R2INC AMOV R0,ARETKEY_END:MOV DPTR,#8000H;键盘地址MOVX A,@DPTR;扫描键盘CPL A;取正逻辑,1为按下ANL A,#0FHJNZ KEY_ENDLCALL KEY_DELAYJNZ KEY_ENDRETKEY_DELAY:MOV R5,#10HDS1:MOV R6,#0FFHDS2:NOPDJNZ R6,DS2DJNZ R5,DS1RETINT_T0:;中断服务程序,更改数码管显示MOV R7,AJB LED_CHA,DISP_L;检查数码管显示标志位CPL LED_CHAMOVDPTR, #8200H;段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA, #0FEH;位选数据,选中个位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问;判断需要显示的个位数字MOV A,R0NOPMOV DPTR,#LED_TAB1NOPNOPMOVC A,@A+DPTRMOVDPTR, #8200H;段选地址MOVX @DPTR,AJMP INT_EXITDISP_L:CPL LED_CHAMOVDPTR, #8200H;段选地址MOV A,#0MOVX @DPTR,AMOVDPTR,#8300H;位选地址赋给DPTR高八位P2口,选中U13锁存器MOVA, #0FDH;位选数据,选中十位数码管,置低为选中MOVX@DPTR, A;位选数据,对片外I/O口的外设芯片访问;判断需要显示的十位数字0或1MOV A,R0NOPMOV DPTR,#LED_TAB2MOVC A,@A+DPTRMOVDPTR, #8200H;段选地址MOVX @DPTR,AINT_EXIT:MOV IE,#82HMOV TH0,#0D8HMOV TL0,#0F0H;装入初值,10MS延时SETB TR0MOV A,R7MOV DPTR,#8000HRETIEND12MHZ。
基于51单片机的六层电梯c语言矩阵键盘控制系统
#include〈reg51.h〉#define MAXFLOOR 6unsigned char code LEDCODES[]={0x3f,0x06, 0x5b, 0x4f,0x66,0x6d,0x7d}; sbit LEDUP=P3^6;sbit LEDDOWN=P3^7;bit DIRECTION=1,STOP=0;unsigned char CURFLOOR=1;unsigned char DESTFLOOR=1;unsigned char RUN=1;unsigned int timer1=0, timer2=0;unsigned char CALLFLOORUP[7]={0, 0,0, 0, 0, 0, 0};unsigned char CALLFLOORDOWN[7]={0, 0, 0, 0, 0,0,0};unsigned char CALLFLOOR[7]={0, 0,0, 0, 0, 0,0};unsigned char keyscan(void);unsigned char key;void readarray(void);void SELECTNEXT();void step(bit DIRECTION);void DELAY(unsigned int Z);void DELAY2(unsigned int S);void JUDGESIT();void main(void){P0=LEDCODES[1];TH0=0x3C;TL0=0xB0;TMOD=0x01;ET0=1;EA=1;EX0=1;IT0=1;while(1){if(! RUN&&! STOP){SELECTNEXT();step(DIRECTION);}else if(STOP){timer2=0;TR0=1;while(timer2<100&&STOP);TR0=0;timer2=0;STOP=0;}return;}}void SELECTNEXT(){ char n;if(CURFLOOR==MAXFLOOR){DIRECTION=0;}else if(CURFLOOR==1){DIRECTION=1;}if(DIRECTION==0){if(CALLFLOORDOWN[CURFLOOR]){CALLFLOORDOWN[CURFLOOR]=0;STOP=1;return;}for(n=CURFLOOR-1;n〉=1;n——)if(CALLFLOORDOWN[n]){DESTFLOOR=n;return;}for(n=0;n<CURFLOOR;n++)if(CALLFLOORUP[n]){DESTFLOOR=n;return;}DIRECTION=1;for(n=CURFLOOR+1;n<=MAXFLOOR;n++)if(CALLFLOORUP[n]){DESTFLOOR=n;return;}for(n=MAXFLOOR;n>CURFLOOR;n——)if(CALLFLOORDOWN[n]){DESTFLOOR=n;return;}}else{if(CALLFLOORUP[CURFLOOR]){CALLFLOORUP[CURFLOOR]=0;STOP=1;return;}for(n=CURFLOOR+1;n<=MAXFLOOR;n++)if(CALLFLOORUP[n]){DESTFLOOR=n;return;}for(n=MAXFLOOR;n〉CURFLOOR;n——)if(CALLFLOORDOWN[n]){DESTFLOOR=n;return;}DIRECTION=0;for(n=CURFLOOR-1;n〉=1;n——)if(CALLFLOORDOWN[n]){DESTFLOOR=n;return;}for(n=1;n〈=CURFLOOR;n++)if(CALLFLOORDOWN[n]){DESTFLOOR=n;return;}}}void step(bit DIRECTION){if(DESTFLOOR==CURFLOOR)return;else if(! RUN){RUN=1;DELAY(50);if(DIRECTION==1){LEDUP=0;LEDDOWN=1;}else{LEDUP=1;LEDDOWN=0;}timer1=0;TR0=1;}}void DELAY(unsigned int Z){unsigned int X, Y;for(X=Z;X〉0;X-—)for(Y=125;Y>0;Y—-);}void timer0_int() interrupt 1{TH0=0x3C;TL0=0xB0;timer1++;timer2++;if(RUN){if(timer1==20){timer1=0;if(DIRECTION){CURFLOOR++;CALLFLOORUP[CURFLOOR]=0;}else{CURFLOOR—-;CALLFLOORDOWN[CURFLOOR]=0;}RUN=0;TR0=0;P0=LEDCODES[CURFLOOR];if(DESTFLOOR==CURFLOOR){TR0=0;LEDUP=1;LEDDOWN=1;STOP=1;return;}}}}void readarray(void){unsigned char key;while(1){key=keyscan();switch(key){case 0xee:CALLFLOORDOWN[6]=1;break;case 0xed: CALLFLOORUP[5]=1;break;case 0xeb: CALLFLOORDOWN[5]=1;break;case 0xe7: CALLFLOORUP[4]=1;break;case 0xde: CALLFLOORDOWN[4]=1;break;case 0xdd:CALLFLOORUP[3]=1;break;case 0xdb: CALLFLOORDOWN[3]=1;break;case 0xd7: CALLFLOORUP[2]=1;break;case 0xbe: CALLFLOORDOWN[2]=1;break;case 0xbd:CALLFLOORUP[1]=1;break;case 0xbb:CALLFLOORDOWN[6]=1;JUDGESIT();break;case 0xb7:CALLFLOORDOWN[5]=1;JUDGESIT();break;case 0x7e:CALLFLOORDOWN[4]=1;JUDGESIT();break;case 0x7d: CALLFLOORDOWN[3]=1;JUDGESIT();break;case 0x7b:CALLFLOORDOWN[2]=1;JUDGESIT();break;case 0x77: CALLFLOORDOWN[1]=1;JUDGESIT();break;}}}unsigned char keyscan(void) //键盘扫描函数, 使用行列反转扫描法{unsigned char cord_h,cord_l;//行列值中间变量P1=0x0f; //行线输出全为0cord_h=P1&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{DELAY2(100); //去抖if(cord_h! =0x0f){cord_h=P1&0x0f; //读入列线值P1=cord_h|0xf0; //输出当前列线值cord_l=P1&0xf0; //读入行线值return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}void DELAY2(unsigned int S){while(S——);}void JUDGESIT(){char m;for(m=1;m<=MAXFLOOR;m++){if (CALLFLOOR[m]){if (CURFLOOR<=m){CALLFLOORUP[m]=1;CALLFLOOR[m]=0;return;}else{CALLFLOORDOWN[m]=1;CALLFLOOR[m]=0;return;}}}}。
51单片 矩阵键盘按键程序
}
}
P3=0xfb;//第三行
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xeb:key=8;
break;
case 0xdb:key=9;
{
delay(10);
//temp=P3;
temp=P3&0xf0;
if(temp!=0xf0)
{
//temp=P3;
switch(P3)
{
case 0xee:key=0;
break;
case 0xde:key=1;
break;
case 0xbe:key=2;
break;
case 0x7e:key=3;
}
void delay(unsigned int z)
{
unsigned int x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
int keyscan()
{
P3=0xfe;//第一行有别于二三四行
//temp=P3;
temp=P3&0xf0;
if(temp!=0xf0)
/*矩阵键盘*/
#include <REG52.H>
sbit du=P2^6;
sbit we=P2^7;
unsigned int i,j,key,temp;
char code table[]={0x3f,0x06,0x5b,0x4f,
51单片机矩阵键盘按键C语言程序
#include<reg52.h>#define uchar unsigned char#define uint unsigned intucharsmg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x7 1} ;uchar smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78} ;//有一篇74HC573必须为高电平//*************************8//12M频率下大约50US延时//**************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--) ;}void delay_50ms(uint t){uchar j;for(;t>0;t--)for(j=6245;j>0;j--);}/*这个程序可以不用松手检测,因为我们程序首选判断键是否按下然后发现按下后我们延时5MS,然后再检测。
确实是按下啦。
我们再执行在第二个循环假如我们继续检测,那么消耗时间10MS这个短时间中我们的按键已经松手啦。
不会在执行后面的。
*/void main(){uchar key_l,key_h;uchar key;while(1){P3=0xf0; //首先给P3口赋值key_l=P3; //从p3口读一个数据到key_lkey_l=key_l&0xf0;if(key_l!=0xf0) //如果不等于的话,说明有按键按下去{delay_50us(100);//稍微延时一下if(key_l!=0xf0){key_l=P3&0xf0;// 11100000 再读一次P3的值然后和0xf0相与key_l=key_l|0x0f; // 11101111P3=key_l; //在把key_l的值送给P3口//此时P3口的值为11101111,而正在此时我们把键按下啦因此按下的键为11101110与11101111// 相与还是11101110;key_h=P3; //再读一次P3口,键还是按下,可以得到行的值。
试述51系列单片机矩阵键盘编程
试述51系列单片机矩阵键盘编程摘要在单片机系统中,常常使用键盘向单片机输入信息。
键盘由一组常开的按键组成,当按键闭合时就会向单片机系统输入一个电平信息。
每个按键都被赋予了一个键码,单片机根据此代码执行任务。
在单片机系统按键数量较多时,为了减少I/O口的使用通常使用矩阵键盘。
关键词单片机;键盘;矩阵键盘;I/O口1 矩阵键盘的结构矩阵键盘的按键排成矩阵,一般是4×4矩阵,即4行4列,行和列的交叉点接一个常开的独立按键,按键被闭合时就接通行线和列线。
8个I/O口产生16个交叉点16个按键,按键数量比独立按键多了一倍,9个I/O口产生20个按键,I/O口越多产生的按键数量越多,效果越明显。
可以在键盘扫描程序中对每个按键进行编号,如第一行按键从左到右对应0、1、2、3,第二行按键从左到右对应4、5、6、7,第三行按键从左到右对应8、9、A、B,第四行按键左到右对应C、D、E、F,每按一次键让数码管显示该按键所代表的编号。
2 矩阵键盘的工作原理矩阵键盘结构比独立键盘复杂,识别难度也比独立按键大很多。
矩阵键盘的工作方式有程序扫描方式、定时扫描方式、中断扫描方式3种。
本文只讨论程序扫描方式。
程序扫描方式是CPU主动调用扫描子函数,响应键盘的输入要求。
在子函数里有以下步骤:1)判断键盘中有无按键闭合;2)延时去抖消除干扰;3)检测是否确实有按键闭合,确定闭合键的编号;4)等待闭合键的释放。
整个步骤中确定闭合键的编号是关键所在,常用的判断方法有逐行扫描法和反转扫描法。
3 硬件仿真4×4矩阵键盘无需外接电源,电位变化完全由编程来决定。
通过软件延时来消抖动,去干扰。
4×4矩阵键盘4行4列交叉,每个按键位于交叉点上对应的行列号唯一,共16个按键。
4×4矩阵键盘8个I/O口接P1口,7SEG-MPX2-AN-GREEN7段共阳极数码管通过上拉电阻接P0口。
键盘中每闭合一个按键让数码管显示对应的编号。
基于51单片机的矩阵键盘
case 4:wei_1=0;wei_2=1;wei_3=1;wei_4=1;break;
}
delay_ms(2)
P0=0x00;
//每次显示完后都要消隐,这非常重要!这句一缺数码管就会闪屏
wei_1=1;wei_2=1;wei_3=1;wei_4=1;
if(temp==1)key=key+0;
else if(temp==2)key=key+1;
if(temp==4)key=key+2;
else if(temp==8)key=key+3;
}
void led_init()
{
wei_1=1;wei_2=1;wei_3=1;wei_4=1;
P0=0x00;
break;
}
if(key_putdown())//这个if是转到第一个while的必要条件
break;
}
}
}
}
void main()
{
wei=1;
control=0;
led_init();
if(key_putdown())
while(1)
//这里用了两个while(1)嵌套
{
key_scan();
key_tem[control++]=key;
if(control==5){led_init();control=0;}
}
void led_disp(uchar wei2,uchar num)
{
P0=table[num];
switch(wei2)
[单片机矩阵键盘实验实验报告范文]矩阵键盘实验心得
[单片机矩阵键盘实验实验报告范文]矩阵键盘实验心得实验五矩阵键盘实验一、实验内容1、编写程序,做到在键盘上每按一个数字键(0-F)用发光二极管将该代码显示出来。
按其它键退出。
2、加法设计计算器,实验板上有12个按键,编写程序,实现一位整数加法运算功能。
可定义“A”键为“+”键,“B”键为“=”键。
二、实验目的学习独立式按键的查询识别方法。
2、非编码矩阵键盘的行反转法识别方法。
三、实验说明1、MCS51系列单片机的P0~P3口作为输入端口使用时必须先向端口写入“1”。
2、用查询方式检测按键时,要加入延时(通常采用软件延时10~20mS)以消除抖动。
3、识别键的闭合,通常采用行扫描法和行反转法。
行扫描法是使键盘上某一行线为低电平,而其余行接高电平,然后读取列值,如读列值中某位为低电平,表明有键按下,否则扫描下一行,直到扫完所有行。
行反转法识别闭合键时,要将行线接一并行口,先让它工作在输出方式,将列线也接到一个并行口,先让它工作于输入方式,程序使CPU通过输出端口在各行线上全部送低电平,然后读入列线值,如此时有某键被按下,则必定会使某一列线值为0。
然后,程序对两个并行端口进行方式设置,使行线工作于输入方式,列线工作于输出方式,并将刚才读得的列线值从列线所接的并行端口输出,再读取行线上输入值,那么,在闭合键所在行线上的值必定为0。
这样,当一个键被接下时,必定可以读得一对唯一的行线值和列线值。
由于51单片机的并口能够动态地改变输入输出方式,因此,矩阵键盘采用行反转法识别最为简便。
行反转法识别按键的过程是:首先,将4个行线作为输出,将其全部置0,4个列线作为输入,将其全部置1,也就是向P1口写入0某F0;假如此时没有人按键,从P1口读出的值应仍为0某F0;假如此时1、4、7、0四个键中有一个键被按下,则P1.6被拉低,从P1口读出的值为0某B0;为了确定是这四个键中哪一个被按下,可将刚才从P1口读出的数的低四位置1后再写入P1口,即将0某BF写入P1口,使P1.6为低,其余均为高,若此时被按下的键是“4”,则P1.1被拉低,从P1口读出的值为0某BE;这样,当只有一个键被按下时,每一个键只有唯一的反转码,事先为12个键的反转码建一个表,通过查表就可知道是哪个键被按下了。
(原创)51单片机C语言程序设计--速学教程实例(入门篇)之矩阵键盘(逐行扫描法)
Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xde:num=9; break; case 0xdd:num=10; break; case 0xdb:num=11; break; case 0xd7:num=12; break; } } } else num=17; P3=0xef; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xee:num=13; break; case 0xed:num=14; break; case 0xeb:num=15; break; case 0xe7:num=16; break; } }
case 0x7e:num=1; break; case 0x7d:num=2; break; case 0x7b:num=3; break; case 0x77:num=4; break; } } } else num=17; P3=0xbf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) { Delay1ms(5); temp=P3; temp=temp&0x0f; if(temp!=0x0f) { temp=P3; switch(temp) { case 0xbe:num=5; break; case 0xbd:num=6; break; case 0xbb:num=7; break; case 0xb7:num=8; break; } } } else num=17; P3=0xdf; temp=P3; temp=temp&0x0f; if(temp!=0x0f) {
51单片机的矩阵按键扫描的设计C语言程序
51单片机的矩阵按键扫描的设计C语言程序以下为一个基于51单片机的矩阵按键扫描的设计C语言程序:```c#include <reg51.h>//定义端口连接到矩阵键盘sbit col1 = P2^0;sbit col2 = P2^1;sbit col3 = P2^2;sbit row1 = P2^3;sbit row2 = P2^4;sbit row3 = P2^5;sbit row4 = P2^6;//声明按键函数char read_keypad(;void maiwhile (1)char key = read_keypad(; // 读取按键值//根据按键值进行相应操作switch(key)case '1'://第一行第一列按键逻辑//在此处添加相应的代码break;case '2'://第一行第二列按键逻辑//在此处添加相应的代码break;//继续处理其他按键//...default://未识别到按键break;}}//按键扫描函数char read_keypacol1 = 0; col2 = 1; col3 = 1; // 激活第一列if (row1 == 0) { // 第一行第一列按键被按下while (row1 == 0); //等待按键释放return '1'; // 返回按键值}if (row2 == 0) { // 第二行第一列按键被按下while (row2 == 0); //等待按键释放return '4'; // 返回按键值}if (row3 == 0) { // 第三行第一列按键被按下while (row3 == 0); //等待按键释放return '7'; // 返回按键值}if (row4 == 0) { // 第四行第一列按键被按下while (row4 == 0); //等待按键释放return '*'; // 返回按键值}col1 = 1; col2 = 0; col3 = 1; // 激活第二列//处理第二列的按键逻辑//...col1 = 1; col2 = 1; col3 = 0; // 激活第三列//处理第三列的按键逻辑//...return '\0'; // 返回空字符表示未检测到按键```以上代码中,我们使用51单片机的P2端口连接到矩阵键盘的列和行,通过扫描不同的列和检测行的状态来判断按键是否被按下。
51单片机 矩阵键盘 千百十个 加1减1
default: break;
}
}
}
void xianshi()//显示当前数值
{
//显示个位
P1_3=0;//开位码控制位,此段接PNP三极管8550的基极,低电平开位码。
P0=dis[ge];//显示段码
delay();//每次亮的状态为50us
P0=0xff;//清除数码管显示,因为是共阳极的,故为0xff。如不清除,则数码管上有鬼影
//51单片机控制四个数码管,P2口接4*4矩阵式键盘,采用行列翻转的原理,1键按下千位加1,5键按下千位减一,;2键按下百位加1,6键按下百位减1;
//3键按下十位加1,7键按下十位减1;4键按下个位加1,8键按下个位键1
#include<reg52.h>
#define uchar unsigned char
uchar row,col,k=0xff;//定义行、列、返回值、循环控制变量
unsigned char qian,bai,shi,ge;
sbit P1_3=P1^3;//个位位码
sbit P1_2=P1^2;//十位位码
sbit P1_1=P1^1;//百位位码
sbit P1_0=P1^0;//千位位码
break;
case 0xBd: k=7;//第二行第三列的按键按下(代号为7),数码管十位减1
if(shi==0) shi=9;
else shi=shi-1;
break;
case 0x7d: k=8;//第二行第四列的按键按下(代号为8),数码管个位减1
if(ge==0) ge=9;
else ge=ge-1;
P2=0xf0;
while((P2&0xf0)!=0xf0);//等待键释放(松手检测)
基于51单片机矩阵键盘程序
j=0;
for(k=0;k{
P3=table[k];//P3接有一排指示灯
delay (1000);//延时1S
}
}
}
}
主程序2:
main(){
int i,j,a[2][5]={10,15,25,15,75,15,45,65,85,95};
for(i=0;ifor(j=0;jprintf(“%d“,a[i][j]);
}
printf(“\n”);
}
主程序3:
由键盘输入一个3×4矩阵a,选出各列最小的元素组成一个一维数组b并输
出
由键盘输入一个3×4矩阵a,选出各列最小的元素组成一个一维数组b并输
出
#include“stdio.h”
#include“conio.h”
void main()
{
int i,j,a[3][4],b[4],min;
基于51单片机矩阵键盘程序
主程序1:
void main(){uch来自r i,j,ki=0;
j=0;
while(1)
{
i=key();//键盘循环扫描,其值赋给变量数组table
if(i!=0)//键盘子程序返回值非0,即有按键按下
{
table[j]=i;//将值存在变量数组中
j++;
}
if(j==6)
for(i=0;ifor(j=0;jscanf(“%d”,&a[i][j]);
for(i=0;ib[i]=a[0][i];
for(i=0;ifor(j=1;jif(a[i][j]for(i=0;iprintf(“%d”,b[i]);
getch();
}
51单片机矩阵键盘的编程
51单片机矩阵键盘的编程C51 单片机上的外设键盘键是使用的矩阵方式扩展的,但是硬件仿真时必须把蜂民器的开关打开触使行扫描的74HC53 的E 端接地为输出型,否则测死了也没反应,我还以为是我的程序有问题呢,后来才找到的。
其原理74HC138 译码器在输出端Y1 与WR(P3)都处于低电平通过或非门,转化成行扫描的74HC53 的片选端打开写入数据,在输出端的高4 位通过移位方式输出到外设键盘中。
然后给WR 一个高电平来给74HC53 一个低电平使得输入无效进行锁存操作。
然后通过RD(P3)与Y2 共同输出低电平通过或非门加上个非门把低电平送到列扫描的74HC53 的片选端E 上,在读取数据前必须先将要获取的高4 位进行置1,然后读取高4 位数据,通过RD 送出高电平进行锁住输出,防止74HC53 同时输入输出导致芯片烧毁。
然后根据获得的unsigned char 进行移位比对操作来获得是哪一列,然后在通过运算得到第几个按键被按下。
这是最简单的矩阵方式扩展键盘的代码流程,上述是我理解的流程,测试已没问题。
#includereg52.h#includeabsacc.hvoid my_delay10nms(unsigned int n){unsigned i,j;while(n --){for(i = 128;i 0;i --)for(j = 10;j 0;j --);}}sbit LED_BIT = P1;vo i dmain(void){unsigned char Key_h;unsigned char Key_Val;unsigned char Key_r;unsigned char Last_key;unsigned char Key_Temp;while(1){Key_Val=0;for(Key_h=4;Key_h8;Key_h++){P2=0x88;P0=(1Key_h);P3=~(16);P3|=(16);P2=0x90;P3=~(17); //读P0|=0xf0;Key_Temp=P00xf0; // P3|=(17); // 防止芯片烧坏if(Key_Temp) {for(Key_r=4;Key_r8;Key_r++){if(Key_Temp(1Key_r)){Key_Val=(Key_h-。
51单片机教程:按键输入、矩阵按键(按键巧用)proteus仿真+keil
51单⽚机教程:按键输⼊、矩阵按键(按键巧⽤)proteus仿真+keil⽂章⽬录IO⼝原理(P1⼝最简单,所以这⾥只介绍P1,其他IO⼝原理类似)P1⼝原理可以看到的是P1⼝的⼯作原理⽐较简单,⾸先⽤P1⼝做输⼊输出较为好理解。
1、内部总线:就是内部P1.X位寄存器的值,⽐如说内部总线P1.0上电压为0V,那么对应P1.0=0;内部总线P1.0上电压为5V,那么对应P1.0=1;2、P1.X引脚:对应单⽚机引脚接⼝3、读锁存器:读锁存器为1,允许读锁存器。
为0,不允许读锁存器。
4、读引脚:为0不允许读引脚,为1允许读引脚5、写锁存器:提供⼀个上升沿锁存数据(写数据到单⽚机IO⼝上时⾃动提供⼀个脉冲)⼏个核⼼问题:1、读锁存器与读引脚区别是什么?读锁存器:读锁存器Q的电平读引脚:读P1.X引脚的电平2、读锁存器与读引脚能不能同时读?不能,两个输⼊缓冲器只能同时打开⼀个,所以只能同时读取⼀个电平。
3、什么时候读锁存器,什么时候读引脚?凡属于读-修改-写⽅式的指令,从锁存器读⼊信号,其它指令则从端⼝引脚线上读⼊信号。
也就是说遇到读指令时,相应的输⼊缓冲器才会打开,⼀般是出于关闭状态4、如果P1.0⼝⼀开始置⼀,然后⽤按键拉低,松开按键后P1.0⼝会是低电平吗?不会,锁存器锁1,没有写⼊0之前⼀直输出1,按下按键只不过P1.0引脚变低了,松开后依然是⾼电平(有了以上知识,我们就可以轻松解决很多问题了)按键输⼊按键由于是机械结构,按下的时候难免产⽣抖动,⼀般抖动会在按下的时候与松开的时候产⽣,抖动时间⼤概是10ms⼆、打开proteus仿真,绘制电路功能:利⽤⼀个按键对⼀个发光⼆极管进⾏控制。
这个可以说是最简单的按键输⼊实验了!由于是51单⽚机,内部有上拉电阻,我们就不要浪费材料在按键上接上拉了三、打开keil,编写如下代码sbit key=P1^0;//定义key为P1.0sbit led=P2^0;//定义LED为P2.0void delay10(void)//延时10ms{int n=1000;while(n--);}void main(void){while(1){if(key==0)//读P1.0引脚,如果引脚为低电平,则进⼊if{delay10();//延时10ms消抖if(key==0)//再次判断按键是否按下,防⽌⼲扰,增强稳定{led =!led;//led状态改变while(key==0);//等待按键松开,防⽌往下执⾏}}}}博主有个疑问也很不解,当"key"换成"P2^0"后程序就不能正常运⾏了,知道的⼩伙伴能不能给我解解惑。
51单片机:独立按键与矩阵按键控制数码管
51单⽚机:独⽴按键与矩阵按键控制数码管⼀,独⽴按键注意⼀下⼏点>按下的时候,电压被拉低,所以IO⼝要传低电平( 0x0 )>按下的时候要消除抖动 ( 延时10ms ),在判断,是否还是低电平,再做业务处理下⾯这段程序,就是通过⼀个独⽴按键连接到p1⼝,控制静态数码管的⼀段进⾏亮和灭的切换。
#include <reg52.h>sbit key_control = P1^0;sbit led = P0^0;typedef unsigned char u8;typedef unsigned int u16;void delay( u16 i ){while( i-- );}void key_press(){if( key_control == 0x0 ) {delay( 1110 );if( key_control == 0x0 ){led = ~led;}while( !key_control );}}void main (){/*while( 1 ){if( key_control == 0x0 ) {delay( 1110 ); //⼤概10msif ( key_control == 0x0 ) {led = 1;}}else if( key_control == 0x1 ) {delay( 1110 );if ( key_control == 0x1 ) {led = 0;}}}*/led = 0;while( 1 ) {key_press();}}⼆,当按键⽐较多的时候,⽤矩阵按钮,因为如果不⽤矩阵按钮,⼀个独⽴按键需要⼀个IO⼝,浪费资源。
如: 16个独⽴按键需要16个io⼝,⽽16个矩阵按键(4x4,⼀共8个管脚)需要8个IO⼝下⾯的程序,通过16个矩阵按钮,控制静态数码管,显⽰0~F#include <reg52.h>#define GPIO_DIG P0 //段选数码管#define GPIO_KEY P1 //矩阵按键typedef unsigned char u8;typedef unsigned int u16;void delay( u16 i ){while( i-- );}u8 key_value;//静态数码管段码u8 character [16] = { 0xC0, 0xF9 , 0xA4 , 0xB0 , 0x99 , 0x92,0x82 , 0xF8 , 0x80 , 0x90 , 0x88 , 0x83,0xC6 , 0xA1 , 0x86 , 0x8E};void key_down(){u8 count = 0;//⾏列扫描判断哪个键被按下GPIO_KEY = 0x0F; //⾼四位全部输出低电平,低四位输出⾼电平-->判断被按下的按钮所在的列if( GPIO_KEY != 0x0F ) { //有按键按下delay( 1110 ); //消除抖动if( GPIO_KEY != 0x0F ){switch( GPIO_KEY ){case0x07:key_value = 0; //矩阵第1列的按钮被按下break;case0x0B:key_value = 1; //矩阵第2列的按钮被按下break;case0x0D:key_value = 2; //矩阵第3列的按钮被按下break;case0x0E:key_value = 3; //矩阵第4列的按钮被按下break;}GPIO_KEY = 0xF0; //⾼四位输出⾼电平,低四位输出低电平-->判断被按下的按钮所在的⾏switch( GPIO_KEY ){case0x70:key_value = key_value; //矩阵第1⾏的按钮被按下break;case0xB0:key_value = key_value + 4; //矩阵第2⾏的按钮被按下break;case0xD0:key_value = key_value + 8; //矩阵第3⾏的按钮被按下break;case0xE0:key_value = key_value + 12; //矩阵第4⾏的按钮被按下break;}GPIO_DIG = character[key_value];//如果⼀直按下按键,等待500ms,强制退出while( ( count < 50 ) && ( GPIO_KEY != 0xF0 ) ) {count++;}}}}void main (){while( 1 ) {key_down();}}。
51单片机矩阵键盘C语言编程
/****************************************************************************** 函数名称:main() 函数功能:主函数,键值处理
******************************************************************************/
__ ____
KEY=HSM + LJC|0x0f 例如,“0”键处在第 1 行第 1 列,其 HSM=0xfe,LJC=0xe0,代入上式,可得“0” 键的键值为
__ ____ __ ____ KEY=HSM + LJC|0x0f = 0xfe + 0xe0|0x0f =0x01 + 0x10= 0x11 根据上述计算方法,可计算所有按键地键值,见下表
4
5
6
7
P11
8
9
A
Байду номын сангаас
B
P12
C
D
E
F
P13
原理图12
根据矩阵非编码键盘逐行扫描法处理流程,键盘扫描程序应包括以下内容。 (1)查询是否有键被按下。 首先单片机向行扫描口输出扫描码 F0H,然后从列检测口读取列检测信号,只要一列信 号不为“1”,即 P1 口的值不等于 F0H,则表示有键被按下;否则表示无键被按下。 键值译码公式如下: (2)查询闭合键所在的行列位置。 若有键按下,单片机将等到的列检测信号取反,列检测口中为 1 的位便是闭合键所在 的列。 列号确定后,还需要进行逐行扫描以确定行号。单片机首先向行扫描口输出第 1 行的 扫描码 FEH,按着读列检测口,若列检测信号全为“1”,则表示闭合键不在第 1 行。接着 向行扫描口输出第 2 行的扫描码 FDH,再读列检测品,……。以此类推,直到找到闭合键 所在的行,并将该行的扫描码取反保存。如果扫描完所有的行后仍没有找到闭合键,则结束 行扫描,判断本次按键是误动作。 (3)对得到的行号和列号进行译码,确定键值。 根据原理图 12 所示,1、2、3、4 行的扫描码分别为 0xfe、0xfd、0xeb、0xf7;1、2、3、 4 列的列检测数据分别为 0xe0、0xd0、0xb0、0x70。设行扫描码码子 HSM,列检测数据为 LJC,则键值为 KEY,则有
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
temp=temp&0x0F ;
temp=~(temp|0xF0) ;
if(temp==1)
key=0 ;
else if(temp==2)
key=1 ;
}
*/
/*******************************************************************/
/*
/*写指令数据到LCD
//矩阵键盘一号,看不懂
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit BEEP = P2^2 ; //蜂鸣器驱动线
/* LCD初始化设定
/*
/*************************************************************/
/*
/*************************************************************/
void lcd_pos(uchar pos)
void lcd_init()
{
delay(15) ;
lcd_wcmd(0x38) ; //16*2显示,5*7点阵,8位数据
delay(5) ;
lcd_wcmd(0x38) ;
delay(5) ;
/* 延时子程序
/*
/*************************************************************/
else if(temp==2)
key=key+4 ;
else if(temp==4)
key=key+8 ;
else if(temp==8)
key=key+12 ;
delay(1) ;
temp=P1 ; //读P1口
temp=temp&0xF0 ;
temp=~((temp>>4)|0xF0) ;
if(temp==1)
key=key+0 ;
else if(temp==4)
key=2 ;
else if(temp==8)
key=3 ;
else
key=16 ;
P1=0xF0 ; //高四位输入
delay(5) ;
}
/*************************************************************/
/*
/* 设定显示位置
/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。
/*
/*******************************************************************/
/*************************************************************/
void keyscan(void)
{
P1=0x0F ; //低四位输入
delay(1) ;
/*
/*检查LCD忙状态
/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据
/* 键扫描子程序
/*
lcd_wcmd(0x38) ;
delay(5) ;
lcd_wcmd(0x0c) ; //显示开,关光标
delay(5) ;
lcd_wcmd(0x06) ; //移动光标
delay(5) ;
lcd_wcmd(0x01) ; //清除LCD的显示内容
{
//while(lcd_busy()) ;
LCD_RS = 1 ;
//LCD_RW = 0 ;
LCD_EN = 0 ;
P0 = dat ;
delayNOP() ;
LCD_EN = 1 ;
#define delayNOP() ; {_nop_() ;_nop_() ;_nop_() ;_nop_() ;} ;
/*************************************************************/
/*
void lcd_wcmd(uchar cmd)
{
//while(lcd_busy()) ;
LCD_RS = 0 ;
// LCD_RW = 0 ;
LCD_EN = 0 ;
_nop_() ;
_nop_() ;
/*
/*******************************************************************/
void lcd_wdat(uchar dat)
P0 = cmd ;
delayNOP() ;
LCD_EN = 1 ;
delayNOP() ;
LCD_EN = 0 ;
}
/*******************************************************************/
bit result ;
LCD_RS = 0 ;
LCD_RW = 1 ;
LCD_EN = 1 ;
delayNOP() ;
result = (bit)(P0&0x80) ;
LCD_EN = 0 ;
return(result) ;
/*
/*************************************************************/
/*
bit lபைடு நூலகம்d_busy()
{
void delay(uchar x)
{ uchar j ;
while((x--)!=0)
{ for(j=0 ;j< 125 ;j++)
{ ;}
}
}
/*************************************************************/
sbit LCD_RS = P3^5 ;
//sbit LCD_RW = P2^1 ;
sbit LCD_EN = P3^4 ;
uchar code cdis1[ ] = {" KEY NUMBER "} ;
uchar code cdis2[ ] = {" KEY-CODE: H "} ;
{
lcd_wcmd(pos | 0x80) ; //数据指针=80+地址变量
}
/*************************************************************/
/*
uchar dis_buf ; //显示缓存
uchar temp ;
uchar key ; //键顺序吗
void beep() ; //蜂鸣器
void delay0(uchar x) ; //x*0.14MS
delayNOP() ;
LCD_EN = 0 ;
}
/*************************************************************/
/*
/*
/*写显示数据到LCD
/*RS=H,RW=L,E=高脉冲,D0-D7=数据。