找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 6369|回复: 0
打印 上一主题 下一主题
收起左侧

单片机制作计算器汇编程序

[复制链接]
跳转到指定楼层
楼主
ID:83710 发表于 2015-6-24 21:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
                                                                                                 矩阵键盘接p1口1602液晶控制p2.0-2.2 液晶数据p0 *
;0-99之间的加、减、乘、除运算       *
; 0a键+   0b键-   0c键*     0#键/  0#键清除  00键 等于             *
;矩阵键盘定义:         *
;P1.0-P1.3为列线,P1.4-P1.7为行线      *
;出口:A、R3存键值        *                    
           RELAY  EQU  P1.3
           BEEP   EQU  P3.7
;-------------------------------
           RS    EQU  P2.0
           RW    EQU  P2.1
           EN    EQU  P2.2
           X     EQU  3fH        ;LCD 地址变量
;-------------------------------
           TEMP1  EQU  30H       ;临时暂存器
           TEMP2  EQU  31H
           TEMP3  EQU  32H
           TEMP4  EQU  33H
           RES_H  EQU  24H       ;输入被加(减、乘、除)数
           RES_L  EQU  25H       ;输入加(减、乘、除)数
           OUT_H  EQU  26H       ;运算结果高位
           OUT_L  EQU  27H       ;运算结果低位
;-------------------------------
           ORG  0000H
           JMP  MAIN
;-------------------------------
MAIN:      MOV  SP,#60H
           CLR   EN
           CALL  SET_LCD
           MOV  20H,#00H
           CALL  BEEP_BL            ;起延时作用
           MOV  R1,#00H
           MOV  TEMP1,#00H
           MOV  TEMP2,#00H
           MOV  TEMP3,#00H
           MOV  RES_L,#00H
           MOV  RES_H,#00H
           MOV  OUT_H,#00H
           MOV  OUT_L,#00H
LOOP:
           CALL  KEY_IN             ;送被(加、减、乘、除)数
           JNB  20H.0,LOOP          ;键标记
           CALL  BEEP_BL
           INC  R1
           CJNE  R1,#01H,LOOP_1         
           MOV  TEMP2,A             ;高位
           MOV  X,#2
           CALL  CONV0
LOOP_1:    CJNE  R1,#02H,LOOP
           SUBB  A,#0AH             ;判是否是功能键?
           JNC  LOOP_2              ;是,转LOOP_2
           MOV  TEMP1,TEMP2
           MOV  A,TEMP1
           MOV  X,#1
           CALL  CONV0
           MOV  A,R3                ;恢复有效键值
           MOV  TEMP2,A             ;低位
           MOV  X,#2
           CALL  CONV0
           MOV  A,TEMP1
           ANL  A,#0FH
           SWAP  A
           ORL  A,TEMP2
           MOV  RES_H,A
           JMP  LOOP0
LOOP_2:
           MOV  RES_H,TEMP2
           AJMP  LOOP0A
LOOP0:     CALL  KEY_IN
           JNB  20H.0,LOOP0
           CALL  BEEP_BL
LOOP0A:    MOV  A,R3                 ;重装键值
           CJNE  A,#0AH,LOOP1        ;加运算
           CALL  CONV1
           SETB  20H.1               ;加运算标记
           AJMP  LOOP5
LOOP1:     CJNE  A,#0BH,LOOP2        ;减运算
           CALL  CONV2
           SETB  20H.2               ;减运算标记
           AJMP  LOOP5
LOOP2:     CJNE  A,#0CH,LOOP3        ;乘运算
           CALL  CONV3
           SETB  20H.3               ;乘运算标记
           AJMP  LOOP5
LOOP3:     CJNE  A,#0DH,LOOP4        ;除运算
           CALL  CONV4
           SETB  20H.4               ;除运算标记
           AJMP  LOOP5
LOOP4:     CJNE  A,#0FH,LOOP4A
           AJMP  MAIN         
LOOP4A:    AJMP  LOOP0
LOOP5:     MOV  R1,#00H
           MOV  TEMP1,#00H
           MOV  TEMP2,#00H
           CLR  20H.0                ;送(加、减、乘、除)数
LOOP5A:    CALL  KEY_IN
           JNB  20H.0,LOOP5A
           CALL  BEEP_BL           
           CJNE  A,#0FH,LOOP5B
           AJMP  MAIN
LOOP5B:    INC  R1
           CJNE  R1,#01H,LOOP5C
           MOV  TEMP2,A
           MOV  X,#6
           CALL  CONV0
LOOP5C:    CJNE  R1,#02H,LOOP5A
           SUBB  A,#0AH             ;判是否是功能键?
           JNC  LOOP5D              ;是,转LOOP5C
           MOV  TEMP1,TEMP2
           MOV  A,TEMP1
           MOV  X,#6
           CALL  CONV0
           MOV  A,R3
           MOV  TEMP2,A
           MOV  X,#7
           CALL  CONV0
           MOV  A,TEMP1
           ANL  A,#0FH
           SWAP  A
           ORL  A,TEMP2
           MOV  RES_L,A
           JMP  LOOP6
LOOP5D:    MOV  RES_L,TEMP2
           JMP  LOOP6A
LOOP6:     CALL  KEY_IN
LOOP6A:    MOV  A,R3                ;重装键值
           CJNE  A,#0FH,LOOP6B
           AJMP  MAIN
LOOP6B:    CJNE  A,#0EH,LOOP6       ;显示(=)
           CALL  CONV5
           CALL  BEEP_BL            ;显示运算结果
           JNB  20H.1,LOOP6C
           CALL  SUADD
LOOP6C:    JNB  20H.2,LOOP6D
           CALL  SUSUB
LOOP6D:    JNB  20H.3,LOOP6E
           CALL  SUMUL
LOOP6E:    JNB  20H.4,LOOP7
           CALL  SUDIV
LOOP7:     CALL  KEY_IN
           CJNE  A,#0FH,LOOP7        ;复位(清零)
           AJMP  MAIN
;------------------------
;加法运算子程序
;入口:R0-被加数,R1-加数
;出口:R4(高)、R2(低)为和值
;------------------------
SUADD:
           MOV  R1,RES_L
           MOV  R0,RES_H
           MOV  A,R0
           ADD  A,R1
           DA  A
           MOV  R2,A
           CLR  A
           ADDC  A,#00H
           MOV  R4,A
           MOV  OUT_H,R4
           MOV  OUT_L,R2
           CALL T_CONV
           RET
;------------------------
;减法运算子程序
;入口:R0-被减数,R1-减数
;出口:R2-差值
;------------------------
SUSUB:
          MOV  R1,RES_L
          MOV  R0,RES_H
          CLR  C
          MOV  A,#9AH
          SUBB  A,R1        ;减数十进制求补
          ADD  A,R0
          DA  A
          MOV  R2,A         ;差值送R2
          JC  POSI          ;C=1,表示差值为正
NEGA:    MOV  A,#9AH       ;差值为负,求补后得差值的绝对值
          SUBB  A,R2
          MOV  R2,A
          SETB  20H.5       ;显示负号标记
POSI:    MOV  OUT_H,#00H
          MOV  OUT_L,R2
          CALL  T_CONV
          RET
;-------------------------
;乘法运算子程序
; 单字节BCD码乘法子程序
;入口: R0(被乘数)、R1(乘数)
;出口: R3(高)、R2(低),积为双字节,BCD码形式的积
;从乘数高位开始进行BCD码移位乘法
;-------------------------
SUMUL:
            MOV  R1,RES_L
            MOV  R0,RES_H
BCDMUL:
            CLR  A             ;积单元清零
            MOV  R2,A
            MOV  R3,A
            MOV  A,R1
            JZ  RETURN
            ANL  A,#0F0H        ;取乘数高位
            JZ  LBCD            ;乘数高位是否为0?
            SWAP  A
            MOV  R4,A
            ACALL  DDBCDM
            SWAP  A             ;BCD码左移一位
            MOV  R3,A
            MOV  A,R2
            SWAP  A
            MOV  R2,A
            ANL  A,#0FH
            ORL  A,R3
            MOV  R3,A
            MOV  A,R2
            ANL  A,#0F0H
            MOV  R2,A
LBCD:      MOV  A,R1            ;取乘数低位
            ANL  A,#0FH
            JZ  RETURN           ;乘数低位是否为0?
            MOV  R4,A
            ACALL  DDBCDM
RETURN:     MOV  OUT_H,R3
            MOV  OUT_L,R2
            CALL T_CONV
            RET
DDBCDM:                          ;一位BCD码乘法
            MOV  A,R2
            ADD  A,R0
            DA  A
            MOV  R2,A
            MOV  A,R3
            ADDC  A,#00H
            DA  A
            MOV  R3,A
            DJNZ  R4,DDBCDM
            RET
;------------------------------------------------
;除法运算子程序
;单字节BCD码除法
;入口:R0(被除数)、R1(非零除数)
;出口:R2(商)、R3(余数)
;《MCS-51系列单片机实用子程序集锦》Page 73
;-----------------------------------------------
SUDIV:
              MOV  R1,RES_L
              MOV  R0,RES_H
BCDDIV:
              MOV  R2,#00H       ;商单元清零
              MOV  A,R1          ;除数求补
              CPL  A
              ADD  A,#9BH
              MOV  R1,A
              MOV  A,R0           ;被除数高位移入
              ANL  A,#0F0H        ;部分余单元
              SWAP  A
   LP0:       MOV  R3,A           ;做除法
              ADD  A,R1
              DA  A
              JNC  LP1            ;部分余数>=除数?
              INC  R2             ;商加1
              SJMP  LP0
   LP1:       MOV  A,R3           ;
              SWAP  A
              MOV  R3,A
              MOV  A,R2           ;商左移一位
              SWAP  A
              MOV  R2,A
              MOV  A,R0            ;移位
              ANL  A,#0FH
              ORL  A,R3
  LP2:        MOV  R3,A            ;做除法
              ADD  A,R1
              DA  A
              JNC  LP3
              INC  R2              ;商加1
              SJMP  LP2
  LP3:        MOV  A,R3            ;四舍五人
              ADD  A,R3
              DA  A
              JC  LP4
              ADD  A,R1
              DA  A
              JNC  RETURN1
  LP4:        MOV  A,R2
              ADDC  A,#00H
              DA  A
              MOV  R2,A
RETURN1:     MOV  OUT_H,#00H
              MOV  OUT_L,R2
              CALL T_CONV
              RET
;-----------------------------------------------------
;  LCD 初始化设置
;-----------------------------------------------------
SET_LCD:
          CLR  EN
          CALL  INIT_LCD      ;初始化 LCD
          CALL  DELAY1
          MOV  DPTR,#INFO1    ;指针指到显示信息1
          MOV  A,#1           ;显示在第一行
          CALL  LCD_SHOW
          MOV  DPTR,#INFO2    ;指针指到显示信息2
          MOV  A,#2           ;显示在第二行
          CALL  LCD_SHOW
          RET
;-----------------------------------------------------
INFO1:  DB  "   CALCULATOR   ",0  ;LCD 第一行显示信息
INFO2:  DB  "                ",0  ;LCD 第二行显示信息
;----------------------------------------------------
INIT_LCD:                  ;8位I/O控制 LCD 接口初始化
          MOV  A,#38H      ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H      ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H      ;双列显示,字形5*7点阵
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#0CH      ;开显示,关光标,
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#01H      ;清除 LCD 显示屏
          CALL  WCOM
          CALL  DELAY1
          RET
;----------------------------------------------------
LCD_SHOW:             ;在LCD的第一行或第二行显示信息字符          CJNE  A,#1,LINE2   ;判断是否为第一行
  LINE1:  MOV  A,#80H        ;设置 LCD 的第一行地址
          CALL  WCOM         ;写入命令
          CALL  CLR_LINE     ;清除该行字符数据
          MOV  A,#80H        ;设置 LCD 的第一行地址
          CALL  WCOM         ;写入命令
          JMP  FILL
  LINE2:  MOV  A,#0C0H       ;设置 LCD 的第二行地址
          CALL  WCOM         ;写入命令
          CALL  CLR_LINE     ;清除该行字符数据
          MOV  A,#0C0H       ;设置 LCD 的第二行地址
          CALL  WCOM
  FILL:   CLR  A             ;填入字符
          MOVC  A,@A+DPTR    ;由信息区取出字符
          CJNE  A,#0,LC1     ;判断是否为结束码
          RET
  LC1:    CALL  WDATA        ;写入数据
          INC  DPTR          ;指针加1
          JMP  FILL          ;继续填入字符
          RET
;---------------------------------------------------
CLR_LINE:                    ;清除该行 LCD 的字符
          MOV  R0,#24
   CL1:   MOV  A,#' '
          CALL  WDATA
          DJNZ  R0,CL1
          RET
;-----------------------------------------------------
; 写指令、数据使能子程序
;-----------------------------------------------------
WCOM:                       ;写指令使能
          MOV  P0,A
          CLR RS            ;RS=L,RW=L,D0-D7=指令码,E=高脉冲
          CLR RW
          SETB EN
          CALL  DELAY0
          CLR EN
          RET
WDATA:                      ;写数据使能
          MOV  P0,A
          SETB  RS          ;RS=H,RW=L,D0-D7=数据,E=高脉冲
          CLR   RW
          SETB  EN
          CALL  DELAY0
          CLR   EN
          RET
DELAY0:   MOV  R7,#250       ;延时500微秒
          DJNZ  R7,$
          RET
;---------------------------------------------------
;在 LCD 第二行显示字符
;A=ASC DATA, B=LINE X POS
;---------------------------------------------------
LCDP2:                     ;在LCD的第二行显示字符
         PUSH  ACC         ;
         MOV  A,B          ;设置显示地址
         ADD  A,#0C0H      ;设置LCD的第二行地址
         CALL  WCOM        ;写入命令
         POP  ACC          ;由堆栈取出A
         CALL  WDATA       ;写入数据
         RET
;-----------------------------------------------------
;矩阵键盘键值读取子程序
;-----------------------------------------------------
KEY_IN:    MOV  P1,#0F0H          ;置列线为0,行线为1
           MOV  A,P1
           ANL  A,#0F0H
           MOV  B,A
           MOV  P1,#0FH           ;置列线为1,行线为0
           MOV  A,P1
           ANL  A,#0FH
           ORL  A,B               ;高四位与低四位重新组合
           CJNE  A,#0FFH,KEY_IN1  ;0FFH为末按键
           CLR  20H.0
           RET
KEY_IN1:   MOV  B,A
           MOV  DPTR,#KEYTABLE
           MOV  R3,#0FFH
KEY_IN2:   INC  R3
           MOV  A,R3
           MOVC  A,@A+DPTR
           CJNE  A,B,KEY_IN3
           MOV  A,R3              ;找到,取顺序码
           MOV  R5,#08H           ;延时
           CALL  DELAY
           SETB  20H.0
           RET
KEY_IN3:   CJNE  A,#0FFH,KEY_IN2  ;末完,继续查
           RET                    ;0FFH为结束码
;------------------------
;在指定位置显示符合子程序
;------------------------
CONV0:
          add A,#30h
          MOV  B,X
          CALL  LCDP2
          ret
CONV1:
          MOV  X,#4
          MOV  A,#2BH        ;+
          MOV  B,X
          CALL  LCDP2
          RET
CONV2:
          MOV  X,#4
          MOV  A,#2DH        ;-
          MOV  B,X
          CALL  LCDP2
          RET
CONV3:
          MOV  X,#4
          MOV  A,#2AH        ;*
          MOV  B,X
          CALL  LCDP2
          RET
CONV4:
          MOV  X,#4
          MOV  A,#2FH        ;/
          MOV  B,X
          CALL  LCDP2
          RET
CONV5:
          MOV  X,#09H
          MOV  A,#3DH        ;=
          MOV  B,X
          CALL  LCDP2
          RET
;--------------------------
;
;--------------------------
CONV:        
          MOV   A,R3
          ANL   A,#0FH       ;取出低四位二进制数
          PUSH  ACC           ;压入堆栈
          CLR   C             ;C=0
          SUBB  A,#0AH        ;减10
          POP   ACC           ;弹出堆栈
          JC    ASCII0        ;该数小于10,转ASCII0
          JMP  ASCII1

ASCII0:   ADD   A,#30H        ;小于10的数加上30H
          MOV   B,X
          CALL  LCDP2
ASCII1:   
          RET
;-------------------------------------------------------
T_CONV:
          MOV   A,OUT_H          ;取高位数
          mov  x,#11
          cjne  a,#00h,t_conv1   ;判高位数是否为0?
          setb  20h.6            ;为0,20h.6置1
          jmp  t_conv3           ;转取低位数
                                 ;高位数不为0,则
t_conv1:  anl a,#0f0h            ;判高位数的高四位是否为0?
          cjne  a,#00h,t_conv2   ;不为0,2位数都显示
          setb  20h.6            ;为0,20h.6置1,只显示低四位
t_conv2:  mov  a,out_h
          CALL  SHOW_DIG2
          inc  x
          clr  20h.6             ;清显示标记位
t_conv3:  mov  a,out_l           ;取低位数
          jnb  20h.6,t_conv5     ;高位数有显示,则不判低位数。
          anl  a,#0f0h           ;高位数无显示,则判低位数。
          cjne  a,#00h,t_conv4   ;判低位数的高四位是否为0?
          setb  20h.6            ;为0,20h.6置1,只显示低四位
          MOV  A,OUT_L
          JMP  T_CONV5
T_conv4:  CLR  20H.6             ;低位数不为0,2位数都显示
          mov  a,out_l
t_conv5:  call  show_dig2
          clr  20h.6            ;清显示标记位
          RET
;----------------------------
;在 LCD 的第二行显示数字与符号
;----------------------------
SHOW_DIG2:
          JNB  20H.5,DIG2    ;符号标记
          MOV  TEMP3,A
          MOV  A,#2DH        ;显示负号
          MOV  B,X
          CALL  LCDP2
          MOV  A,TEMP3
          INC  X
DIG2:    MOV  B,#16         ;设置被除数
          DIV  AB            ;结果A存商数,B存余数
          jnb  20h.6,dig3    ;显示位标记
          mov  a,#20h
          jmp  dig4
dig3:     ADD  A,#30H        ;A为十位数,转换为字符
dig4:     PUSH  B            ;B放入堆栈暂存
          MOV  B,X           ;设置 LCD 显示的位置
          CALL  LCDP2        ;由 LCD 显示出来
          POP  B             ;
          MOV  A,B           ;B为个位数
          ADD  A,#30H        ;转换为字符
          INC  X             ;LCD 显示位置加1
          MOV  B,X           ;设置 LCD 显示的位置
          CALL  LCDP2        ;由 LCD 显示出来
          RET
;--------------------------------------------------------
;蜂鸣器响一声子程序
;--------------------------------------------------------
BEEP_BL:
         MOV  R6,#100
  BL1:   CALL  DEX1
         CPL  BEEP
         DJNZ  R6,BL1
         MOV  R5,#50
         CALL  DELAY
         RET
DEX1:   MOV  R7,#180
DEX2:   NOP
         DJNZ  R7,DEX2
         RET
DELAY:                     ;延时R5×10MS
         MOV  R6,#50
  D1:    MOV  R7,#100
         DJNZ  R7,$
         DJNZ  R6,D1
         DJNZ  R5,DELAY
         RET
;-----------------------------------------------------
DELAY1:                     ;延时5MS
         MOV  R6,#25
  D2:    MOV  R7,#100
         DJNZ  R7,$
         DJNZ  R6,D2
         RET
;-----------------------------------------------------
KEYTABLE:
DB 0eeH ,077H,0B7H,0D7H,07bh,0bbh,0dbh ,07dh,0bdh,0ddh,0e7h,0ebh,0edh, 07eh,0beh,0deh,0ffH
;-----------------------------------------------------
    END                                                                                                                    
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表