站內搜尋

2008/8/26

8051 組語 - 利用keypad及LCD完成的簡單的減乘除運算

大約十年前,在台中勤益就讀的時後,修了 8051 的組合語言。
這也是我那時 Implement 的作業之一,雖然沒有什麼特別了不起的功能,
但沒想到當時為了讓同學看得懂,寫了不少的註解,現在看到真是有一種懷念的感覺。

一直以來,我對於自己曾經寫過的程式都沒有什麼保存的概念。
直到我找工作被狂打槍之後,才了解到作品的重要性。
雖然已經很多東西找不到了,但還是找到了些有趣的東西。
這是當年在學習 8051 時寫的一個作品,也因為組語這種東西不是人人都覺得它可愛,
所以這支程式也可以是說寫出來送全班用的,所以裡面註解的很詳細。
現在看來,也許已經沒什麼價值了,但也許還是能幫助到一些人,就貼上來吧。 \
四則運算處理器:

; 設計理念 ; 20H ~ 23H 為LCD顯示之值      
; 24H ~ 27H 為顯示暫存       
; 28H 為功能 Flag 
D1 EQU 0F9H      
D2 EQU 24H       
D3 EQU 30H       
D4 EQU 19H       
D5 EQU 12H       
D6 EQU 03H       
D7 EQU 78H       
D8 EQU 00H       
D9 EQU 18H       
D0 EQU 40H       
    ORG 0H       
    AJMP RESET       
    ORG 30H       
; 重設整個系統       
RESET:       
    MOV R1,#28H       
    MOV @R1,#0       
    MOV R4,#8       
    CALL CLRX    
; 鍵盤掃描起點       
START:       
    MOV R0,#00H       
    MOV R1,#0F7H       
SCAN:       
    MOV P1,R1       
    MOV A,P1       
    SETB C       
    MOV R2,#4H       
CHECK_KEY: 
    RLC A      
    JNC KEYIN       
    INC R0       
    DJNZ R2,CHECK_KEY       
    MOV A,R1       
    SETB C       
    RRC A       
    MOV R1,A       
    JC SCAN       
    ; 每做一列鍵盤掃描呼叫一次LCD顯示模組       
    CALL DISPLAY       
    AJMP START 
; 鍵盤判斷,利用類似輪詢觀念完成      
KEYIN:       
K0:    CJNE R0,#0,KA       
    MOV R0,#0       
    CALL ADD_NUM    
    AJMP KIN2 
; 設定功能 Flag 為 1 ( 加法 )      
KA:    CJNE R0,#1,KB       
    CALL ACTION       
    MOV R1,#28H       
    MOV @R1,#1H       
    MOV R4,#4       
    CALL CLRX       
    AJMP KIN2 
; 設定功能 Flag 為 2 ( 減法 )      
KB:    CJNE R0,#2,KF       
    CALL ACTION       
    MOV R1,#28H       
    MOV @R1,#2H       
    MOV R4,#4       
    CALL CLRX       
    AJMP KIN2 
; 處理功能 Flag 所指定之工作 ( 等於鍵 )      
KF:    CJNE R0,#3,K1       
    CALL AMOUNT       
    AJMP KIN2 
K1:    CJNE R0,#4,K2      
    MOV R0,#1       
    CALL ADD_NUM       
    AJMP KIN2 
K2:    CJNE R0,#5,K3      
    MOV R0,#2       
    CALL ADD_NUM       
    AJMP KIN2 
K3:    CJNE R0,#6,KE      
    MOV R0,#3       
    CALL ADD_NUM       
    AJMP KIN2 
; 清除鍵      
KE:    CJNE R0,#7,K4       
    AJMP RESET       
    AJMP KIN2       
K4:    CJNE R0,#8,K5       
    MOV R0,#4       
    CALL ADD_NUM       
    AJMP KIN2 
K5:    CJNE R0,#9,K6      
    MOV R0,#5       
    CALL ADD_NUM       
    AJMP KIN2 
K6:    CJNE R0,#10,KD      
    MOV R0,#6       
    CALL ADD_NUM       
    AJMP KIN2       
; 除法       
KD:    CJNE R0,#11,K7       
    CALL ACTION       
    MOV R1,#28H       
    MOV @R1,#4H       
    MOV R4,#4       
    CALL CLRX       
    AJMP KIN2 
K7:    CJNE R0,#12,K8      
    MOV R0,#7       
    CALL ADD_NUM       
    AJMP KIN2 
K8:    CJNE R0,#13,K9      
    MOV R0,#8       
    CALL ADD_NUM       
    AJMP KIN2       
K9:    CJNE R0,#14,KC       
    MOV R0,#9       
    CALL ADD_NUM       
    AJMP KIN2 
; 乘法      
KC:    CJNE R0,#15,KIN2       
    CALL ACTION       
    MOV R1,#28H       
    MOV @R1,#3H       
    MOV R4,#4       
    CALL CLRX       
KIN2:       
    MOV R7,#D0H       
; 做一小型的 delay ,消除按鍵彈跳效應       
DD:    CALL DISPLAY       
    DJNZ R7,DD       
    AJMP START       
;------------------------------------------------------       
;-- IN MEM 28H IS A FLAG, 1 = + , 2 = - , 3 = * , 4 = /       
; 處理功能鍵之指示之功能       
AMOUNT:       
    MOV R1,#28H       
; 加法       
; 利用 20H ~ 23H 中的每個位元加上 24H ~ 27H 的每個位元       
; 由低至高,再利用判斷式確定是否有溢位       
ADD_ACT:       
    CJNE @R1,#1,SUB_ACT       
ADD2:    CLR C       
    MOV R7,#4       
    MOV R1,#20H       
    MOV R0,#24H       
ADD_ACT2:    
    MOV A,@R1       
    MOV R3,A       
    MOV A,@R0       
    ADDC A,R3       
    CLR C       
    MOV R3,A       
    SUBB A,#10       
    JC NO_C       
    SETB C       
    MOV R3,A       
    JMP XXXX       
NO_C:    CPL C       
XXXX:    
    MOV A,R3       
    MOV @R1,A       
    INC R1       
    INC R0       
    DJNZ R7,ADD_ACT2       
    AJMP A_OVER       
; 減法       
; 實作方式類似加法       
SUB_ACT:       
    CJNE @R1,#2,MUL_ACT       
    CLR C       
    MOV R7,#4       
    MOV R1,#20H       
    MOV R0,#24H       
SUB_ACT2:       
    MOV A,@R1       
    MOV R3,A       
    MOV A,@R0       
    SUBB A,R3       
    JNC NO_CY       
    MOV A,@R0       
    ADD A,#10       
    CLR C       
    SUBB A,R3       
    SETB C    
NO_CY:    
    MOV @R1,A       
    INC R1       
    INC R0       
    DJNZ R7,SUB_ACT2       
    AJMP A_OVER       
; 乘法,計算輸入之被乘數之"值"       
; 然後依此值做連加動作       
MUL_ACT:       
    CJNE @R1,#3,DIV_ACT       
    CLR C       
    MOV B,#10       
    MOV A,21H       
    MUL AB       
    ADD A,20H       
    MOV R5,A       
    MOV R4,#4       
    CALL CLRX       
DO_ADD:    
    CALL ADD2       
    DJNZ R5,DO_ADD       
    AJMP A_OVER 
; 除法,將除數及被除數皆運算出其值,利用組語中 div 指令完成      
; 重點部份在於需要將計算出來之數值換算成顯示數值       
DIV_ACT:       
    CJNE @R1,#4,DIV_LAST       
    CLR C       
    MOV B,#10       
    MOV A,21H       
    MUL AB       
    ADD A,20H       
    MOV 28H,A 
    MOV B,#10      
    MOV A,25H       
    MUL AB       
    ADD A,24H       
    MOV B,28H       
    DIV AB       
    MOV 24H,A       
    MOV 25H,B       
    MOV B,#10       
    DIV AB       
    MOV 21H,A       
    MOV 20H,B       
    MOV 28H,#5       
    AJMP A_OVER       
DIV_LAST:    
    CJNE @R1,#5,A_OVER       
    MOV A,25H       
    MOV B,#10       
    DIV AB       
    MOV 21H,A       
    MOV 20H,B       
A_OVER:       
    RET       
;---------------------------       
; 將目前之值推入暫存       
ACTION:       
    MOV R0,#20H       
    MOV R1,#24H       
    MOV R7,#4       
ACT2:       
    MOV A,@R0       
    MOV @R1,A       
    INC R0       
    INC R1       
    DJNZ R7,ACT2       
    RET       
;----------------------       
DISPLAY:       
    MOV R4,#4       
    MOV R1,#20H       
    MOV A,#0FEH       
DISL1:       
    MOV P0,A       
    MOV R0,A       
    MOV A,@R1       
    XCH A,R0       
    RL A       
    INC R1 
    CJNE R0,#0,OUT1      
    MOV P2,#D0       
    AJMP NET 
OUT1:    CJNE R0,#1,OUT2      
    MOV P2,#D1       
    AJMP NET    
OUT2:    CJNE R0,#2,OUT3       
    MOV P2,#D2       
    AJMP NET       
OUT3:    CJNE R0,#3,OUT4       
    MOV P2,#D3       
    AJMP NET       
OUT4:    CJNE R0,#4,OUT5       
    MOV P2,#D4       
    AJMP NET       
OUT5:    CJNE R0,#5,OUT6       
    MOV P2,#D5       
    AJMP NET       
OUT6:    CJNE R0,#6,OUT7       
    MOV P2,#D6       
    AJMP NET       
OUT7:    CJNE R0,#7,OUT8       
    MOV P2,#D7       
    AJMP NET       
OUT8:    CJNE R0,#8,OUT9       
    MOV P2,#D8       
    AJMP NET       
OUT9:    CJNE R0,#9,ERR       
    MOV P2,#D9       
NET:       
    CALL DELAY       
    DJNZ R4,DISL1       
ERR:       
    RET       
;-----------------------------       
; 清除動作       
CLRX:       
    MOV R1,#20H       
CLR1:       
    MOV @R1,#0       
    INC R1       
    DJNZ R4,CLR1       
    RET       
;----------------------------       
DELAY:       
    MOV R5,#03H       
DL1:    MOV R6,#040H       
DL2:    NOP       
    DJNZ R6,DL2       
    DJNZ R5,DL1       
    RET       
;-----------------------------       
; 處理顯示位元之向上推移動作       
ADD_NUM:       
    MOV R7,#04H       
    MOV R1,#20H       
    MOV A,R0       
NUM2:       
    XCH A,@R1       
    INC R1       
    DJNZ R7,NUM2       
    RET       
    END
希望這支程式還是能幫助到剛開始學習 8051 組語的一些朋友。

熱門文章