51单片机设计的简易的计算器

51单片机设计的简易的计算器,第1张

我以前做过4x4键盘控制电动机转速,用数码管显示电机转速的程序,程序如下:

AD EQU 30H

RTR EQU 31H

LTR EQU 32H

STR EQU 33H

BW EQU 34H

BWS EQU 35H

SHW EQU 36H

SHWS EQU 37H

GW EQU 38H

GWS EQU 39H

WSHR EQU 3AH;WSHR=BWS100+SHWS10+GWS

sz EQU 3BH;数字与代码对应程序的数字变量

xsm EQU 3CH;数字与代码对应程序的代码变量

TODH EQU 3DH;计算的10进位数的高位电机的要求转速高位

TODL EQU 3EH;计算的10进位数的低位电机的要求转速低位

TODHT EQU 3FH;测试后电机的实际转速高位

TODLT EQU 40H;测试后电机的实际转速低位

PCK EQU 41H;pc口当前的状态植

TOH EQU 42H;定时器高位数

T0L EQU 43H;定时器低位数

pink1 EQU 44H;电机转动1/4圈定时器1的奇数次数

pink2 EQU 45H

VTIMES EQU 46H;速度显示次数

T1H EQU 47H

T1L EQU 48H

TESTK DATA 49H ;高电平脉冲的个数

TTH0 EQU 1AH

TTL0 EQU 4BH

SUBNOW EQU 4CH

ORG 0000H

LJMP MAIN

ORG 03H

AJMP INTR0;中段0,用来计算电机转速

ORG 0BH

MOV A,PCK

ANL A,#00000111B

MOV PCK,A

MOV A,#00000110B

CJNE A,PCK,INTT0LF

LJMP INTT0L;

ORG 1BH;pwm停转子程序

AJMP INTT0H

ORG 0040H

;定时器中断子程序

;电机停止程序

INTT0H:

mov th0,TOH

mov tl0,T0L

SETB TR0;定时器0开始计数

CLR TR1;定时器1禁止计数

INC pink1

MOV DPTR,#7F02H; b地址

MOV A, #00000000B;电机停止运动

MOVX @DPTR,A

reti

;电动机正转子程序

INTT0L:

mov th1,T1H

mov tl1,T1L

SETB TR1;定时器1开始计数

CLR TR0;定时器0禁止计数

MOV DPTR,#7F02H; b地址

MOV A, #11001100B;C口输出片选号灯

MOVX @DPTR,A

reti

;电动机反转

INTT0LF:

mov th1,T1H

mov tl1,T1L

SETB TR1;定时器1开始计数

CLR TR0;定时器0禁止计数

MOV DPTR,#7F02H; b地址

MOV A, #10101100B;C口输出片选号灯

MOVX @DPTR,A

reti

;计算电机转速

;R2R3R4R5/ R6R7=R4R5余R2R3////(R2R3R4/R7)=(R2)R3R4 余数R7

INTR0:

MOV R2,#00H

MOV R3,#0EH

MOV R4,#0A6H

MOV R7,pink1

MOV pink1,#0

MOV A,#10

CLR CY

SUBB A,R7

JNB CY,OUTINT0

LCALL NDIV31

MOV TODHT, R3

MOV TODLT,R4

MOV R6,TODH

MOV R7,TODL

CLR CY

MOV A,R4

SUBB A,R7

MOV SUBNOW,A

JB CY,ADV

LCALL SUBV

JMP OUTINT0

ADV:

LCALL ADDV

OUTINT0:

LCALL JSW;计算各位的数值毫时大大约600个始周期 ;MOV TODLT,TOH

;LCALL JSW;计算各位的数值毫时大大约600个始周期

RETI;

;

;

COMP_M:

MOV A,#0FDH

SUBB A,TOH

JNB CY,OUT_PMM

MOV TOH,#0FDH

MOV T1H,#85

OUT_PMM:

RET

;加速子程序

ADDV:

CLR EA

CLR TR1

CLR TR0

MOV R1,SUBNOW

MOV R0,#10000000B

FRT:

MOV A,R0

RL A

MOV R0,A

MOV A,R1

ANL A,R0

JZ FRT

MOV A,TOH

ADD A,R0

JC VMAX

MOV TOH,A

MOV A,T1H

SUBB A,R0

MOV T1H,A

JMP TXT

VMAX:

MOV TOH,#0FDH

MOV T1H,#85

TXT:

SETB TR0

SETB TR1

SETB EA

RET

;减加速子程序

SUBV:

CLR EA

CLR TR1

CLR TR0

MOV R1,SUBNOW

MOV R0,#10000000B

FRT1:

MOV A,R0

RL A

MOV R0,A

MOV A,R1

ANL A,R0

JZ FRT1

MOV A,TOH

SUBB A,R0

JC VMAX1

MOV TOH,A

MOV A,T1H

ADD A,R0

MOV T1H,A

JMP TXT1

VMAX1:

MOV TOH,#85

MOV T1H,#0FDH

TXT1:

SETB TR0

SETB TR1

SETB EA

RET

;主程序

MAIN:

MOV BW,#7DH

MOV SHW,#7DH

MOV GW,#7DH

MOV BWS,#0

MOV SHWS,#0

MOV GWS,#0

MOV SP,#0A0H

MOV TOH,#0A1h;

MOV T0L,#0h;

MOV T1H,#0E1h;

MOV T1L,#37h;

MOV TMOD,#00H;定时器0在模式1下工作

MOV RTR,#00110110B

MOV LTR,#00101101B

MOV PCK,#00H

MOV TODHT,#2

MOV TODLT,#25H

MOV TODH,#0

MOV TODL,#0

;LCALL JSTIM;计算总值TODH;TODL

MOV pink2,#0

MOV pink1,#0

SETB EX0

SETB IT0

START:

MOV DPTR,#7F00H; 状态字地址

MOV A, #00111111B;设A,B,C口均为输出

MOVX @DPTR,A

LCALL DISPLAY;显示

LCALL KEYSC;扫描键盘

;MOV TESTK,#44H;TEST

ACALL DISPKEYV ;确定键盘

;LCALL JSTIM;计算总值TODH;TODL

;LCALL JSW;计算各位的数值毫时大大约600个始周期

LCALL JSEHW;计算各个代码

JMP START

;键盘扫描程序

KEYSC:

MOV TESTK,#0

mov p1,#0FH ;p10-3输出1,作为输入位

mov a ,p1

ANL A,#0FH

CJNE A,#0FH,DELAY

RET

DELAY: ACALL DELAY1 ; 延时去键抖

mov a ,p1

ANL A,#0FH

CJNE A,#0FH,HAVE

RET

HAVE:

MOV A,#0EFH ;行扫描码

NEXT:

MOV B,A

MOV P1,A

MOV A,p1

ANL A,#0FH ;检测列

CJNE A,#0FH,YES

MOV A,B

RL A

CJNE A,#0FEH,NEXT

YES: orl a,#0f0h ;高四位置1

CPL A

mov r2,#00h

MOV R2,A ;存列码

MOV A,B ;取行码,

CPL A

ORL A,R2 ;列码+行码=键植

MOV AD,#00H

MOV TESTK,A

RET

;确定键盘程序

DISPKEYV:MOV A,TESTK

KEY0:CJNE A,#11H,KEY1

acall WORD0

KEY1:CJNE A,#12H,KEY2

acall WORD1

KEY2:CJNE A,#14H,KEY3

acall WORD2

KEY3:CJNE A,#18H,KEY4

acall WORD3

KEY4:CJNE A,#21H,KEY5

acall WORD4

KEY5:CJNE A,#22H,KEY6

acall WORD5

KEY6:CJNE A,#24H,KEY7

acall WORD6

KEY7:CJNE A,#28H,KEY8

acall WORD7

KEY8:CJNE A,#41H,KEY9

acall WORD8

KEY9:CJNE A,#42H,KEY10

acall WORD9

KEY10:CJNE A,#44H,KEY11

acall WORD10

KEY11:CJNE A,#48H,KEY12

acall WORD11

KEY12:CJNE A,#81H,KEY13

acall WORD12

KEY13:CJNE A,#82H,KEY14

acall WORD13

KEY14:CJNE A,#84H,KEY15

acall WORD14

KEY15:

CJNE A,#88H,PASS

AJMP WORD15

PASS:RET

WORD0:

lCALL MOVE

MOV A,#0

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV R0,TESTK

TSTK0:

LCALL KEYSC

MOV A,R0

CJNE A,TESTK,OUT0

JMP TSTK0

OUT0:

MOV R0,#0

RET

WORD1:

lCALL MOVE

MOV A,#1

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV R0,TESTK

TSTK1:

LCALL KEYSC

MOV A,R0

CJNE A,TESTK,OUT1

JMP TSTK1

OUT1:

MOV R0,#0

RET

WORD2:

lCALL MOVE

MOV A,#2

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV R0,TESTK

TSTK2:

LCALL KEYSC

MOV A,R0

CJNE A,TESTK,OUT2

JMP TSTK2

OUT2:

MOV R0,#0

ACALL JSEHW;计算各个位的显示代码

RET

WORD3:

lCALL MOVE

MOV A,#3

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV R0,TESTK

TSTK3:

LCALL KEYSC

MOV A,R0

CJNE A,TESTK,OUT3

JMP TSTK3

OUT3:

MOV R0,#0

ACALL JSEHW;计算各个位的显示代码

RET

WORD4:

lCALL MOVE

MOV A,#4

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK4:

LCALL KEYSC

CJNE A,TESTK,OUT4

JMP TSTK4

OUT4:

ACALL JSEHW;计算各个位的显示代码

RET

WORD5:

lCALL MOVE

MOV A,#5

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK5:

LCALL KEYSC

CJNE A,TESTK,OUT5

JMP TSTK5

OUT5:

ACALL JSEHW;计算各个位的显示代码

RET

WORD6:

lCALL MOVE

MOV A,#6

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK6:

LCALL KEYSC

CJNE A,TESTK,OUT6

JMP TSTK6

OUT6:

ACALL JSEHW;计算各个位的显示代码

RET

WORD7:

lCALL MOVE

MOV A,#7

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK7:

LCALL KEYSC

CJNE A,TESTK,OUT7

JMP TSTK7

OUT7:

ACALL JSEHW;计算各个位的显示代码

RET

WORD8:

lCALL MOVE

MOV A,#8

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK8:

LCALL KEYSC

CJNE A,TESTK,OUT8

JMP TSTK8

OUT8:

ACALL JSEHW;计算各个位的显示代码

RET

WORD9:

lCALL MOVE

MOV A,#9

MOV GWS,A

LCALL JSTIM;计算总值TODH;TODL

MOV A,TESTK

TSTK9:

LCALL KEYSC

CJNE A,TESTK,OUT9

JMP TSTK9

OUT9:

ACALL JSEHW;计算各个位的显示代码

RET

WORD10:

CLR EA

CLR ET0

CLR TR0

mov th0,TOH

mov tl0,T0L

MOV PCK,#00000110B

SETB EA;打开所有中断

SETB ET0;定时器允许中断

SETB TR0;定时器0开始计数

CLR TR1;定时器1禁止计数

SETB ET1;定时器1允许中断

RET

WORD11:

CLR EA

CLR ET0

CLR TR0

mov th0,TOH

mov tl0,T0L

MOV PCK,#00000101B

SETB EA;打开所有中断

SETB ET0;定时器允许中断

SETB TR0;定时器0开始计数

CLR TR1;定时器1禁止计数

SETB ET1;定时器1允许中断

RET

WORD12:

LCALL ADDV

MOV TODLT,TOH

LCALL JSW;计算各位的数值毫时大大约600个始周期

MOV A,TESTK

TSTK12:

LCALL KEYSC

CJNE A,TESTK,OUT12

JMP TSTK12

OUT12:

RET

WORD13:

LCALL SUBV

MOV TODLT,TOH

LCALL JSW;计算各位的数值毫时大大约600个始周期

MOV A,TESTK

TSTK11:

LCALL KEYSC

CJNE A,TESTK,OUT11

JMP TSTK11

OUT11:

RET

WORD14:

CLR ET0;使能定时器0中断

CLR ET1;使能定时器1中断

CLR EA;使能总中断

CLR TR1;关闭T1计时

CLR TR0;关闭T0计时

MOV PCK,#00H

MOV BW,#7DH

MOV SHW,#7DH

MOV GW,#77H

RET

WORD15:JB EA,MID15

MOV BWS,#0

MOV SHWS,#0

MOV GWS,#0

JMP OUT15

MID15:

CLR EA

MOV A,TESTK

TSTK15:

LCALL KEYSC

CJNE A,TESTK,OUT15

JMP TSTK15

MOV TODLT,TOH

LCALL JSW;计算各位的数值毫时大大约600个始周期

OUT15:

SETB EA

RET

;计算各个代码

JSEHW:

MOV SZ,BWS

ACALL js

MOV BW,xsm

MOV SZ,SHWS

ACALL js

MOV SHW,xsm

MOV SZ,GWS

ACALL js

MOV GW,xsm

RET

js:

mov a,sz

js0:cjne a,#0,js1

mov xsm,#7dh

js1:cjne a,#1,js2

mov xsm,#14h

js2:cjne a,#2,js3

mov xsm,#6eh

js3:cjne a,#3,js4

mov xsm,#3eh

js4:cjne a,#4,js5

mov xsm,#17h

js5:cjne a,#5,js6

mov xsm,#3bh

js6:cjne a,#6,js7

mov xsm,#7bh

js7:cjne a,#7,js8

mov xsm,#00011100B

js8:cjne a,#8,js9

mov xsm,#7fh

js9:cjne a,#9,js10

mov xsm,#3fh

js10:ret

;计算各位的数值毫时大大约600个始周期

JSW:;(R2R3R4/R7)=(R2)R3R4 余数R7

MOV R2,#0

MOV R3,TODHT

MOV R4, TODLT

MOV R7,#100

LCALL NDIV31

MOV BWS,R4

MOV A,R7;

MOV R4,A

MOV R3,#0

MOV R2,#0

MOV R7,#10

LCALL NDIV31

MOV SHWS,R4

MOV GWS,R7

RET

;计算十进制结果

JSTIM:

MOV TODL,#0

MOV TODH,#0

MOV A,GWS

MOV B,#1

ACALL JSHL

MOV A,SHWS

MOV B,#10

ACALL JSHL

MOV A,BWS

MOV B,#100

ACALL JSHL

RET

JSHW:

JB OV,JSGW

CLR OV

RET

JSGW:

INC TODH;TEST DATE

RET

JSHL:

MUL AB

MOV R1,B

ADD A,TODL

MOV TODL,A

MOV A,B

ADDC A,TODH

MOV TODH,A

ACALL JSHW

RET

;单字节的除法

;(R2R3R4/R7)=(R2)R3R4 余数R7

NDIV31 :MOV A,R2

MOV B,R7

DIV AB

MOV R2,B

MOV B,#10H

NDV311 :CLR C

MOV A,R4

RLC A

MOV R4,A

MOV A,R3

RLC A

MOV R3,A

MOV A,R2

RLC A

MOV R2,A

MOV F0,C

CLR C

SUBB A,R7

JB F0,NDV312

JC NDV313

NDV312 :MOV R2,A

INC R4

NDV313 :DJNZ B,NDV311

CLR OV

JZ NDV314

SETB OV

NDV314 :XCH A,R2

MOV R7,A

RET

;双字节减法(R3R4-R6R7)=(R3R4)

NSUB :MOV A,R4

CLR C

SUBB A,R7

MOV R4,A

MOV A,R3

SUBB A,R6

MOV R3,A

RET

DELAY1:

MOV R5,#10

D1: MOV R6,#250

DJNZ R6, $

DJNZ R5,D1

RET

DELAY_BS:

MOV R5,#5

D2: MOV R6,#99

D3: MOV R7,#99

DJNZ R7, $

DJNZ R6,D3

DJNZ R5,D2

RET

;显示器显示子程序

DISPLAY:

MOV DPTR,#7F01H;

MOV A, BW;

MOVX @DPTR,A

MOV DPTR,#7F03H; c地址

MOV A, #00011000B;C口输出片选号灯

MOV R0,PCK;pck=

ORL A,R0;a=11

MOV R0,#00011111B;a=00011

ANL A,R0

MOVX @DPTR,A

ACALL D_40ms

MOV DPTR,#7F01H;

MOV A, SHW;

MOVX @DPTR,A

MOV DPTR,#7F03H; c地址

MOV A,#00101000B

ORL A,R0

MOV R0,#00101111B

ANL A,R0

MOVX @DPTR,A

ACALL D_40ms

MOV DPTR,#7F01H;

MOV A, GW;

MOVX @DPTR,A

MOV DPTR,#7F03H; c地址

MOV A, #00110000B;C口输出片选号灯

ORL A,R0

MOV R0,#00110111B

ANL A,R0

MOVX @DPTR,A

ACALL D_40ms

mov a,#0ffh

MOVX @DPTR,A

RET

D_40ms:

MOV R7,#10

DELAYBB:

MOV R6,#10

NOP

DELAYNN:

DJNZ R6,DELAYNN; 2X198+2=398

DJNZ R7,DELAYBB; (398+2)X200+1=80ms

RET

;各个位移位自程序

MOVE:

MOV A,SHWS

MOV BWS,A

MOV A,GWS

MOV SHWS,A

RET

END

计算器用R5、R6、R7三位显示,段码为0,全暗,段码为0xff,全亮。

2、R3用于保存运算符

3、两数都用B压入栈中,最后取结果时可以分别d出,并根据 *** 作符计算。

4、程序在两数的第一位默认都输入数字,其他位置皆可复位。

5、一次计算完成后、按任意

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

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

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

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

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

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

程序的话可以给你一个作为参考!  实现了计算结果的小数显示。

//

//扫描显示6位数码管,显示信息为缓冲区的六个“0”

//201787 添加浮点数显示支持

//  

#include<reg52h> //头文件定义

#include<stdioh>

#include<intrinsh>

#define uchar unsigned char // 宏定义

#define uint unsigned int

#define KEY P1

uchar code Tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,//

0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};  //00 显示空

uchar disp_buffer[6]={2,0,1,7,0,5} ,buf[10]; //显示缓冲区

uchar flag = 0;

long dat1,dat2;

float temp;

bit keypress = 1,getv = 0;

void p_data(long dat);

void display();

//

//延时子程序,带有输入参数 m

//

void delay(unsigned int m)

{

unsigned int i,j;

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

{

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

{;}

}

}

//

//按键扫描程序 4X4

//

uchar key()

{

uchar keytemp , key_h;

KEY = 0xf0;

if((KEY &0xf0)!= 0xf0)

{

keytemp = KEY&0xf0;

KEY = 0x0f; //翻转

key_h = KEY&0x0f;

keytemp = keytemp | key_h;

switch(keytemp)

{

case 0xee: return(0);break;

case 0xed: return(1);break;

case 0xeb: return(2);break;

case 0xe7: return(3);break;

case 0xde: return(4);break;

case 0xdd: return(5);break;

case 0xdb: return(6);break;

case 0xd7: return(7);break;

case 0xbe: return(8);break;

case 0xbd: return(9);break;

case 0xbb: return(10);break;

case 0xb7: return(11);break;

case 0x7e: return(12);break;

case 0x7d: return(13);break;

case 0x7b: return(14);break;

case 0x77: return(15);break;

}

}

return 0xff;

}

void keyscan()

{

uchar getk;

getk = key();

if(getk != 0xff)

{

delay(10);

getk = key();

if(getk != 0xff)

{

if(keypress)

{

keypress = 0;

switch(getk)

{

case 0:           //根据按键决定是做哪种运算,并置位getv

getv = 1;

flag = 1;

break;

case 0x0b:

getv = 1;

flag = 2;

break;

case 0x0c:

getv = 1;

flag = 3;

break;

case 0x0d://

flag = 4;

getv = 1;

break;

case 0x0e:  

getv = 0;

switch(flag)                 //按等号键 进行运算,并将结果输出给temp  用于显示

{

case 1:

temp = dat1 + dat2;

break;

case 2:

temp = dat1 - dat2;

break;

case 3:

temp = dat1 dat2;

break;

case 4:

temp = (float)dat1 / (float)dat2;

break;

}

dat1 = 0;

dat2 = 0;

flag = 0;

break;

case 0x0f:

if(!getv)

{

dat1 = dat1/10;;

temp = dat1;

}

else

{

dat2 = dat2/10;

temp = dat2;

}

break;

default:

if(!getv) //根据getv的值判断是第一个数据还是第二个数据!

{

dat1 = dat110 + getk; //将按键值组合成为数据

temp = dat1;

}

else

{

dat2 = dat210 + getk;

temp = dat2;

}

break;

}

}

}

}

else

keypress = 1;

}

//

//填充disp_buffer   浮点数数据处理 转换为整数,并标记小数点位置

//

uchar float_int_dot(float numf)

{

uchar ct,ctn,dotps;

for(ct = 7 ; ct != 0 ; ct--)    //初始化打印缓冲区和显示缓冲区

{

buf[ct - 1] = 0;

if(ct - 1 > 0)

disp_buffer[ct - 2] = 16;

}

sprintf(buf,"%f",numf);

for(ct = 7 ,ctn = 5; ct != 0 ; ct--)

{

if(buf[ct-1] == '')       //如果是小数点则记录位置,并传递给返回值

{

dotps = 6 - ctn;

disp_buffer[ctn] = 0;

}

else if(buf[ct - 1] != '0')//不等于0 则将ascii转换为数值填充入显示缓冲区,

{

disp_buffer[ctn] = buf[ct - 1] - 0x30;

ctn--;

}

}

return dotps;

}

//

//填充disp_buffer ,数据处理

//

void p_data(long dat)

{

uchar pi;

for(pi = 0 ; pi < 6 ; pi++)

{

if(dat != 0 )

{

disp_buffer[5 - pi] = dat%10;

}

else

disp_buffer[5 - pi] = 16;

dat = dat/10;

}

}

//

//显示子程序

//

void display(uchar  flash , uchar count, uchar dot) //dot 代表现实小数点的位置

{

uchar i,temp;

temp = 0x01;

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

{

P2 = temp;                               //位选

/方法一

if( i == flash - 1)

{

if(ct <50)

P0 = Tab[disp_buffer[i]];                //送显示段码

else

P0 = 0;                //送显示段码

}

else

P0 = Tab[disp_buffer[i]];                //送显示段码

/

/方法二/

if(!(flash&0x01))

{

if(count <50)

P0 = Tab[disp_buffer[i]];                //送显示段码

else

P0 = 0;                //送显示段码

}

else

P0 = Tab[disp_buffer[i]];                //送显示段码

flash = flash >> 1;

//

if(dot - 1 == 5 - i)

P0 = P0|0x80;

delay(2);

P0 = 0x00;                               //消隐

temp = _crol_(temp,1);

}

}

//

//主函数

//

void main()

{

uchar dot;

while(1)

{

keyscan();

dot = float_int_dot(temp);

display(0xff,100,dot); //11 001101

}

}

Proteus 仿真图

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的 *** 作我就不写了(其实我也没用过,但知道怎么用,应该不难)

你再把分加到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

这是流程:

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 错误显示

这是源码:>

以上就是关于51单片机设计的简易的计算器全部的内容,包括:51单片机设计的简易的计算器、用51单片机实现多个整数的四则运算的计算器、51单片机 计算器程序 不能成功 按键按下没反应 附上程序 看哪里错误等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

保存