找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 185|回復(fù): 1
收起左側(cè)

幾個(gè)MCU51單片機(jī)匯編語(yǔ)言設(shè)計(jì)

[復(fù)制鏈接]
ID:1155552 發(fā)表于 2025-6-29 09:57 | 顯示全部樓層 |閱讀模式
系統(tǒng)采用AT89S51,晶振為12MHz,獨(dú)立、依次完成以下設(shè)計(jì)任務(wù):
(1) 利用P1口,設(shè)計(jì)一份含4個(gè)獨(dú)立鍵盤和4個(gè)獨(dú)立發(fā)光二極管的硬件電路圖,并設(shè)計(jì)晶振和復(fù)位電路,正確連接EA引腳。
(2) 設(shè)計(jì)一份(1)電路的鍵盤判斷程序(不含鍵盤消除抖動(dòng)功能),以及自定義功能的發(fā)光二極管顯示程序。
(3) 設(shè)計(jì)一份通過(guò)P3.4口輸出周期為1ms的方波(采用軟件延時(shí)),以及通過(guò)P3.5口輸出周期為1min的方波(采用定時(shí)中斷)程序。
(4) 利用P1口,設(shè)計(jì)4×4行列式鍵盤電路,以及采用74HC164芯片,設(shè)計(jì)通過(guò)串行口連接方式連接4個(gè)7段數(shù)碼管的電路。
(5) 在(4)電路中,設(shè)計(jì)一份鍵盤判斷程序(包含鍵盤軟件消除抖動(dòng)功能)和顯示學(xué)號(hào)后四位程序。
(6) 采用DAC0832設(shè)計(jì)一份D/A轉(zhuǎn)換電路圖,需要設(shè)計(jì)專門的基準(zhǔn)電壓。

led程序:
; 8051 匯編:按鍵(P1.0-P1.3)控制共陰極 LED(P1.4-P1.7)
; 功能:短按點(diǎn)亮對(duì)應(yīng) LED,長(zhǎng)按(超 200ms)切換狀態(tài)(亮/滅)
; 硬件:按鍵接 P1.0-P1.3(按下接地),共陰極 LED 接 P1.4-P1.7(陽(yáng)極串電阻接 P1)

ORG 0000H
    LJMP MAIN

; 延時(shí)消抖(約 20ms@12MHz)
DELAY_20MS:
    MOV R7, #20
DEL1:
    MOV R6, #248
DEL2:
    DJNZ R6, DEL2
    DJNZ R7, DEL1
    RET

; 主程序
MAIN:
    MOV P1, #0FH       ; P1 低四位上拉輸入,高四位初始滅(共陰極 LED 高電平滅)
   
KEY_SCAN:
    ; 檢測(cè) P1.0 按鍵
    MOV A, P1
    ANL A, #01H        ; 屏蔽其他位,取 P1.0
    JNZ CHECK_P11      ; 未按下,跳檢測(cè) P1.1
   
    ACALL DELAY_20MS   ; 消抖
    MOV A, P1
    ANL A, #01H
    JNZ CHECK_P11      ; 抖動(dòng),跳檢測(cè) P1.1
   
    ; 確認(rèn) P1.0 按下:翻轉(zhuǎn) P1.4 狀態(tài)(共陰極 LED 高電平滅、低電平亮)
    CPL P1.4         
   
    ; 等待釋放(長(zhǎng)按不影響其他按鍵,但需等釋放再掃其他鍵)
WAIT_RELEASE0:
    MOV A, P1
    ANL A, #01H
    JZ WAIT_RELEASE0   ; 未釋放則等待
    ACALL DELAY_20MS   ; 釋放消抖
    SJMP CHECK_P11     ; 掃下一個(gè)鍵

CHECK_P11:
    ; 檢測(cè) P1.1 按鍵(邏輯同 P1.0)
    MOV A, P1
    ANL A, #02H
    JNZ CHECK_P12
   
    ACALL DELAY_20MS
    MOV A, P1
    ANL A, #02H
    JNZ CHECK_P12
   
    CPL P1.5         
   
WAIT_RELEASE1:
    MOV A, P1
    ANL A, #02H
    JZ WAIT_RELEASE1
    ACALL DELAY_20MS
    SJMP CHECK_P12

CHECK_P12:
    ; 檢測(cè) P1.2 按鍵(邏輯同 P1.0)
    MOV A, P1
    ANL A, #04H
    JNZ CHECK_P13
   
    ACALL DELAY_20MS
    MOV A, P1
    ANL A, #04H
    JNZ CHECK_P12
   
    CPL P1.6         
   
WAIT_RELEASE2:
    MOV A, P1
    ANL A, #04H
    JZ WAIT_RELEASE2
    ACALL DELAY_20MS
    SJMP CHECK_P13

CHECK_P13:
    ; 檢測(cè) P1.3 按鍵(邏輯同 P1.0)
    MOV A, P1
    ANL A, #08H
    JNZ KEY_SCAN       ; 未按下,回到總掃描
   
    ACALL DELAY_20MS
    MOV A, P1
    ANL A, #08H
    JNZ KEY_SCAN       ; 抖動(dòng),回到總掃描
   
    CPL P1.7         
   
WAIT_RELEASE3:
    MOV A, P1
    ANL A, #08H
    JZ WAIT_RELEASE3
    ACALL DELAY_20MS
    SJMP KEY_SCAN      ; 掃完所有鍵,回到總掃描

END


矩陣鍵盤程序:
;====================================================================
; 4x4矩陣鍵盤掃描與數(shù)碼管顯示程序
; 硬件連接:
;   P1.0-P1.3: 鍵盤行輸出
;   P1.4-P1.7: 鍵盤列輸入
;   P3.2: INT0(前兩列按鍵中斷)
;   P3.3: INT1(后兩列按鍵中斷)
;   P3.1: TXD(串口輸出,驅(qū)動(dòng)數(shù)碼管)
;====================================================================

        ORG     0000H        ; 設(shè)置程序起始地址為0000H(復(fù)位向量)
        LJMP    MAIN        ; 無(wú)條件跳轉(zhuǎn)到主程序MAIN處執(zhí)行

        ORG     0003H        ; 設(shè)置外部中斷0(INT0)向量地址
        LJMP    INT0_HANDLER ; 當(dāng)發(fā)生INT0中斷時(shí),跳轉(zhuǎn)到INT0_HANDLER處理

        ORG     0013H        ; 設(shè)置外部中斷1(INT1)向量地址
        LJMP    INT1_HANDLER ; 當(dāng)發(fā)生INT1中斷時(shí),跳轉(zhuǎn)到INT1_HANDLER處理

;====================================================================
; 主程序
;====================================================================
MAIN:   MOV     SP, #70H      ; 設(shè)置堆棧指針SP為70H(避免覆蓋工作寄存器區(qū))
        MOV     IE, #85H      ; 開(kāi)中斷控制寄存器:
                           ;   EA=1(開(kāi)總中斷),
                           ;   EX0=1(開(kāi)INT0中斷),
                           ;   EX1=1(開(kāi)INT1中斷)
        MOV     TCON, #05H    ; 設(shè)置外部中斷觸發(fā)方式:
                           ;   IT0=1(INT0下降沿觸發(fā)),
                           ;   IT1=1(INT1下降沿觸發(fā))
        MOV     SCON, #00H    ; 配置串口為模式0(同步移位寄存器方式)
        MOV     P1, #0F0H     ; 初始化P1口:
                           ;   P1.0-P1.3(低4位)=0(輸出行掃描信號(hào))
                           ;   P1.4-P1.7(高4位)=1(輸入列檢測(cè)信號(hào))

MAIN_LOOP:
        SJMP    MAIN_LOOP     ; 無(wú)限循環(huán)(所有工作在中斷處理中完成)

;====================================================================
; 前兩列按鍵中斷處理(INT0)
;====================================================================
INT0_HANDLER:
        PUSH    ACC           ; 保護(hù)累加器A的值到堆棧
        PUSH    PSW           ; 保護(hù)程序狀態(tài)字PSW到堆棧
        PUSH    DPH           ; 保護(hù)數(shù)據(jù)指針高8位DPH到堆棧
        PUSH    DPL           ; 保護(hù)數(shù)據(jù)指針低8位DPL到堆棧

        LCALL   DELAY_10MS    ; 調(diào)用延時(shí)子程序消抖(約10ms)

        JB      P3.2, INT0_EXIT ; 檢查P3.2是否仍為低電平:
                           ;   若為高電平,說(shuō)明是按鍵抖動(dòng),跳轉(zhuǎn)到INT0_EXIT返回

        MOV     R0, #0        ; 初始化行計(jì)數(shù)器R0=0(從第1行開(kāi)始掃描)
        MOV     R1, #0FEH     ; 初始化行掃描碼R1=11111110B(選中第1行)

KEY_SCAN_0:
        MOV     P1, R1        ; 將行掃描碼輸出到P1口(低4位)
        JNB     P1.4, KEY_00  ; 檢測(cè)第1列(P1.4):
                           ;   若為低電平,說(shuō)明第1列有按鍵按下,跳轉(zhuǎn)到KEY_00
        JNB     P1.5, KEY_01  ; 檢測(cè)第2列(P1.5):
                           ;   若為低電平,說(shuō)明第2列有按鍵按下,跳轉(zhuǎn)到KEY_01

        MOV     A, R1         ; 將當(dāng)前行掃描碼復(fù)制到累加器A
        RL      A             ; 將A循環(huán)左移一位(生成下一行掃描碼)
                           ;   例如: 11111110B → 11111101B → 11111011B → 11110111B
        MOV     R1, A         ; 將新的行掃描碼保存回R1
        INC     R0            ; 行計(jì)數(shù)器R0加1(指向下一行)
        CJNE    R0, #4, KEY_SCAN_0 ; 比較R0與4:
                           ;   若不等于4,說(shuō)明未掃描完所有行,繼續(xù)掃描下一行

INT0_EXIT:
        POP     DPL           ; 從堆;謴(fù)數(shù)據(jù)指針低8位DPL
        POP     DPH           ; 從堆;謴(fù)數(shù)據(jù)指針高8位DPH
        POP     PSW           ; 從堆棧恢復(fù)程序狀態(tài)字PSW
        POP     ACC           ; 從堆;謴(fù)累加器A
        RETI                  ; 中斷返回,恢復(fù)PC值并開(kāi)中斷

;====================================================================
; 后兩列按鍵中斷處理(INT1)
;====================================================================
INT1_HANDLER:
        PUSH    ACC           ; 保護(hù)累加器A
        PUSH    PSW           ; 保護(hù)程序狀態(tài)字PSW
        PUSH    DPH           ; 保護(hù)數(shù)據(jù)指針高8位DPH
        PUSH    DPL           ; 保護(hù)數(shù)據(jù)指針低8位DPL

        LCALL   DELAY_10MS    ; 調(diào)用延時(shí)子程序消抖

        JB      P3.3, INT1_EXIT ; 檢查P3.3是否仍為低電平
                           ;   若為高電平,說(shuō)明是抖動(dòng),跳轉(zhuǎn)到INT1_EXIT返回

        MOV     R0, #0        ; 初始化行計(jì)數(shù)器R0=0
        MOV     R1, #0FEH     ; 初始化行掃描碼R1=11111110B

KEY_SCAN_1:
        MOV     P1, R1        ; 輸出行掃描碼到P1口
        JNB     P1.6, KEY_10  ; 檢測(cè)第3列(P1.6):
                           ;   若為低電平,跳轉(zhuǎn)到KEY_10
        JNB     P1.7, KEY_11  ; 檢測(cè)第4列(P1.7):
                           ;   若為低電平,跳轉(zhuǎn)到KEY_11

        MOV     A, R1         ; 復(fù)制當(dāng)前行掃描碼到A
        RL      A             ; 循環(huán)左移生成下一行掃描碼
        MOV     R1, A         ; 保存新的行掃描碼
        INC     R0            ; 行計(jì)數(shù)器加1
        CJNE    R0, #4, KEY_SCAN_1 ; 未掃描完4行則繼續(xù)掃描

INT1_EXIT:
        POP     DPL           ; 恢復(fù)DPL
        POP     DPH           ; 恢復(fù)DPH
        POP     PSW           ; 恢復(fù)PSW
        POP     ACC           ; 恢復(fù)ACC
        RETI                  ; 中斷返回

;====================================================================
; 按鍵處理與數(shù)碼管顯示
;====================================================================
KEY_00: MOV     A, R0         ; 將行號(hào)(R0)復(fù)制到累加器A
        MOV     B, #4         ; 將常數(shù)4放入寄存器B
        MUL     AB            ; 執(zhí)行乘法: A = A × B (行號(hào)×4)
        MOV     R2, A         ; 將計(jì)算結(jié)果(行號(hào)×4)保存到R2
        SJMP    DISPLAY_KEY   ; 跳轉(zhuǎn)到DISPLAY_KEY顯示按鍵值

KEY_01: MOV     A, R0         ; 復(fù)制行號(hào)到A
        MOV     B, #4         ; 常數(shù)4放入B
        MUL     AB            ; 行號(hào)×4
        ADD     A, #1         ; 加1(第2列對(duì)應(yīng)的偏移量)
        MOV     R2, A         ; 保存按鍵值到R2
        SJMP    DISPLAY_KEY   ; 跳轉(zhuǎn)到顯示處理

KEY_10: MOV     A, R0         ; 復(fù)制行號(hào)到A
        MOV     B, #4         ; 常數(shù)4放入B
        MUL     AB            ; 行號(hào)×4
        ADD     A, #2         ; 加2(第3列對(duì)應(yīng)的偏移量)
        MOV     R2, A         ; 保存按鍵值到R2
        SJMP    DISPLAY_KEY   ; 跳轉(zhuǎn)到顯示處理

KEY_11: MOV     A, R0         ; 復(fù)制行號(hào)到A
        MOV     B, #4         ; 常數(shù)4放入B
        MUL     AB            ; 行號(hào)×4
        ADD     A, #3         ; 加3(第4列對(duì)應(yīng)的偏移量)
        MOV     R2, A         ; 保存按鍵值到R2

DISPLAY_KEY:
        MOV     A, R2         ; 將按鍵值從R2復(fù)制到累加器A
        MOV     DPTR, #SEG_TAB ; 將段碼表的基地址存入數(shù)據(jù)指針DPTR
        MOVC    A, @A+DPTR    ; 查表獲取按鍵值對(duì)應(yīng)的段碼
                           ;   A = 段碼表[按鍵值]
        MOV     SBUF, A       ; 將段碼發(fā)送到串口數(shù)據(jù)緩沖區(qū)SBUF
                           ;   觸發(fā)串口發(fā)送過(guò)程
        JNB     TI, $         ; 等待發(fā)送完成標(biāo)志位TI置位
                           ;   $表示當(dāng)前地址,形成原地循環(huán)
        CLR     TI            ; 手動(dòng)清除發(fā)送完成標(biāo)志位TI
        SJMP    INT0_EXIT     ; 跳轉(zhuǎn)到INT0_EXIT恢復(fù)現(xiàn)場(chǎng)并返回

;====================================================================
; 延時(shí)子程序(約10ms @12MHz晶振)
;====================================================================
DELAY_10MS:
        MOV     R7, #20       ; 設(shè)置外層循環(huán)計(jì)數(shù)器R7=20
DELAY_LOOP1:
        MOV     R6, #248      ; 設(shè)置內(nèi)層循環(huán)計(jì)數(shù)器R6=248
DELAY_LOOP2:
        DJNZ    R6, DELAY_LOOP2 ; 內(nèi)層循環(huán): R6減1,若不為0則繼續(xù)循環(huán)
        DJNZ    R7, DELAY_LOOP1 ; 外層循環(huán): R7減1,若不為0則繼續(xù)循環(huán)
        RET                   ; 子程序返回

;====================================================================
; 共陽(yáng)極數(shù)碼管段碼表(0-F)
;====================================================================
SEG_TAB:
        DB      0C0H, 0F9H, 0A4H, 0B0H, 99H, 92H, 82H, 0F8H ; 0-7的段碼
        DB      80H, 90H, 88H, 83H, 0C6H, 0A1H, 86H, 8EH     ; 8-F的段碼

        END                     ; 程序結(jié)束標(biāo)記

DA轉(zhuǎn)換程序:
ORG 0000H
    LJMP MAIN
    ORG 100H
;程序初始化
MAIN:   MOV A,#00H               ;賦初值
UP:     MOVX @DPTR, A            ;輸出  4機(jī)器周期
        INC A                    ;A的值加1 1機(jī)器周期
        CJNE A ,0FFH ,UP          ;如果上次計(jì)算的結(jié)果不是0,就跳轉(zhuǎn) 當(dāng)A加到255,再變成0之后就會(huì)下降。
DOWN:   DEC A                    ;同上
        MOVX @DPTR, A            ;4個(gè)機(jī)器周期
        CJNE A ,#00H , DOWN      ;條件滿足時(shí)使用4個(gè)機(jī)器周期,條件不滿足時(shí)使用3個(gè)機(jī)器周期
        INC A                    ;1個(gè)機(jī)器周期
        SJMP UP                  ;2個(gè)機(jī)器周期

        END
屏幕截圖 2025-06-29 095233.png

矩陣鍵盤

矩陣鍵盤

DA轉(zhuǎn)換

DA轉(zhuǎn)換

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:1155590 發(fā)表于 2025-6-29 21:40 | 顯示全部樓層
嗯,剛好學(xué)到這個(gè),很好的參考
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

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

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

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