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_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单片机 计算器程序 不能成功 按键按下没反应 附上程序 看哪里错误等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)