我想用51单片机,矩阵键盘,lcd1602写个简易计算器程序

我想用51单片机,矩阵键盘,lcd1602写个简易计算器程序,第1张

C语言的语句可以这样写

#include<stdioh>

void main()

{

float fxx;

unsigned char str[10];

fxx = 125;

sprintf(str,"%82f\n",fxx); //将125转换成82(2位小数)格式以ASCII方式存储到str字符串中

}

由于1620液晶模块支持ASCII码,所以只要将str中的内容送到1602就行了。至于1602的 *** 作我就不写了(其实我也没用过,但知道怎么用,应该不难)

要求还不低,i简单的我有,不能实现混合运算比较

主程序如下:

void main()

{ while(1)

{

c=1;

while(c<7)//输入第1个6 位数

{

keyval=keyscan();

if(keyval<10)

{

switch(c)

{

case 1:b1=keyval; break;

case 2:b2=keyval; break;

case 3:b3=keyval; break;

case 4:b4=keyval; break;

case 5:b5=keyval; break;

case 6:b6=keyval; break;

}

c++;

}

display(b1,b2,b3,b4,b5,b6);

}

while(c==7) //输入计算符号

{

keyval=keyscan();

if(keyval>=10)

{

d=keyval;

}

c=1;

}

while(c<7) //输入第2个6 位数

{

keyval=keyscan();

if(keyval<10)

{

switch(c)

{

case 1:d1=keyval; break;

case 2:d2=keyval; break;

case 3:d3=keyval; break;

case 4:d4=keyval; break;

case 5:d5=keyval; break;

case 6:d6=keyval; break;

}

c++;

}

display(d1,d2,d3,d4,d5,d6);

}

P1=0;

bb= b1100000+b210000+b31000+b4100+b510+b6;

dd=d1100000+d210000+d31000+d4100+d510+d6;

while(keyval!=15) //等待按下"="号

{

keyval=keyscan();

}

delay(100);

switch(d1)//根据输入的运算符,作不同的运算

{

case 10:ee=bb+dd; break;//加

case 11:

flag1=0;

if(bb>=dd)//减

{

ee=bb-dd;

flag1=1;;//flag 是正负号标志

}

else ee=bb-dd;

break;

case 12:ee=bbdd; break;//乘

case 13:ee=bb/dd; break; //除

}

f1=ee/100000%10;;// 分离 个十百千万

f2=ee/10000%10;

f3=ee/1000%10;

f4=ee/100%10;

f5=ee/10%10;

f6=ee%10;

display(f1,f2,f3,f4,f5,f6);//显示运算结果

}

}

看不太懂,不过发现好象按键扫描程序有误

象 P1=0xf0; 你的目的可能是让高4 位作为输出,低4 位作为输入

按键按下时,高4 位的1传到低4 位上,这样是不行的

对于51单片机,由于是弱上拉,只有0将1拉低,1不可能将0填高

就是说让 P1=0xf0,读取P1,低4 位永远是0

if(P1==0xf1) if (P1==0xf2)等条件永远不具备

ORG 0000H

LJMP MAIN

ORG 0100H

MAIN:MOV SP,#7EH

MOV 22H,#00H

CLR P20

CLR P23

MOV 20H,#00H

MOV 21H,#00H

MOV 30H, #00H

MOV 31H, #00H

MOV 32H, #00H ;初始化

SU: MOV 7DH,#0FFH

MOV 7EH,#0FFH

MOV 7FH,#0FFH

KEYI:ACALL KS1

CJNE A,#0F0H,LK1

ACALL DIR

AJMP KEYI

LK1:ACALL DIR

ACALL DIR

ACALL KS1

CJNE A, #0F0H,LK2

ACALL DIR

AJMP KEYI

LK2: ACALL KS1

MOV R2,A

ORL A,#0FH

MOV P0,A

ANL A,#0FH

ADD A,R2 ;键特征值

CJNE A,#0EEH,JZHI1

MOV A,#00H

PUSH ACC

JZHI1: CJNE A,#0DEH,JZHI2

MOV A,#01H

PUSH ACC

JZHI2: CJNE A,#0BEH, JZHI3

MOV A,#02H

PUSH ACC

JZHI3: CJNE A,#7EH,JZHI4

MOV A,#03H

PUSH ACC

JZHI4: CJNE A, #0EDH, JZHI5

MOV A,#04H

PUSH ACC

JZHI5: CJNE A,#0DDH, JZHI6

MOV A, #05H

PUSH ACC

JZHI6: CJNE A,#0BDH, JZHI7

MOV A, #06H

PUSH ACC

JZHI7: CJNE A,#07DH, JZHI8

MOV A, #07H

PUSH ACC

JZHI8: CJNE A,#0EBH, JZHI9

MOV A, #08H

PUSH ACC

JZHI9: CJNE A,#0DBH, JZHI10

MOV A, #09H

PUSH ACC

JZHI10: CJNE A,#0BBH, JZHI11

MOV 20H,#01H

JZHI11: CJNE A,#07BH,FAN

MOV 21H, #01H

LCALL GMI

SETB P22 ;灭绿灯

LJMP SU ;改密

FAN: MOV A, 81H

CJNE A,#7FH, KEYI

JNB (20H)0, KEYITMP

MOV 20H,#00H

JBC (21H)0,LOOP

POP ACC

CJNE A,32H,NOTE

MOV 7FH,A

POP ACC

CJNE A,31H,NOTE

MOV 7EH,A

POP ACC

CJNE A,30H,NOTE

MOV 7DH,A

CLR P22

KEYITMP:LJMP KEYI

NOTE:LCALL BAOJ ;NOT是保留字不能做标号

SUTMP:LJMP SU

BAOJ:MOV SP,#7EH

INC 22H

JNB (22H)1, SUTMP

CLR P21

SETB P23

ACALL DELY1

CPL P21

CPL P23

MOV 22H,#00H

RET

GMI:JNB P22,SUTMP

LOOP:POP 32H

POP 31H

POP 30H

RET

DIR:MOV R0,#7DH

MOV R3,#01H

LD1: MOV A,@R0

MOV P1,A

MOV P3,R3

LCALL DELY

INC R0

MOV A,R3

JB ACC2,LD2

RL A

MOV R3,A

SJMP LD1

LD2:RET ;显示

DELY:MOV R7,#249

DL:DJNZ R7,DL

RET ;1ms延时

DELY1:MOV R5,#200

MOV R4,#50

LOOP1:MOV R3,#248

NOP

LOOP2:DJNZ R3,LOOP2

DJNZ R5,LOOP1

DJNZ R4,LOOP1

RET ;10s延时

KS1:MOV P0,#0F0H

MOV A,P0

ANL A, #0F0H

RET ;键是否按下

end

这是流程:

1 4X4键盘输入,点阵字符型液晶显示。

2 由于所采用的浮点程序库的限制(MCU平台只找到这个……),浮点运算采用3字节二进制补码表示,有效数字6位。对于输入输出,采用3字节BCD码浮点数格式,有效数字只有4位,因此最终有效数字只有4位。

3 可进行连续输入,例如:123+456823/2348 ,但是运算结果为从左到右,这也是8位简易计算器的方式。

4 可进行错误判断,溢出、除零等错误将显示一个字符 E 。

5 由于键盘只有16个按键,安排如下:

+---------------+

| 7 | 8 | 9 | + |

| 4 | 5 | 6 | - |

| 1 | 2 | 3 | |

| 0 | | = | / |

+---------------+

6 按键的缺少导致取消了一些特殊函数,即开根号,三角函数(sin, cos, tan, ctg)的实现,由于这些函数在浮点程序库中均已提供,如果硬件允许,在原来的框架上添加这些附加功能是很容易的(可以看作和+, -, , /等价的按键 *** 作,调用不同的子程序进行运算即可)

7 按两次 = 等于清灵。因为按键实在太少,才采用了这个做法。

8 相应举例:

按键 结果 说明

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

123+= 123 按下等号而没有第二个 *** 作数,保留第一个 *** 作数

并认为此次运算结束(等号的功能)

123+321/111 40 等价于(123+321) / 111

23+54=/01+ 77 等号后直接按 / ,则将前面的运算结果作为第一个

*** 作数

1/0= E 错误显示

这是源码:>

你再把分加到100分,我给你一个C语言的,带电路图。

;不知和您的硬件电路是否相同,

;不知和2你的单片机型号是否相同

sec_l equ 30h ;30单元存储秒个位

sec_h equ 31h ;31单元存储秒十位值

bar_2 equ 32h ;32单元存储"-"段码的偏移量

min_l equ 33h ;33单元存储分个位值

min_h equ 34h ;34单元存储分十位值

bar_5 equ 35h ;35单元存储"-"段码的偏移量

hou_l equ 36h ;36单元存储时个位值

hou_h equ 37h ;37单元存储时十位值

sec equ 38h ;38单元为秒计数器(00s-59s)

min equ 39h ;39单元为分计数器(00m-59m)

hou equ 40h ;40单元为时计数器(00h-23h)

cou equ 41h ;41单元为软计数器,对10ms时基信号累加到1s

dis_b equ 42h ;dis_b(42单元)作为位码选通数码管

dis_r equ 43h ;dis_r(43单元)为取段码时的偏移量

key_v equ 44h ;存储键值

key_t equ 45h ;按键扫描中临时存储键值

org 0000h

ajmp start

org 000bh ;定时器0的中断入口地址

ajmp time0 ;跳到定时器0的中断服务程序处

org 001bh ;定时器1的中断入口地址

ajmp time1 ;跳到定时器1的中断服务程序处

org 0030h

start:

mov p2,#0xff ;关所有数码管

mov p1,#0xff ;p1为准双向口,作输入时先写1

mov key_v,#0xff ;初始键值为ff

mov bar_2,#10 ;'-'段码偏移量为10

mov bar_5,#10 ;'-'段码偏移量为10

mov dis_b,#0x7f ;初始选通P27口数码管

mov dis_r,#0 ;初始化偏移量为0

mov sec,#0 ;秒计数清零

mov min,#0 ;分计数清零

mov hou,#0 ;时计数清零

mov cou,#0 ;软计数器清零

mov tmod,#00010001b ;定时/计数器0、1工作于方式1

mov th0,#0xd8 ;预置定时常数55536(d8f0),产生10ms时基信号

mov tl0,#0xf0

mov th1,#0xfc ;预置定时常数64536(fc18),产生1ms间隔用于动态显示

mov tl1,#0x18

setb ea ;开总中断

setb et0 ;定时/计数器0允许中断

setb et1 ;定时/计数器1允许中断

setb tr0 ;开定时/计数器0

setb tr1 ;开定时/计数器1

key:

mov a,p1 ;读入键值

mov key_t,a ;存储到临时变量中

xrl a,key_v ;检测键值是否改变

jz key ;未改变则重新扫描

lcall d_10ms ;有键按下则延时10ms消抖

mov a,p1 ;再次读入键值

mov key_t,a ;存入临时变量

xrl a,key_v ;检测键值是否改变

jz key ;未改变则为抖动继续扫描

mov key_v,key_t ;确定为键按下则保存键值

lcall key_to ;调用键处理部分

ajmp key ;循环扫描按键

key_to: ;键处理子程序

mov a,key_v ;读入键值

cjne a,#0xef,next ;不是P14口键值则查下一个

ajmp k1 ;是则转去执行该键的处理

next: cjne a,#0xdf,back ;也不是P15口键值则结束

ajmp k2 ;是则转去执行该键的处理

k1: mov a,min ;读入分计数器的值

cjne a,#59,k1_add ;分计数值未到59

mov min,#0 ;分钟加到59时则清零

ajmp back ;结束

k1_add: inc min ;分加1

ajmp back ;结束

k2: mov a,hou ;读入时计数器的值

cjne a,#23,k2_add ;时计数值未到23

mov hou,#0 ;时加到23时则清零

ajmp back ;结束

k2_add: inc hou ;时加1

back: ret ;结束

;--------------------------------------------------------------------------------

time0: ;定时器0中断服务程序

push psw ;保护现场

push acc

inc cou ;软计数器加1

mov a,cou ;计数器值送入a

cjne a,#100,over ;未计到100则返回继续计数

mov cou,#0 ;计到100后软计数器清零(到1s)

inc sec ;秒计数器加1(进位10ms100=1s)

mov a,sec ;秒计数值送入a

cjne a,#60,over ;未计到60则返回继续计数

mov sec,#0 ;计到60后秒计数器清零

inc min ;分计数器加1(进位60s=1m)

mov a,min ;分计数值送入a

cjne a,#60,over ;未计到60则返回继续计数

mov min,#0 ;计到60后分计数器清零

inc hou ;时计数器加1(进位60m=1h)

mov a,hou ;时计数值送入a

cjne a,#24,over ;未计到24则返回继续计数

mov hou,#0 ;计到24后时计数器清零,重新计时

over: mov th0,#0xd8 ;重置定时常数

mov tl0,#0xf0

pop acc ;恢复现场

pop psw

reti ;中断返回

;--------------------------------------------------------------------------------

time1: ;定时器1中断服务程序

push psw ;保护现场

push acc

push b

;以下是秒计数器值个位十位分开

mov a,sec ;秒计数器值送入a(被除数)

mov b,#10 ;除数10送入b

div ab

mov sec_l,b ;余数b(秒个位值)送入秒个位存储单元

mov sec_h,a ;商a(秒十位值)送入秒十位存储单元

;以下是分计数器值个位十位分开

mov a,min ;分计数器值送入a(被除数)

mov b,#10 ;除数10送入b

div ab

mov min_l,b ;余数b(分个位值)送入分个位存储单元

mov min_h,a ;商a(分十位值)送入分十位存储单元

;以下是时计数器值个位十位分开

mov a,hou ;时计数器值送入a(被除数)

mov b,#10 ;除数10送入b

div ab

mov hou_l,b ;余数b(时个位值)送入时个位存储单元

mov hou_h,a ;商a(时十位值)送入时十位存储单元

mov dptr,#table ;数码管段码表首址送入dptr

mov a,#sec_l ;取秒个位值的地址

add a,dis_r ;基址+偏移量

mov r0,a ;R0为欲显示值的地址

mov a,@r0 ;取欲显示值送入a

; dis_r : 0 1 2 3 4 5 6 7

;对应单元: sec_l sec_h bar_2 min_l min_h bar_5 hou_l hou_h

movc a,@a+dptr ;取对应值的段码

mov p0,a ;段码送入P0口

mov p2,dis_b ;位码送入P2口

inc dis_r ;偏移量加1,下次中断时显示下个数

anl dis_r,#0x07 ;dis_r增到8时自动清0(使之在0到7间循环)

mov a,dis_b ;位码循环右移,下次中断时选通下个数码管

rr a

mov dis_b,a

mov th1,#0xfc ;重置定时常数

mov tl1,#0x18

pop b

pop acc ;恢复现场

pop psw

reti

d_10ms: mov r5,#20 ;1+(1+2255)20+220=10261ms@12M

temp1: mov r6,#255 ;1+2255

djnz r6,$

djnz r5,temp1

ret

table: db 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf ;段码表

; 0 1 2 3 4 5 6 7 8 9 - 对应内容

羚羊

end

楼主,我给你一个代码,你参考一下和验证一下!

用51单片机做的简单计算器的程序

/按键处理/

void KeyDeal(unsigned char Key)

{

if(Key!=0) //判断 有无按键按下。

{

switch(Key)

{ //以下定义0~9的数字键。

case 0x11: K=0; break;

case 0x21: K=1; break;

case 0x41: K=2; break;

case 0x81: K=3; break;

case 0x12: K=4; break;

case 0x22: K=5; break;

case 0x42: K=6; break;

case 0x82: K=7; break;

case 0x14: K=8; break;

case 0x24: K=9; break;

//以下+。-,,/ 键

case 0x44: K=10; break; //加

case 0x84: K=11; break; //减

case 0x18: K=12; break; //乘

case 0x28: K=13; break; //除

case 0x48: K=14; break; //等于

case 0x88: K=15; break; //清除

default: break;

}

if(K<10) //数字键

{

d[2]=d[1];

d[1]=d[0];

d[0]=K;

c[2]=c[1];

c[1]=c[0];

c[0]=b[K];

//以上数组数据赋值是保证数字按键入顺序移位。

}

if(K==10) //加

{ m=d[2]100+d[1]10+d[0],d[0]=0,d[1]=0,d[2]=0,d[3]=0,d[4]=0;p=1;

c[0]=0xc0, c[1]=0xc0, c[2]=0xc0, c[3]=0xc0, c[4]=0xc0; }

if(K==11)//减

{ m=d[2]100+d[1]10+d[0],d[0]=0,d[1]=0,d[2]=0,d[3]=0,d[4]=0;p=2;

c[0]=0xc0, c[1]=0xc0, c[2]=0xc0, c[3]=0xc0, c[4]=0xc0;}

if(K==12)//乘

{ m=d[2]100+d[1]10+d[0],d[0]=0,d[1]=0,d[2]=0,d[3]=0,d[4]=0;p=3;

c[0]=0xc0, c[1]=0xc0, c[2]=0xc0, c[3]=0xc0, c[4]=0xc0;}

if(K==13)//除

{ m=d[2]100+d[1]10+d[0],d[0]=0,d[1]=0,d[2]=0,d[3]=0,d[4]=0;p=4;

c[0]=0xc0, c[1]=0xc0, c[2]=0xc0, c[3]=0xc0, c[4]=0xc0;}

if(K==14) //此处是按 =键

{ n=d[2]100+d[1]10+d[0];

if (p==1) shu=m+n;

if (p==2) shu=m-n;

if (p==3) shu=mn;

if (p==4) shu=m/n;

c[4]=b[shu/10000];

c[3]=b[shu%10000/1000];

c[2]=b[shu%1000/100];

c[1]=b[shu%100/10];

c[0]=b[shu%10]; //C[]存的是 计算结果 。

}

if(K==15) // 此处是按 清除键

{d[0]=0,d[1]=0,d[2]=0,d[3]=0,d[4]=0;

shu=0;

c[4]=b[shu/10000];

c[3]=b[shu%10000/1000];

c[2]=b[shu%1000/100];

c[1]=b[shu%100/10];

c[0]=b[shu%10]; }

}

}

void main()

{

while(1)

{

Key = Keycan();//键盘扫描获取一次按键的编码0x11-0x88

KeyDeal(Key); //对扫描到的键盘编码进行转换处理,变成数据键盘0-

display();

}

以上就是关于我想用51单片机,矩阵键盘,lcd1602写个简易计算器程序全部的内容,包括:我想用51单片机,矩阵键盘,lcd1602写个简易计算器程序、51单片机计算器,运算部分和结果显示怎么写、51单片机 计算器程序 不能成功 按键按下没反应 附上程序 看哪里错误等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存