求一单片机(C51)的简易计算器程序,能实现加减乘除。

求一单片机(C51)的简易计算器程序,能实现加减乘除。,第1张

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

你是不是想用汇编实现浮点数加减法?网上有好多汇编子程序,其中就有这个。给你个:

标号: FADD 功能:浮点数加法

入口条件:被加数在[R0]中,加数在[R1]中。

出口信息:OV=0时,和仍在[R0]中,OV=1时,溢出。

影响资源:PSW、A、B、R2~R7、位PFA、PFB 堆栈需求: 6字节

FADD: CLR F0 ;设立加法标志

SJMP AS ;计算代数和

(3) 标号: FSUB 功能:浮点数减法

入口条件:被减数在[R0]中,减数在[R1]中。

出口信息:OV=0时,差仍在[R0]中,OV=1时,溢出。

影响资源:PSW、A、B、R2~R7、位PFA、PFB 堆栈需求:6字节

FSUB: SETB F0 ;设立减法标志

AS: LCALL MVR1 ;计算代数和。先将[R1]传送到第二工作区

MOV C,F0 ;用加减标志来校正第二 *** 作数的有效符号

RRC A

XRL A,@R1

MOV C,ACC7

ASN: MOV PFB,C ;将第二 *** 作数的有效符号存入位PFB中

XRL A,@R0 ;与第一 *** 作数的符号比较

RLC A

MOV F0,C ;保存比较结果

LCALL MVR0 ;将[R0]传送到第一工作区中

LCALL AS1 ;在工作寄存器中完成代数运算

MOV0: INC R0 ;将结果传回到[R0]中的子程序入口

INC R0

MOV A,R4 ;传回尾数的低字节

MOV @R0,A

DEC R0

MOV A,R3 ;传回尾数的高字节

MOV @R0,A

DEC R0

MOV A,R2 ;取结果的阶码

MOV C,PFA ;取结果的数符

MOV ACC7,C ;拼入阶码中

MOV @R0,A

CLR ACC7 ;不考虑数符

CLR OV ;清除溢出标志

CJNE A,#3FH,MV01;阶码是否上溢?

SETB OV ;设立溢出标志

MV01: MOV A,@R0 ;取出带数符的阶码

RET

MVR0: MOV A,@R0 ;将[R0]传送到第一工作区中的子程序

MOV C,ACC7 ;将数符保存在位PFA中

MOV PFA,C

MOV C,ACC6 ;将阶码扩充为8bit补码

MOV ACC7,C

MOV R2,A ;存放在R2中

INC R0

MOV A,@R0 ;将尾数高字节存放在R3中

MOV R3,A

INC R0

MOV A,@R0 ;将尾数低字节存放在R4中

MOV R4,A

DEC R0 ;恢复数据指针

DEC R0

RET

MVR1: MOV A,@R1 ;将[R1]传送到第二工作区中的子程序

MOV C,ACC7 ;将数符保存在位PFB中

MOV PFB,C

MOV C,ACC6 ;将阶码扩充为8bit补码

MOV ACC7,C

MOV R5,A ;存放在R5中

INC R1

MOV A,@R1 ;将尾数高字节存放在R6中

MOV R6,A

INC R1

MOV A,@R1 ;将尾数低字节存放在R7中

MOV R7,A

DEC R1 ;恢复数据指针

DEC R1

RET

AS1: MOV A,R6 ;读取第二 *** 作数尾数高字节

ORL A,R7

JZ AS2 ;第二 *** 作数为零,不必运算

MOV A,R3 ;读取第一 *** 作数尾数高字节

ORL A,R4

JNZ EQ1

MOV A,R6 ;第一 *** 作数为零,结果以第二 *** 作数为准

MOV R3,A

MOV A,R7

MOV R4,A

MOV A,R5

MOV R2,A

MOV C,PFB

MOV PFA,C

AS2: RET

EQ1: MOV A,R2 ;对阶,比较两个 *** 作数的阶码

XRL A,R5

JZ AS4 ;阶码相同,对阶结束

JB ACC7,EQ3 ;阶符互异

MOV A,R2 ;阶符相同,比较大小

CLR C

SUBB A,R5

JC EQ4

EQ2: CLR C ;第二 *** 作数右规一次

MOV A,R6 ;尾数缩小一半

RRC A

MOV R6,A

MOV A,R7

RRC A

MOV R7,A

INC R5 ;阶码加一

ORL A,R6 ;尾数为零否?

JNZ EQ1 ;尾数不为零,继续对阶

MOV A,R2 ;尾数为零,提前结束对阶

MOV R5,A

SJMP AS4

EQ3: MOV A,R2 ;判断第一 *** 作数阶符

JNB ACC7,EQ2 ;如为正,右规第二 *** 作数

EQ4: CLR C

LCALL RR1 ;第一 *** 作数右规一次

ORL A,R3 ;尾数为零否?

JNZ EQ1 ;不为零,继续对阶

MOV A,R5 ;尾数为零,提前结束对阶

MOV R2,A

AS4: JB F0,AS5 ;尾数加减判断

MOV A,R4 ;尾数相加

ADD A,R7

MOV R4,A

MOV A,R3

ADDC A,R6

MOV R3,A

JNC AS2

LJMP RR1 ;有进位,右规一次

AS5: CLR C ;比较绝对值大小

MOV A,R4

SUBB A,R7

MOV B,A

MOV A,R3

SUBB A,R6

JC AS6

MOV R4,B ;第一尾数减第二尾数

MOV R3,A

LJMP RLN ;结果规格化

AS6: CPL PFA ;结果的符号与第一 *** 作数相反

CLR C ;结果的绝对值为第二尾数减第一尾数

MOV A,R7

SUBB A,R4

MOV R4,A

MOV A,R6

SUBB A,R3

MOV R3,A

RLN: MOV A,R3 ;浮点数规格化

ORL A,R4 ;尾数为零否?

JNZ RLN1

MOV R2,#0C1H ;阶码取最小值

RET

RLN1: MOV A,R3

JB ACC7,RLN2 ;尾数最高位为一否?

CLR C ;不为一,左规一次

LCALL RL1

SJMP RLN ;继续判断

RLN2: CLR OV ;规格化结束

RET

RL1: MOV A,R4 ;第一 *** 作数左规一次

RLC A ;尾数扩大一倍

MOV R4,A

MOV A,R3

RLC A

MOV R3,A

DEC R2 ;阶码减一

CJNE R2,#0C0H,RL1E;阶码下溢否?

CLR A

MOV R3,A ;阶码下溢, *** 作数以零计

MOV R4,A

MOV R2,#0C1H

RL1E: CLR OV

RET

RR1: MOV A,R3 ;第一 *** 作数右规一次

RRC A ;尾数缩小一半

MOV R3,A

MOV A,R4

RRC A

MOV R4,A

INC R2 ;阶码加一

CLR OV ;清溢出标志

CJNE R2,#40H,RR1E;阶码上溢否?

MOV R2,#3FH ;阶码溢出

SETB OV

RR1E: RET

#include<reg52>

#define uchar unsigned char

#define uint unsigned int

sbit K1 = P1^4;

sbit K2 = P1^5;

uchar data K1state;

uchar data K2state;

uint  data num,ntmp;

uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x06f,0x77,0x7c,0x39,0x5e,0x79,0x71} ;

uchar data showIndex,indexTmp;

uchar data  W[8];

void delay(uint z)

{

    uint x,y;

    for(x=z;x>0;x--)

        for(y=110;y>0;y--);//能使之延时接近1毫秒就成 无需精确

}

void main()

{

  K1state = 0xFF;

  K2state = 0xFF;

  num = 0;

  while(1)

  {

    delay(1);//每毫秒轮询一回

    //移位法,延时防抖

    K1state = (K1state<<1);

    K2state = (K2state<<1);

    if(K1) K1state++;

    if(K2) K2state++;

    //检查开关状态

    if(K1state==0x80) num++;

    if(K2state==0x80) num--;

    for(indexTmp=0,ntmp = num;indexTmp<=7;indexTmp++)

    {

      W[indexTmp] = num%10;

      num /=10;

    }

    P0 = (0x01<<showIndex);//位选

    P2 = table[W[showIndex]];//段选

    showIndex++;

    if(showIndex>=8)

      showIndex=0;

  }

}

看了你的全图,修改后了,用Keil uVision 3或4都可以,编译后可以查看对应的汇编代码

程序稍大一点的,不会有人用汇编来给你蘑菇,汇编设计写编码太慢了,开发代价不值得

#include <reg52h>

//P0是数码管。P1是LEDP2是按键

sbit KEY_OUT_1 = P2^3;

sbit KEY_OUT_2 = P2^2;

sbit KEY_OUT_3 = P2^1;

sbit KEY_OUT_4 = P2^0;

#define uchar unsigned char

#define ulint unsigned long

#define Frequency 10//定时器中断时间 = fT

#define Time 1//一个周期1ms

#define TubeNumber 6//数码管个数

#define KeyLine 4//矩阵按键行数

#define KeyColumn 4//矩阵按键列数

//数码管真值表

uchar code LED_Number[]={0x0C,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};

//uchar code LED_Alphabet[]={0x88,0x83,0xC6,0xA1,0x86,0x8E,0x89,0xC7,0x8C,0xC1,0x91,0x9C};

/0~9

A~F (b 、d为小写) H L P U y o /

uchar LED_Buff[TubeNumber]={0xff,0xff,0xff,0xff,0xff,0xff};

/数码管显示缓冲区,0xff确保初始时都不亮

不可写成uchar code LED_Buff[]。code定义变量写入room,不可修改/

// 矩阵按键编号到标准盘码的映射表

uchar code KeyCodeMap[4][4] = {

( 0x31, 0x32, 0x33, 0x26 ), // 数字键 1、数字键 2、数字键 3、向上键

( 0x34, 0x35, 0x36, 0x25 ), // 数字键 4、数字键 5、数字键 6、向左键

( 0x37, 0x38, 0x39, 0x28 ), // 数字键 7、数字键 8、数字键 9、向下键

( 0x30, 0x1B, 0x0D, 0x27 )}; // 数字键 0、ESC 键 、回车键 、向右键

uchar StaFlag[KeyLine][KeyColumn] ={(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1)};//按键是否稳定标志

void StartTime0();

void TubeDisplay(ulint sec);

ulint pow(x,y);

void TubeScan();

void KeyAction(uchar keycode);

void KeyDriver();

void KeyScan();

void main ()

{

P1 = 0x08;//使能U3,选择数码管。

StartTime0();

while(1)KeyDriver();

}

//定时器0启动函数

void StartTime0()

{

EA = 1;

ET0 = 1;

TMOD = 0x01;

TH0 = (65536 - Time 100) / 256;

TL0 = (65536 - Time 100) % 256;

PT0 = 1;

/定时器0优先中断控制位。

IP 这个寄存器的每一位,表示对应中断的抢占优先级,每一位的复值都是0,当我们把某一位设置为1的时候,这一位优先级就比其它位的优先级高了。

比如我们设置了 PT0位为1后, 当单片机在主循环或其他中断程序执行时,一旦TO发生中断,作为更高优先级,程序马上执行T0若在T0程序执行时,

其他中断程序发生中断,仍执行TO直到T0中断结束后再执行其他程序。

/

}

//中断服务函数

void To_time0()interrupt 1 using 0

{

static uchar cnt;//记录TO中断次数

// static ulint sec;//记录经过秒速

//判断是否溢出

if (TF0 == 1)

{

TF0 = 0;

TH0 = (65536 - Time 100) / 256;

TL0 = (65536 - Time 100) % 256;

}

if (cnt >= Frequency)

{

cnt = 0;

//sec++;

// Tube_Display(sec);

TubeScan();

KeyScan();

}

}

//数码管显示函数

void TubeDisplay(ulint nom)

{

uchar m = 2;//小数部分位数

uchar i;//传输索引

//秒速达到上限清零

if (nom > pow(10,TubeNumber - m))nom = 0;

//分别传输小数部分和整数部分

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

LED_Buff[i] = LED_Number[nom/pow(10,i)%10];

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

LED_Buff[i+m] = LED_Number[nom/pow(10,i)%10];

//点亮小数点

LED_Buff[m] &= 0x7f;

}

//平方运算函数

ulint pow(x,y)//x为底,为幂

{

ulint p,i = 1;

//平方运算

for(i=1; i<=y; i++)

p=x;

//输出结果

return p;

}

//数码管动态函数

void TubeScan()

{

static uchar i = 0;//动态扫描索引

//关闭所有段选位,数码管消隐

P0 = 0xff;

//for (i=0; i < Tube_number; i++)

P1 = (P1 & 0xf8) | i;//位选索引赋值到P1口低3位

P0 = LED_Buff[i];//缓冲区中的索引位置数据传输到P0口

if (++i >= TubeNumber)i=0;//索引递增循环,遍历整个缓冲区

}

//矩阵按键动作函数

void KeyAction(uchar keycode)

{

static ulint result;

ulint nom = 0;

//输入数字0~9

if ((keycode >= 0x30) && (keycode <= 39))

{

nom = (nom10) + (keycode - 0x30);//十进制整体左移,新数进入各位

TubeDisplay(nom);

}

//输入方向键

if ((keycode >= 0x25) && (keycode <= 28))

switch (keycode)

{

case 0x26:result += nom; nom = 0; TubeDisplay(result);

case 0x28:result -= nom; nom = 0; TubeDisplay(result);

case 0x25:result = 1; result = nom; nom = 0; TubeDisplay(result);

case 0x27:result = 1; result /= nom; nom = 0; TubeDisplay(result);

}

else if (keycode == 0x0d)TubeDisplay(result);//输入回车键,输出最终结果

else if (keycode == 0x1b)//输入ESC键,清零

{

nom = result = 0;

TubeDisplay(nom);

}

}

//矩阵按键驱动函数

void KeyDriver()

{

uchar l,c;

static uchar backup[KeyLine][KeyColumn] = {(1,1,1,1),(1,1,1,1),(1,1,1,1),(1,1,1,1)};//按键值备份,保存前一次值

for(l=0; l<KeyLine; l++)

{

for(c=0; c<KeyColumn; c++)

{

if (backup[l][c] != StaFlag[l][c])

{//检测按键动作

if (backup[l][c] == 1)//按键按下时执行

KeyAction(KeyCodeMap[l][c]);//调用动作函数

backup[l][c] = StaFlag[l][c];//刷新前一次备份值

}

}

}

}

//矩阵按键扫描函数

void KeyScan()

{

uchar l = 0;//矩阵按键扫描输出索引

uchar c = 0;//矩阵按键扫描列索引

uchar keybuff [KeyLine][KeyColumn] = {(0xff,0xff,0xff,0xff),(0xff,0xff,0xff,0xff),

(0xff,0xff,0xff,0xff),(0xff,0xff,0xff,0xff)};//矩阵按键扫描缓冲区

//将一行的四个按键移入缓冲区

for(l=0; l<KeyColumn; l++)

keybuff [l][c] = ((0xfe | (P2 >> (4 + l)) & 0x01));

//按键消抖

for(l=0; l <KeyLine; l++)

{

if((keybuff [l][c] & 0x0f) == 0x00)//连续4次扫描都为0,判断44ms内都是按下状态,可认为按键已稳定按下

StaFlag[l][c] = 0;

else if ((keybuff [l][c] & 0x0f) == 0x0f)//连续4次扫描都为1,判断44ms内都是d起状态,可认为按键已稳定d起

StaFlag[l][c] = 1;

}

for(c=0; c <KeyColumn; c++)

{

switch (c) // 根据索引,释放当前输出脚 拉低下次的根据索引

{

case 0: KEY_OUT_4 = 1; KEY_OUT_1 = 0; break;

case 1: KEY_OUT_1 = 1; KEY_OUT_2 = 0; break;

case 2: KEY_OUT_2 = 1; KEY_OUT_3 = 0; break;

case 3: KEY_OUT_3 = 1; KEY_OUT_4 = 0; break;

default: break;

}

}

}

会加的,减的也就不难了

设置计数器工作模式,然后反复读取计数器的值即可

TMOD=0X05;//定时器0为16位计数模式

TH0=0;

TL0=0;

TR0=1;//启动计数器

while(1)

{

delay_ms(10);//如果液晶显示,可加大延时时间,如果数码管显示,可不要此延时

//但数码管显示程序中间要有驻留延时

a=TH0256+TL0;//读取计数器的值

b=10000-a;//假设减1计数的初值为10000

if (key==0) display(1,0,a);//显示从第一行第一列起

else  display(1,0,b);//也可改成display(2,0,b)

}

液晶显示函数附件里有,可干脆将else去掉,第一行递增显示,第二行递减显示

;R3R2+R7R6=R3R2C

ADD16:

MOV A,R2

ADD A,R6

MOV R2,A

MOV A,R3

ADDC A,R7

MOV R3,A

RET

;R3R2-R7R6=R3R2C

SUBB16:

CLR C

MOV A,R2

SUBB A,R6

MOV R2,A

MOV A,R3

SUBB A,R7

MOV R3,A

RET

;(R3R4R6R7)=(R5R2R3R4)

NMUL22 : MOV A,R4

MOV B,R7

MUL AB

XCH A,R4

MOV R5,B

MOV B,R6

MUL AB

ADD A,R5

MOV R5,A

CLR A

ADDC A,B

MOV R2,A

MOV A,R3

MOV B,R7

MUL AB

ADD A,R5

MOV R5,A

MOV A,B

ADDC A,R2

MOV R2,A

CLR A

ADDC A,#00H

XCH A,R3

MOV B,R6

MUL AB

ADD A,R2

MOV R2,A

MOV A,B

ADDC A,R3

XCH A,R5

MOV R3,A

CLR OV

RET

是主函数出了问题,你的键盘扫描程序是有返回值的函数,返回的值是指函数的运算结果,不是对于keycounts这个变量的,所以你需要把主函数改成

while (1)

{

uchar m;

m=keyscan();

bai=m/100;

shi=m/10%10;

ge=m%10;

display(bai,shi,ge);

}

再有就是楼上说的问题了,松手检测while(temp!=0xff);处

应该加显示函数,不加也能运行,但是按下按键时,没有显示,造成显示一闪一闪的,

再有,函数返回 return keycounts;之后

,就不再向下运行了,所以,最后一句 P3=0xff;

是白写的,根本不会执行。

另外呢,写程序要慢慢练,一句一句的弄懂,看别人写一遍之后,自己再写一遍,不要怕错,错了才更懂,我刚学的时候写一个时钟程序,写了一周,除了上课时间,一天只吃一顿饭的写(当时老师逼得紧),后来写了560行,结果老师说太长了,就没看,然后我看别人写的,再看自己写的,的确很烂,但还是让我受益匪浅的,后来慢慢的练一下,就把程序缩短了。

你练久了就会发现,上面的显示函数,可以用一个for循环和一个数组就完成的

,不用一个一个的写,关键是不要怕错,多练就好。

我也才学几个月,上面是我的一点建议,希望对你有所帮助

以上就是关于求一单片机(C51)的简易计算器程序,能实现加减乘除。全部的内容,包括:求一单片机(C51)的简易计算器程序,能实现加减乘除。、如何用AT89c51单片机实现浮点数的加减(带进位的)。谢谢了、单片机 一个按钮设置按一下加1 另一个按键按一下减1 求帮忙编写程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

原文地址:https://54852.com/zz/9521854.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存