用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的

用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的,第1张

KEYBUF EQU 40H ;键号存放单元

ORG 0000H

LJMP MAIN

ORG 0030H

MAIN: MOV KEYBUF,#0 ;初始键号设位0,也可以为任意值

MOV R0,#30H ;显示首地址

MOV R2,#0CH ;计算数据存放单元个数

CLR A

QING: MOV @R0,A ;将数据存放单元清零

INC R0

DJNZ R2,QING

MOV P0,#8FH ;关闭显示

MOV R1,#30H ;将显示首地址存放R1里

;===============================================

;五位无符号显示子程序

DIS1: MOV R0,#30H ;把显示数据第一位放在R0里

MOV R2,#04H ;把显示的位码放在R2里

MOV R3,#05H ;把显示的长度放在R3里

DIS2: MOV A,@R0

ANL A,#0FH ;屏蔽显示数据的高四位

MOV B,A

MOV A,R2

ANL A,#0FH ;屏蔽位码的高四位

SWAP A

ORL A,B

MOV P0,A ;送总显示数据到P0显示

LCALL DELY4ms ;调用延时4ms

INC R0 ;取下一个显示数据

DEC R2

DJNZ R3,DIS2 ;四位显示晚后重新开始显示

;===================================================

;键盘扫描子程序

WAIT: MOV P1,#0FFH ;P1口送高电平

CLR P10 ;第一行清零

MOV A,P1 ;读P1口

ANL A,#0F0H ;低位屏蔽

XRL A,#0F0H ;判断低位是否有低电平 ,即判断是否有按键按下

JZ NOKEY1 ;地位有低电平继续扫描,否者跳到第而行去扫描

LCALL DELY10ms ;延时10ms去抖在进行判断是否有按键按下

MOV A,P1 ;继续读P1口

ANL A,#0F0H ;判断低位是否有低电平

CJNE A,#0E0H,NK1 ;如果扫描数据不为0E0H就转到NK1

MOV KEYBUF,#0 ;否者判断为0号键

AJMP DK ;转DK1查表程序

NK1: CJNE A,#0D0H,NK2 ;如果扫描数据不为0D0H就转到NK2

MOV KEYBUF,#1 ;否者判断为1号键

AJMP DK ;转DK2查表程序

NK2: CJNE A,#0B0H,NK3 ;如果扫描数据不为0B0H就转到NK3

MOV KEYBUF,#2 ;否者判断为2号键

AJMP DK ;转DK3查表程序

NK3: CJNE A,#70H,NK4 ;如果扫描数据不为70H就转到NK4

LJMP SAN_CHU

NK4: NOP

NOKEY1: MOV P1,#0FFH ;和上面相同

CLR P11

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY2

LCALL DELY10MS

MOV A,p1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY2

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK5

MOV KEYBUF,#3

AJMP DK

NK5: CJNE A,#0D0H,NK6

MOV KEYBUF,#4

AJMP DK

NK6: CJNE A,#0B0H,NK7

MOV KEYBUF,#5

AJMP DK

NK7: CJNE A,#70H,NK8

MOV KEYBUF,#10 ;否者判断为3号键

AJMP DK ;转DK4查表程序

NK8: NOP

NOKEY2: MOV P1,#0FFH

CLR P12

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY3

LCALL DELY10MS

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY3

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK9

MOV KEYBUF,#6

AJMP DK

NK9: CJNE A,#0D0H,NK10

MOV KEYBUF,#7

AJMP DK

NK10: CJNE A,#0B0H,NK11

MOV KEYBUF,#8

AJMP DK

NK11: CJNE A,#70H,NK12

LJMP DENG_HAO

NK12: NOP

NOKEY3: MOV P1,#0FFH

CLR P13

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY4

LCALL DELY10MS

MOV A,P1

ANL A,#0F0H

XRL A,#0F0H

JZ NOKEY4

MOV A,P1

ANL A,#0F0H

CJNE A,#0E0H,NK13

LJMP CHU

NK13: CJNE A,#0D0H,NK14

LJMP CHENG

NK14: CJNE A,#0B0H,NK15

LJMP JIAN

NK15: CJNE A,#70H,NK16

LJMP JIA

NK16: NOP

;=======================================================

;查表求键值程序

DK: MOV B,#00H

MOV A,KEYBUF ;查表程序 查对应的键号数据

MOV DPTR,#TABLE ;把表头地址放入DPTR

MOVC A,@A+DPTR ;A里面存放的为键号,利用A和表头地址找到对应的键号数据

MOV B,A ;把查到的数据送往显示单元

INC R1 ;取下一个显示单元

MOV A,R1

CJNE A,#36H,DKA1 ;判断显示单元是否已满

MOV R1,#35H ;35H,36H单元用于更好的控制五位显示

AJMP DKA

DKA1: MOV 34H,33H ;按键代码按左移显示,先按先显示

MOV 33H,32H

MOV 32H,31H

MOV 31H,30H

MOV 30H,B

DKA: MOV A,P1 ;读P1口

ANL A,#0F0H ;屏蔽高四位

XRL A,#0F0H ;地位是有低电平

JNZ DKA ;如果有低电平继续读P1口,否者向下执行,查找第二行

NOKEY4: LJMP DIS1

;===================================

;功能按键功能设定

DENG_HAO:MOV DPTR,#JI_SUAN ;等号键功能通过加、减、乘、除设定的偏移量来调用子程序

MOV A,3CH ;3CH存放的为功能程序入口地址偏移量

JMP @A+DPTR ;转移到按键功能程序

JI_SUAN: AJMP JIA1 ;加计算子程序

AJMP JIAN1 ;减计算子程序

AJMP CHENG1 ;乘计算子程序

AJMP CHU ;除计算子程序

;=======删除键功能

SAN_CHU: ACALL QING_DIS

AJMP DKA

;=======加键功能

JIA: MOV 3CH,#00H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

;=======减键功能

JIAN: MOV 3CH,#02H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

;=======乘键功能

CHENG: MOV 3CH,#04H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

;=======除键功能

CHU: MOV 3DH,#06H

ACALL CUN_SHU

ACALL QING_DIS

AJMP DKA

;=================================

;存被加(减、乘、除)数,存放在37H~3BH里

CUN_SHU: MOV 37H,30H ;36H存放的为最低位

MOV 38H,31H

MOV 39H,32H

MOV 3AH,33H

MOV 3BH,34H ;3AH存放的为最高位

RET

;================================

;清除显示单元

QING_DIS: MOV R1,#30H

QING1: MOV @R1,#00H

INC R1

MOV A,R1

CJNE A,#36H,QING1

MOV R1,#30H

LOP1: RET

;================================

;十进制加法子程序

JIA1:

MOV A,37H ;个位被加数

ADD A,30H ;个位被加数+加数

MOV B,#10 ;十六进制除10转换成BCD码

DIV AB

MOV 30H,B ;余数即个位存放在30H

MOV 37H,A ;商存放在37H

MOV A,38H ;十位被加数

ADD A,31H ;十位被加数+加数

ADD A,37H ;加上个位之和的进位

MOV 37H,#00H ;清除37H

MOV B,#10 ;十六进制除10转换成BCD码

DIV AB

MOV 31H,B ;余数即十位存放在31H

MOV 38H,A ;商存放在38H

MOV A,39H ;百位计算同十位

ADD A,32H

ADD A,38H

MOV 38H,#00H

MOV B,#10

DIV AB

MOV 32H,B

MOV 39H,A

MOV A,3AH ;千位计算同十位

ADD A,33H

ADD A,39H

MOV 39H,#00H

MOV B,#10

DIV AB

MOV 33H,B

MOV 3AH,A

MOV A,3BH ;万位计算同十位

ADD A,34H

ADD A,3AH

MOV 3AH,#00H

MOV B,#10

DIV AB

MOV 34H,B

MOV 3BH,#00H

AJMP DKA

;=====================

JIAN1: AJMP DKA

CHENG1: AJMP DKA

CHU1: AJMP DKA

;=============================================

;延时程序和查表表格

DELY4ms: MOV R6,#8 ;延时4毫秒

D1: MOV R7,#248

DJNZ R7,$

DJNZ R6,D1

RET

DELY10ms:MOV R6,#20 ;延时10毫秒

D2: MOV R7,#248

DJNZ R7,$

DJNZ R6,D2

RET

TABLE: DB 07H, 04H, 01H ; / 本表格是以键盘为参考 7 8 9 /

DB 08H, 05H, 02H ; 4 5 6

DB 09H, 06H, 03H ; - 1 2 3 -

DB 00H, 00H ;= + 清除 0 = +

END

这个很好处理呀,比如以下举例,独立+矩阵,实现独立按键相当于类似SHIFT作用的效果。

#include<reg51h>

#define uchar unsigned char

uchar tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0到f

uchar keyval,num;

sbit skey=P1^0; //独立键P10

void delay(uchar a)

{

uchar i,j;

for(i=0;i<a;i++)

for(j=0;j<125;j++);

}

uchar kbscan(void) //矩阵键扫描程序

{

unsigned char sccode,recode;

P3=0x0f; //发0扫描,列线输入

if ((P3 & 0x0f) != 0x0f) //有键按下

{

delay(20); //延时去抖动

if ((P3&0x0f)!= 0x0f)

{

sccode = 0xef; //逐行扫描初值

while((sccode&0x01)!=0)

{

P3=sccode;

if((P3&0x0f)!=0x0f)

{

recode=(P3&0x0f)|0xf0;

while((P3&0x0f)!=0x0f);//等待键抬起

return((~sccode)+(~recode));

}

else

sccode=(sccode<<1)|0x01;

}

}

}

return 0; //无键按下,返回0

}

void getkey(void)

{

unsigned char key;

key=kbscan();

if(key==0)

{

return;

}

switch(key)

{

case 0x11:keyval=7;break;

case 0x12:keyval=4;break;

case 0x14:keyval=1;break;

case 0x18:keyval=10;break;

case 0x21:keyval=8;break;

case 0x22:keyval=5;break;

case 0x24:keyval=2;break;

case 0x28:keyval=0;break;

case 0x41:keyval=9;break;

case 0x42:keyval=6;break;

case 0x44:keyval=3;break;

case 0x48:keyval=11;break;

case 0x81:keyval=12;break;

case 0x82:keyval=13;break;

case 0x84:keyval=14;break;

case 0x88:keyval=15;break;

default:keyval=0xff;break;

}

//以下处理独立按键

if(skey==0)

{

if(keyval!=0xff)keyval+=16; //如果独立键按下,键值加16

while(skey==0); //等待独立键释放

}

}

void t0isr() interrupt 1

{

TH0=(65536-10000)/256;

TL0=(65536-10000)%256;

switch(num)

{

case 0:P2=0x01;break;

case 1:P2=0x02;break;

case 2:P2=0x04;break;

case 3:P2=0x08;break;

default:break;

}

if(keyval<16) P0=~tab[keyval]; //独立键未按正常显示

else P0=~(tab[keyval]|0x80); //独立键按下显示+DP

num++;

num&=0x03;

}

main()

{

TMOD=0x01;

TH0=(65536-10000)/256;

TL0=(65536-10000)%256;

TR0=1;

ET0=1;

EA=1;

while(1)

{

getkey();

}

}

/

矩阵按键实验

实现现象:下载程序后数码管显示0,按下矩阵按键上的按键显示对应的数字

S1-S4:0-3

S5-S8:4-7

S9-S12:8-B

S13-S16:C-F。

注意事项:如果不想让点阵模块显示,可以将74HC595模块上的JP595短接片拔掉。

/

#include "reg52h" //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16; //对数据类型进行声明定义

typedef unsigned char u8;

#define GPIO_DIG P0

#define GPIO_KEY P1

sbit LSA=P2^2;

sbit LSB=P2^3;

sbit LSC=P2^4;

u8 KeyValue; //用来存放读取到的键值

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,

0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

/

函 数 名 : delay

函数功能 : 延时函数,i=1时,大约延时10us

/

void delay(u16 i)

{

while(i--);

}

/

函 数 名 : KeyDown

函数功能 : 检测有按键按下并读取键值

输 入 : 无

输 出 : 无

/

void KeyDown(void)

{

char a=0;

GPIO_KEY=0x0f;

if(GPIO_KEY!=0x0f)//读取按键是否按下

{

delay(1000);//延时10ms进行消抖

if(GPIO_KEY!=0x0f)//再次检测键盘是否按下

{

//测试列

GPIO_KEY=0X0F;

switch(GPIO_KEY)

{

case(0X07): KeyValue=0;break;

case(0X0b): KeyValue=1;break;

case(0X0d): KeyValue=2;break;

case(0X0e): KeyValue=3;break;

}

//测试行

GPIO_KEY=0XF0;

switch(GPIO_KEY)

{

case(0X70): KeyValue=KeyValue;break;

case(0Xb0): KeyValue=KeyValue+4;break;

case(0Xd0): KeyValue=KeyValue+8;break;

case(0Xe0): KeyValue=KeyValue+12;break;

}

while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测

{

delay(1000);

a++;

}

}

}

}

/

函 数 名 : main

函数功能 : 主函数

输 入 : 无

输 出 : 无

/

void main()

{

LSA=0; //给一个数码管提供位选

LSB=0;

LSC=0;

while(1)

{

KeyDown(); //按键判断函数

GPIO_DIG=smgduan[KeyValue]; //

}

}

有问题,当按下多个按键时,消抖都没用了。有计数法,但是需要消耗的内存。可以识别具体的键位,键的按下d起状态,消抖。每个按键状态独立识别,无需等待延时。typedefenum{Key_No,Key_Down,Key_Up,}KeyStateEnum;vkey[4]={0};//4组按键ucharkeyDownNum[16]={0};//按下计数ucharkeyDownUp[16]={0};//d起计数//判断键状态ucharstateKey(ucharkeySta,uchardownNum,ucharupNum,uchardel){ucharsta=Key_No;if(keySta){upNum[0]=0;if(downNum[0]==del){sta=Key_Down;}if(downNum[0]>4);}}voidmain(){while(1){Readkey();//ScanKey();}}

codevalue = m + j; //行号加列号

while (checkkey() != 0);//待松手

return (codevalue); //返回键值

----------

codevalue = m + j; //为行号加列号,

共有两层循环,各循环四次,即有:

j = 0, 1, 2, 3;

m = 0, 4, 8, 12;

于是:

m + j = 0 ~ 15;

没错。

只是程序编写的滥一些,可以化简好多的,

C51 P1端口 4X4键盘说明

这是一个用C51单片机P1端口制作的4X4键盘,p1端口低4位是键盘列扫描线,高4位是键盘行扫描线,

列扫描线是输出,行扫描线是输入。

下面就程序作一个说明

()表示注意点

1、首先判断整个键盘有无按下键,只要行扫描线输入不为全1,(1111)即有键按下;

P1 = 0xf0;if((P1&0xf0)!=0xf0) 如果无按键按下,全1,则返回return -1;

如果有键按下则延时,再次判断有无按键按下,Delay();if((P1&0xf0)!=0xf0)如果无按键按下则返回return -1。

有键按下则继续,这个过程就是判键消抖,避免多次读键值,或者因为按键抖动到读键值的时候无键按下,发生错误,列扫描线是输出全0,P1 = 0xf0。

2、进入读键值了,与上面不同,每一次判断,列扫描线只有一根输出为0,即P1=0xfe,0xfd,0xfb,0xf7;

首先列扫描线P10,sCode = 0xfe;如果行扫描线全1,则本列无键按下,扫描下一列

sCode = _crol_(sCode,1); sCode左移一位,即0xfd,如此扫描4次,行扫描线都全0,则无键按下,

返回return -1;

如果行扫描线不全0,就是有键按下,现在可以读键值了

kCode = ~P1; //P1=EE,ED

for(i=0;i<16;i++)

{

if(kCode == KeyCodeTable[i])

return i;

}

1首先kCode = ~P1;p1值取反行扫描线可能的是1,2,4,8;同样列扫描线对应值1,2,4,8

合起p1有16个值,就是KeyCodeTable[i]表的x11,0x12,0x14,0x18,0x21,0x22,0x24,0x28,

0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88

如果 if(kCode == KeyCodeTable[i]) 成立,对应的 i 值就是键号。

2返回i值就是键号,return i;。

uchar Keys_Scan()

{

uchar sCode,kCode,i,k;

P1 = 0xf0;

if((P1&0xf0)!=0xf0) //扫描列

{

Delay();

if((P1&0xf0)!=0xf0)//消抖

{

sCode = 0xfe;

for(k=0;k<4;k++)

{

P1 = sCode;//查找低位

if((P1&0xf0)!=0xf0)//只有等于才执行else P1和0xf0作与为0xf0 与 同真为真,一假为假

{

kCode = ~P1; //P1=EE,ED

for(i=0;i<16;i++)

{

if(kCode == KeyCodeTable[i])

return i;

}

}

else

sCode = _crol_(sCode,1);

}

}

}

return -1;

}

KeyPort=0x0f; //行线输出全为0

cord_h=KeyPort&0x0f; //读入列线值

这两句代码最后造成的结果就是使得cord_h=0x0f。

这样的话,完全没有任何的意义呀,

----

不一定是 0f。

有按键时,也可能是 07,也可能是 0d,也可能是 0e,也可能是 0b。

以上就是关于用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的全部的内容,包括:用89C51单片机设计4*4矩阵式键盘计算器程序 要汇编的、单片机中独立键盘和矩阵键盘如何一起使用 请用C语言写个程序说明,谢谢。、求助程序:51单片机矩阵键盘是否按下检测程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9751569.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存