C51单片机4*4按键计算器 ,数码管上只显示结果的 ,P2口是某一位,P0口是数码管显示。P3口是4*4键盘。

作者&投稿:井斌 (若有异议请与网页底部的电邮联系)
单片机p1口按4*4矩阵键盘、p0口按共阳LED数码管,按下相应的键,数码管显示相应的数值。(键值0~F)~

要看是共阳还是共阴的数码管。
#include //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
#define uchar unsigned char
#define uint unsigned int
unsigned char const dofly[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71};//0-F
uchar keyscan(void);//键盘扫描
void delay(uint i); //演示程序
void main()
{
uchar key;
while(1)
{
key=keyscan(); //调用键盘扫描,
switch(key)
{
case 0x7e:P0=dofly[0];break;//0 按下相应的键显示相对应的码值
case 0x7d:P0=dofly[1];break;//1
case 0x7b:P0=dofly[2];break;//2
case 0x77:P0=dofly[3];break;//3
case 0xbe:P0=dofly[4];break;//4
case 0xbd:P0=dofly[5];break;//5
case 0xbb:P0=dofly[6];break;//6
case 0xb7:P0=dofly[7];break;//7
case 0xde:P0=dofly[8];break;//8
case 0xdd:P0=dofly[9];break;//9
case 0xdb:P0=dofly[10];break;//a
case 0xd7:P0=dofly[11];break;//b
case 0xee:P0=dofly[12];break;//c
case 0xed:P0=dofly[13];break;//d
case 0xeb:P0=dofly[14];break;//e
case 0xe7:P0=dofly[15];break;//f
}
}
}
uchar keyscan(void) //键盘扫描函数,使用行列反转扫描法
{
uchar cord_h,cord_l;//行列值中间变量
P1=0x0f; //行线输出全为0
cord_h=P1&0x0f; //读入列线值
if(cord_h!=0x0f) //先检测有无按键按下
{
delay(1000); //去抖
if((P1&0x0f)!=0x0f)
{
cord_h=P1&0x0f; //读入列线值
P1=cord_h|0xf0; //输出当前列线值
cord_l=P1&0xf0; //读入行线值
return(cord_h+cord_l);//键盘最后组合码值
}
}return(0xff); //返回该值
}
void delay(uint i) //延时函数
{
while(i--);
}

你用的是静态显示,按下某一銉后,只有列数信号被锁存,因你的行和列数码管共用P0口和同一个锁存器,所以先显示的行数被后面的列数代替,且中间还没有任何延时,所以行数只是一闪而过
即使按住按键不丢,虽行数信号可以被反复显示,但由于按銉识别时有10MS的延时 ,这期间行数信号是不显示的,所以行数码管看起来还只是微微闪亮
假设按键按住不放其工作过程是这样的
显示行数(可能只有1-2us)--显示列数--延时10ms(列数仍显示)--显示行数....
解决办法,在P0=table_hang[hang]; dula=0;之后加延时,
并且在WHILE (1)大循环未尾加display(hang,lie);
但也带来另外一个问题,即使不按任何按键,也会显示0行0列
可采用给行列赋初值的方法解决(给行和列赋一个不能显示的初值,例如4 4,然后改table_hang[]={0x06,0x5b,0x4f,0x66,0xff}及table_lie[]={0x06,0x5b,0x4f,0x66,0xff};
另一种方法,将display(hang,lie);改成
for(i=0;i<200;i++)
{
display(hang,lie);
}
在显示程序内部最好还有毫秒级延时,
将两处P0=0xff全换成延时

按下数字键,移位显示;

按下运算键,保存当前数据,显示全零;

按下数字键,移位显示;

按下等号键,显示结果。
------------------
做计算器,用数码管显示,档次偏低,不值得费劲。应该用 LCD。
用数码管显示,练习编写一个时钟、计数器、等等,就可以了。

我以前做的,你可以参考一下:
KEYVAL EQU 30H
KEYTM EQU 31H
KEYSCAN EQU 32H
DAT EQU 33H
SCANLED EQU 37H
S_DAT EQU 38H
D_DAT EQU 39H
R_DATL EQU 3AH
R_DATH EQU 3BH
CALFLAG EQU 3CH
FLAG BIT 00H
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP T0ISR
ORG 0030H
MAIN:
MOV SP,#5FH
MOV TMOD,#01H
MOV TH0,#0D8H
MOV TL0,#0F0H
MOV KEYVAL,#0
MOV P2,#00H
MOV SCANLED,#0
MOV 33H,#0H
MOV 34H,#0H
MOV 35H,#0H
MOV 36H,#0H
MOV S_DAT,#0
MOV D_DAT,#0
CLR FLAG
SETB EA
SETB ET0
SETB TR0
LOOP:
LCALL KEYSEL
MOV A,KEYVAL
CJNE A,#0FFH,LOOP1
SJMP LOOP
LOOP1:
CJNE A,#11,LOOP2 ;“=”
MOV A,33H
MOV B,#10
MUL AB
ADD A,34H
MOV D_DAT,A
LCALL DEALDAT
LCALL HB2
MOV A,R5
ANL A,#0FH
MOV 34H,A
MOV A,R5
SWAP A
ANL A,#0FH
MOV 33H,A
MOV A,R4
ANL A,#0FH
MOV 36H,A
MOV A,R4
SWAP A
ANL A,#0FH
MOV 35H,A
SJMP LOOP
LOOP2:
CJNE A,#15,LOOP3 ;“+”
LCALL GETDAT
SJMP LOOP
LOOP3:
CJNE A,#14,LOOP4 ;“-”
MOV CALFLAG,#1
LCALL GETDAT
SJMP LOOP
LOOP4:
CJNE A,#13,LOOP5 ;“*”
MOV CALFLAG,#2
LCALL GETDAT
SJMP LOOP
LOOP5:
CJNE A,#12,LOOP6 ;"/"
MOV CALFLAG,#3
LCALL GETDAT
SJMP LOOP
LOOP6:
CJNE A,#10,LOOP7 ;数字键
LOOP7:
JC LOOP8
LJMP LOOP
LOOP8:
MOV 33H,34H
MOV 34H,KEYVAL
LJMP LOOP
;------------------
HB2:
MOV R6,R_DATH
MOV R7,R_DATL
CLR A ;BCD码初始化
MOV R3,A
MOV R4,A
MOV R5,A
MOV R2,#10H ;转换双字节十六进制整数
HB3:
MOV A,R7 ;从高端移出待转换数的一位到 CY 中
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R5 ;BCD码带进位自身相加,相当于乘2
ADDC A,R5
DA A ;十进制调整
MOV R5,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
MOV R3,A ;双字节十六进制数的万位数不超过6,不用调整
DJNZ R2,HB3 ;处理完16bit
RET
;------------------
GETDAT:
MOV A,33H
MOV B,#10
MUL AB
ADD A,34H
MOV S_DAT,A
MOV 33H,#0
MOV 34H,#0
MOV 35H,#0
MOV 36H,#0
RET
;------------------
DEALDAT:
MOV A,CALFLAG
JNZ DEAL01
DEAL00: ;+
MOV A,S_DAT
ADD A,D_DAT
MOV R_DATL,A
CLR A
ADDC A,#0
MOV R_DATH,A
RET
DEAL01: ;=
DEC A
JNZ DEAL02
CLR C
MOV A,S_DAT
SUBB A,D_DAT
MOV R_DATL,A
SUBB A,#0
MOV R_DATH,A
RET
DEAL02: ;*
DEC A
JNZ DEAL03
MOV A,S_DAT
MOV B,D_DAT
MUL AB
MOV R_DATL,A
MOV R_DATH,B
RET
DEAL03: ;/
MOV A,S_DAT
MOV B,D_DAT
DIV AB
MOV R_DATL,A
MOV R_DATH,#0
RET
;------------------
KEYSEL:
MOV KEYVAL,#0
MOV KEYSCAN,#0EFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS1
MOV KEYVAL,A
SJMP KEYRTN
KEYS1:
MOV KEYSCAN,#0DFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS2
CLR C
ADD A,#4
MOV KEYVAL,A
SJMP KEYRTN
KEYS2:
MOV KEYSCAN,#0BFH
LCALL GETKEY
MOV A,KEYTM
JZ KEYS3
CLR C
ADD A,#8
MOV KEYVAL,A
SJMP KEYRTN
KEYS3:
MOV KEYSCAN,#7FH
LCALL GETKEY
MOV A,KEYTM
JZ KEYRTN
CLR C
ADD A,#12
MOV KEYVAL,A
KEYRTN:
LCALL CHGKEY
RET
;--------------------
GETKEY:
MOV KEYTM,#0
MOV A,KEYSCAN
MOV P3,A
NOP
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV R2,#10
LCALL DELAY
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JZ NOKEY
MOV A,P3
ANL A,#0FH
MOV R7,A
SF:
MOV A,P3
ANL A,#0FH
XRL A,#0FH
JNZ SF
MOV A,R7
CJNE A,#0EH,NK1
MOV KEYTM,#1
SJMP NOKEY
NK1:
CJNE A,#0DH,NK2
MOV KEYTM,#2
SJMP NOKEY
NK2:
CJNE A,#0BH,NK3
MOV KEYTM,#3
SJMP NOKEY
NK3:
CJNE A,#07H,NOKEY
MOV KEYTM,#4
NOKEY: RET
;--------------------
DELAY:
MOV R3,#50
DELAY1:
MOV R4,#100
DJNZ R4,$
DJNZ R3,DELAY1
DJNZ R2,DELAY
RET
;--------------------
T0ISR:
PUSH ACC
CLR TR0
MOV TH0,#0D8H
MOV TL0,#0F0H
SETB TR0
MOV DPTR,#LEDTAB
T000: ;数字显示
MOV R0,#DAT
MOV A,SCANLED
ADD A,R0
MOV R0,A
MOV A,SCANLED
JNZ T001
MOV P2,#01H
SJMP T0DIS
T001:
DEC A
JNZ T002
MOV P2,#02H
SJMP T0DIS
T002:
DEC A
JNZ T003
MOV P2,#04H
SJMP T0DIS
T003:
MOV P2,#08H
T0DIS:
MOV A,@R0
MOVC A,@A+DPTR
; CPL A
MOV P0,A
INC SCANLED
MOV A,SCANLED
ANL A,#03H
MOV SCANLED,A
POP ACC
RETI
;--------------------
CHGKEY:
MOV A,KEYVAL
JZ KV16
DEC A
JNZ KV01
MOV KEYVAL,#7
RET
KV01:
DEC A
JNZ KV02
MOV KEYVAL,#4
RET
KV02:
DEC A
JNZ KV03
MOV KEYVAL,#1
RET
KV03:
DEC A
JNZ KV04
MOV KEYVAL,#10
RET
KV04:
DEC A
JNZ KV05
MOV KEYVAL,#8
RET
KV05:
DEC A
JNZ KV06
MOV KEYVAL,#5
RET
KV06:
DEC A
JNZ KV07
MOV KEYVAL,#2
RET
KV07:
DEC A
JNZ KV08
MOV KEYVAL,#0
RET
KV08:
DEC A
JNZ KV09
MOV KEYVAL,#9
RET
KV09:
DEC A
JNZ KV10
MOV KEYVAL,#6
RET
KV10:
DEC A
JNZ KV11
MOV KEYVAL,#3
RET
KV11:
DEC A
JNZ KV12
MOV KEYVAL,#11 ;=
RET
KV12:
DEC A
JNZ KV13
MOV KEYVAL,#12 ;/
RET
KV13:
DEC A
JNZ KV14
MOV KEYVAL,#13 ;*
RET
KV14:
DEC A
JNZ KV15
MOV KEYVAL,#14 ;-
RET
KV15:
DEC A
JNZ KV16
MOV KEYVAL,#15 ;+
RET
KV16:
MOV KEYVAL,#0FFH
RET
;--------------------
LEDTAB:
DB 0C0H ;"0" 00H
DB 0F9H ;"1" 01H
DB 0A4H ;"2" 02H
DB 0B0H ;"3" 03H
DB 99H ;"4" 04H
DB 92H ;"5" 05H
DB 82H ;"6" 06H
DB 0F8H ;"7" 07H
DB 80H ;"8" 08H
DB 90H ;"9" 09H
DB 88H ;"A" 0AH
DB 83H ;"B" 0BH
DB 0C6H ;"C" 0CH
DB 0A1H ;"D" 0DH
DB 86H ;"E" 0EH
DB 8EH ;"F" 0FH
DB 0FFH ;" " 10H
;--------------------
END


51单片机4×4矩阵键盘,下载程序后LED全亮怎么回事
如果键盘灯亮时,按键无反应这种情况:是接口插错了,一盘键盘的PS2接口是紫色,鼠标是绿色的,检查你插对了吗;是断针,PS2接口有6根针,中间是定位点,其中2根是电源,其他4根是数据,你看一下是丌是断针了。

51单片机4*4按键不好使
自己焊的51单片机板 4*4的键盘就四个好使 剩下的都不好使怎么办?两字:调试!四个字:调试检查。你扫描不对,鉴定完毕。

51单片机矩阵4*4键盘程序,P0口接一个数码管,P2口接矩阵键盘
| 4 | 5 | 6 | - | | 7 | 8 | 9 | * | | 0 | . | = | \/ | ---*\/ unsigned char KeyPro(void){ switch(KeyScan()){ case 0x7e:return 1 ;break;\/\/0 按下相应的键显示相对应的码值 case 0x7d:return 2 ;break;\/\/1 case 0x7b:return 3 ;break;\/\/2 case 0...

基于单片机的电子密码锁设计
设计一个由51单片机控制的电子密码锁,输入接口使用4×4键盘,输出接口使用6位7段数码管。单片机将输入的密码与设定的密码比较,若密码正确,则密码锁打开(绿色发光二极管亮一... 设计一个由51单片机控制的电子密码锁,输入接口使用4×4键盘,输出接口使用6位7段数码管。单片机将输入的密码与设定的密码比较,若密码正确,...

单片机4x4按键中断扫描法中的键盘编码的问题
比如说,键盘口为,P1 在一开始输出,01111111B,再判断P1口值是否变化..若没变化再换成,10111111B,再判断P1口值是否变化..这样依次到,11101111B,在有变化时就可以得到把描码了..就像是你那个表中所示.的数值就经过这四次都可以得出其中一种...include<reg51.h> define uchar unsigned char define ...

如何利用51单片机4*4矩阵键盘和1602液晶实现四位(或者多位)的显示问...
\/\/按4X4键盘的F键 进入设定状态 \/\/E D 键是前后移动键 \/\/C按键是调整数值按键 include "reg52.h"define uchar unsigned char sbit RW=P2^1;sbit RS=P2^0;sbit E=P2^2;bit at=0;uchar code shen[]={"CLOCK!"};uchar code word[]={0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,...

用51单片机制作一个电子密码锁,采用4×4键盘输入,复位功能怎么实现...
复位功能,在硬件电路里接一个按钮开关,按下的时候电路断开,松手的时候通电,就实现复位了啊!

51单片机4*4键盘,输入数据到数组中
LZ可以考虑在键值处理函数中加入这个试试 if(功能键按下){ NUM++;\/\/NUM为数组的下标 此处应加数组元素个数的判断,防止“越界”if(NUM小于数组元素个数){ a[NUM]=function(输入单个数据);} }

你好,我用51单片机要实现4个按钮控制8盏流水灯,四个按钮分别是启动停止...
include<reg51.h>#include<intrins.h>#define uchar unsigned charsbit k1=P1^0;sbit k2=P1^1;sbit k3=P1^2;sbit k4=P1^3;void delay(uchar a){uchar i;while(a--)for(i=0;i<120;i++);}main(){uchar flag=0;uchar led=0xff;while(1) { if(k1==0) { delay(10...

急求4*4矩阵键盘控制数码管显示! 51单片机
共阳极数码管 如果是共阴极数码管则 display()里的P0=0xff;改为P0=0x00;P2=smg_we[a];改为P2=~smg_we[a];P0=dsp_code_ca[xianshi[a]];改为P0=~dsp_code_ca[xianshi[a]];即可 include<reg51.h> define uchar unsigned char define uint unsigned int uchar key_char,key_char0;ui...

和顺县19229123422: 请问单片机中的4*4矩阵键盘的键值怎么求??? -
鱼衫单磷: 单片机书上应该有讲的哦,多查资料. 既然是4x4,即4行4列了,共需要8个I/O口,有8bit数据(如高四位为行4bit,低四位为列4bit)位:xxxx xxxx.还要结合你的程序来编码键值,如果有键按下了,查询所有按键的所连接的I/O口电平状态,每...

和顺县19229123422: 单片机4*4矩阵按键如何计算键值???
鱼衫单磷: 我给你一种线转法吧,这种比较简单JIANPAN: KEY EQU 50H KEY_NUMBER EQU 60H MOV P1,#0FH ;读列线 MOV A,P1 ANL A,#0FH CJNE A,#0FH,KEY_SCAN LJMP EXITKEY_SCAN: MOV P1,#0FH ;读列线 MOV A,P1 ANL A,#0FH MOV...

和顺县19229123422: 51单片机4*4按键做的计算器,谁会?要C编的. -
鱼衫单磷: 1.首先,你需要一个4*4的按键扫描程序,得到一个键值.2.然后你在根据得到的键值来进行相应的运算即可,得到一个运算结果.3.然后将得到的结果输出.输出在使用LCD屏还是,通过串口传到电脑终端,这个看你的设计了.你可以自己做,会收获不少的.或者给钱,让人帮你做咯.

和顺县19229123422: 单片机c语言求救 我做一个4*4的按键扫描, row=P3&0xf0; P3=row|0x0f; col=P3&0x0f; 看不懂中间那句 -
鱼衫单磷: row=P3&0xf0; 意思是:屏蔽低4位,只取出高4位的值,高4位是多少与完后还是多少.也就是列值 P3=row|0x0f; 意思是:P3口读会现在按下哪个键的值 col=P3&0x0f; 意思是:同第一句一样屏蔽高4位,取第四位值.也就是行值.

和顺县19229123422: 单片机S51设计一个计算器 求键盘程序(4*4) -
鱼衫单磷: 键盘扫描+键值转换的方法.4*4的矩阵键盘,我使用不开中断的反转法来做,简单来说就是将横列置1纵列置0,检测到案件后再纵列置1横列置0,这样就可以扫描到按键的特征码了.以下是我早期写的一段程序,你学单片机的,端口怎么用,#...

和顺县19229123422: 51单片机以矩形键盘为数字按键,以LCD为显示器,怎么写计算器代码?求大概思路 -
鱼衫单磷: 12864大液晶吗还是字符型的液晶!不难!就是4*4矩键 输入数据,还有几个运算符的键,怎么运算,写在程序里! 矩键就想当于得到数字和运算符! 然后再加个清屏或着重新开始运算的!定义几个变量,弄个循环,可以死循环,设个定义(从按键里输入),结束输入,矩键的+,-,*,/,可以用switch(key)开关例: switch(key) {case 0xee: a*b;break; case 0xed: a/b; break;}

和顺县19229123422: 51单片机如何通过4*4矩阵键盘输入一个两位数,送给一个变量?求助... -
鱼衫单磷: 设置其中的一个按键,定为标志位 如果没有按下标志位 则 a=a*10+key ; //key为按键值

和顺县19229123422: 51单片机 如何4*4矩阵键盘输入按键 继电器输出信号 -
鱼衫单磷: ........... Inter0_process() interrupt 2 //外部中断1 { Key_scan();//你的键盘扫描程序(中断服务程序),一旦触发中断,将运行至本段. } //主程序main() {........... ........... ........... EX1=1; //开中断一 P3.3 IT1=1; //下降沿触发 ET1=1; EA=1;........... ...........} 注:图中的键盘接法都是独立按键接发,矩阵键盘没有见过能直接触发中断的.

和顺县19229123422: 给予51单片机的简单计算器怎么让它在按键按下的时候 -
鱼衫单磷: 这是我做的一个简易计算器.十位数的加减乘除.#include#define uchar unsigned char; uchar LED1,LED2,LED3,LED4; uchar keyval,calflag,s_dat,d_dat; uchar distab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x...

和顺县19229123422: c51单片机的定时器计数器怎么用?最好用例子 -
鱼衫单磷: 方法有很多的,给你一个,你可以调试一下,你可以通过不同的晶振去计算定时器初值,如果你懂定时器这部分很好调通的 #include sbit p1_0=P1^0; int i; //全局变量void timing(void) //晶振为3.6864M {TMOD|=0x01; //定时器T0,...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网