找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 6406|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

單片機(jī)制作計算器匯編程序

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:83710 發(fā)表于 2015-6-24 21:08 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
                                                                                                 矩陣鍵盤接p1口1602液晶控制p2.0-2.2 液晶數(shù)據(jù)p0 *
;0-99之間的加、減、乘、除運(yùn)算       *
; 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       ;輸入被加(減、乘、除)數(shù)
           RES_L  EQU  25H       ;輸入加(減、乘、除)數(shù)
           OUT_H  EQU  26H       ;運(yùn)算結(jié)果高位
           OUT_L  EQU  27H       ;運(yùn)算結(jié)果低位
;-------------------------------
           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             ;送被(加、減、乘、除)數(shù)
           JNB  20H.0,LOOP          ;鍵標(biāo)記
           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              ;是,轉(zhuǎn)LOOP_2
           MOV  TEMP1,TEMP2
           MOV  A,TEMP1
           MOV  X,#1
           CALL  CONV0
           MOV  A,R3                ;恢復(fù)有效鍵值
           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        ;加運(yùn)算
           CALL  CONV1
           SETB  20H.1               ;加運(yùn)算標(biāo)記
           AJMP  LOOP5
LOOP1:     CJNE  A,#0BH,LOOP2        ;減運(yùn)算
           CALL  CONV2
           SETB  20H.2               ;減運(yùn)算標(biāo)記
           AJMP  LOOP5
LOOP2:     CJNE  A,#0CH,LOOP3        ;乘運(yùn)算
           CALL  CONV3
           SETB  20H.3               ;乘運(yùn)算標(biāo)記
           AJMP  LOOP5
LOOP3:     CJNE  A,#0DH,LOOP4        ;除運(yùn)算
           CALL  CONV4
           SETB  20H.4               ;除運(yùn)算標(biāo)記
           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                ;送(加、減、乘、除)數(shù)
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              ;是,轉(zhuǎn)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            ;顯示運(yùn)算結(jié)果
           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        ;復(fù)位(清零)
           AJMP  MAIN
;------------------------
;加法運(yùn)算子程序
;入口:R0-被加數(shù),R1-加數(shù)
;出口: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
;------------------------
;減法運(yùn)算子程序
;入口:R0-被減數(shù),R1-減數(shù)
;出口:R2-差值
;------------------------
SUSUB:
          MOV  R1,RES_L
          MOV  R0,RES_H
          CLR  C
          MOV  A,#9AH
          SUBB  A,R1        ;減數(shù)十進(jìn)制求補(bǔ)
          ADD  A,R0
          DA  A
          MOV  R2,A         ;差值送R2
          JC  POSI          ;C=1,表示差值為正
NEGA:    MOV  A,#9AH       ;差值為負(fù),求補(bǔ)后得差值的絕對值
          SUBB  A,R2
          MOV  R2,A
          SETB  20H.5       ;顯示負(fù)號標(biāo)記
POSI:    MOV  OUT_H,#00H
          MOV  OUT_L,R2
          CALL  T_CONV
          RET
;-------------------------
;乘法運(yùn)算子程序
; 單字節(jié)BCD碼乘法子程序
;入口: R0(被乘數(shù))、R1(乘數(shù))
;出口: R3(高)、R2(低),積為雙字節(jié),BCD碼形式的積
;從乘數(shù)高位開始進(jìn)行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        ;取乘數(shù)高位
            JZ  LBCD            ;乘數(shù)高位是否為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            ;取乘數(shù)低位
            ANL  A,#0FH
            JZ  RETURN           ;乘數(shù)低位是否為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
;------------------------------------------------
;除法運(yùn)算子程序
;單字節(jié)BCD碼除法
;入口:R0(被除數(shù))、R1(非零除數(shù))
;出口:R2(商)、R3(余數(shù))
;《MCS-51系列單片機(jī)實(shí)用子程序集錦》Page 73
;-----------------------------------------------
SUDIV:
              MOV  R1,RES_L
              MOV  R0,RES_H
BCDDIV:
              MOV  R2,#00H       ;商單元清零
              MOV  A,R1          ;除數(shù)求補(bǔ)
              CPL  A
              ADD  A,#9BH
              MOV  R1,A
              MOV  A,R0           ;被除數(shù)高位移入
              ANL  A,#0F0H        ;部分余單元
              SWAP  A
   LP0:       MOV  R3,A           ;做除法
              ADD  A,R1
              DA  A
              JNC  LP1            ;部分余數(shù)>=除數(shù)?
              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 初始化設(shè)置
;-----------------------------------------------------
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點(diǎn)陣
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H      ;雙列顯示,字形5*7點(diǎn)陣
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#38H      ;雙列顯示,字形5*7點(diǎn)陣
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#0CH      ;開顯示,關(guān)光標(biāo),
          CALL  WCOM
          CALL  DELAY1
          MOV  A,#01H      ;清除 LCD 顯示屏
          CALL  WCOM
          CALL  DELAY1
          RET
;----------------------------------------------------
LCD_SHOW:             ;在LCD的第一行或第二行顯示信息字符          CJNE  A,#1,LINE2   ;判斷是否為第一行
  LINE1:  MOV  A,#80H        ;設(shè)置 LCD 的第一行地址
          CALL  WCOM         ;寫入命令
          CALL  CLR_LINE     ;清除該行字符數(shù)據(jù)
          MOV  A,#80H        ;設(shè)置 LCD 的第一行地址
          CALL  WCOM         ;寫入命令
          JMP  FILL
  LINE2:  MOV  A,#0C0H       ;設(shè)置 LCD 的第二行地址
          CALL  WCOM         ;寫入命令
          CALL  CLR_LINE     ;清除該行字符數(shù)據(jù)
          MOV  A,#0C0H       ;設(shè)置 LCD 的第二行地址
          CALL  WCOM
  FILL:   CLR  A             ;填入字符
          MOVC  A,@A+DPTR    ;由信息區(qū)取出字符
          CJNE  A,#0,LC1     ;判斷是否為結(jié)束碼
          RET
  LC1:    CALL  WDATA        ;寫入數(shù)據(jù)
          INC  DPTR          ;指針加1
          JMP  FILL          ;繼續(xù)填入字符
          RET
;---------------------------------------------------
CLR_LINE:                    ;清除該行 LCD 的字符
          MOV  R0,#24
   CL1:   MOV  A,#' '
          CALL  WDATA
          DJNZ  R0,CL1
          RET
;-----------------------------------------------------
; 寫指令、數(shù)據(jù)使能子程序
;-----------------------------------------------------
WCOM:                       ;寫指令使能
          MOV  P0,A
          CLR RS            ;RS=L,RW=L,D0-D7=指令碼,E=高脈沖
          CLR RW
          SETB EN
          CALL  DELAY0
          CLR EN
          RET
WDATA:                      ;寫數(shù)據(jù)使能
          MOV  P0,A
          SETB  RS          ;RS=H,RW=L,D0-D7=數(shù)據(jù),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          ;設(shè)置顯示地址
         ADD  A,#0C0H      ;設(shè)置LCD的第二行地址
         CALL  WCOM        ;寫入命令
         POP  ACC          ;由堆棧取出A
         CALL  WDATA       ;寫入數(shù)據(jù)
         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  ;末完,繼續(xù)查
           RET                    ;0FFH為結(jié)束碼
;------------------------
;在指定位置顯示符合子程序
;------------------------
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       ;取出低四位二進(jìn)制數(shù)
          PUSH  ACC           ;壓入堆棧
          CLR   C             ;C=0
          SUBB  A,#0AH        ;減10
          POP   ACC           ;彈出堆棧
          JC    ASCII0        ;該數(shù)小于10,轉(zhuǎn)ASCII0
          JMP  ASCII1

ASCII0:   ADD   A,#30H        ;小于10的數(shù)加上30H
          MOV   B,X
          CALL  LCDP2
ASCII1:   
          RET
;-------------------------------------------------------
T_CONV:
          MOV   A,OUT_H          ;取高位數(shù)
          mov  x,#11
          cjne  a,#00h,t_conv1   ;判高位數(shù)是否為0?
          setb  20h.6            ;為0,20h.6置1
          jmp  t_conv3           ;轉(zhuǎn)取低位數(shù)
                                 ;高位數(shù)不為0,則
t_conv1:  anl a,#0f0h            ;判高位數(shù)的高四位是否為0?
          cjne  a,#00h,t_conv2   ;不為0,2位數(shù)都顯示
          setb  20h.6            ;為0,20h.6置1,只顯示低四位
t_conv2:  mov  a,out_h
          CALL  SHOW_DIG2
          inc  x
          clr  20h.6             ;清顯示標(biāo)記位
t_conv3:  mov  a,out_l           ;取低位數(shù)
          jnb  20h.6,t_conv5     ;高位數(shù)有顯示,則不判低位數(shù)。
          anl  a,#0f0h           ;高位數(shù)無顯示,則判低位數(shù)。
          cjne  a,#00h,t_conv4   ;判低位數(shù)的高四位是否為0?
          setb  20h.6            ;為0,20h.6置1,只顯示低四位
          MOV  A,OUT_L
          JMP  T_CONV5
T_conv4:  CLR  20H.6             ;低位數(shù)不為0,2位數(shù)都顯示
          mov  a,out_l
t_conv5:  call  show_dig2
          clr  20h.6            ;清顯示標(biāo)記位
          RET
;----------------------------
;在 LCD 的第二行顯示數(shù)字與符號
;----------------------------
SHOW_DIG2:
          JNB  20H.5,DIG2    ;符號標(biāo)記
          MOV  TEMP3,A
          MOV  A,#2DH        ;顯示負(fù)號
          MOV  B,X
          CALL  LCDP2
          MOV  A,TEMP3
          INC  X
DIG2:    MOV  B,#16         ;設(shè)置被除數(shù)
          DIV  AB            ;結(jié)果A存商數(shù),B存余數(shù)
          jnb  20h.6,dig3    ;顯示位標(biāo)記
          mov  a,#20h
          jmp  dig4
dig3:     ADD  A,#30H        ;A為十位數(shù),轉(zhuǎn)換為字符
dig4:     PUSH  B            ;B放入堆棧暫存
          MOV  B,X           ;設(shè)置 LCD 顯示的位置
          CALL  LCDP2        ;由 LCD 顯示出來
          POP  B             ;
          MOV  A,B           ;B為個位數(shù)
          ADD  A,#30H        ;轉(zhuǎn)換為字符
          INC  X             ;LCD 顯示位置加1
          MOV  B,X           ;設(shè)置 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 分享淘帖 頂 踩
回復(fù)

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表