|
系統(tǒng)采用AT89S51,晶振為12MHz,獨立、依次完成以下設(shè)計任務(wù):
(1) 利用P1口,設(shè)計一份含4個獨立鍵盤和4個獨立發(fā)光二極管的硬件電路圖,并設(shè)計晶振和復(fù)位電路,正確連接EA引腳。
(2) 設(shè)計一份(1)電路的鍵盤判斷程序(不含鍵盤消除抖動功能),以及自定義功能的發(fā)光二極管顯示程序。
(3) 設(shè)計一份通過P3.4口輸出周期為1ms的方波(采用軟件延時),以及通過P3.5口輸出周期為1min的方波(采用定時中斷)程序。
(4) 利用P1口,設(shè)計4×4行列式鍵盤電路,以及采用74HC164芯片,設(shè)計通過串行口連接方式連接4個7段數(shù)碼管的電路。
(5) 在(4)電路中,設(shè)計一份鍵盤判斷程序(包含鍵盤軟件消除抖動功能)和顯示學(xué)號后四位程序。
(6) 采用DAC0832設(shè)計一份D/A轉(zhuǎn)換電路圖,需要設(shè)計專門的基準(zhǔn)電壓。
led程序:
; 8051 匯編:按鍵(P1.0-P1.3)控制共陰極 LED(P1.4-P1.7)
; 功能:短按點亮對應(yīng) LED,長按(超 200ms)切換狀態(tài)(亮/滅)
; 硬件:按鍵接 P1.0-P1.3(按下接地),共陰極 LED 接 P1.4-P1.7(陽極串電阻接 P1)
ORG 0000H
LJMP MAIN
; 延時消抖(約 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:
; 檢測 P1.0 按鍵
MOV A, P1
ANL A, #01H ; 屏蔽其他位,取 P1.0
JNZ CHECK_P11 ; 未按下,跳檢測 P1.1
ACALL DELAY_20MS ; 消抖
MOV A, P1
ANL A, #01H
JNZ CHECK_P11 ; 抖動,跳檢測 P1.1
; 確認(rèn) P1.0 按下:翻轉(zhuǎn) P1.4 狀態(tài)(共陰極 LED 高電平滅、低電平亮)
CPL P1.4
; 等待釋放(長按不影響其他按鍵,但需等釋放再掃其他鍵)
WAIT_RELEASE0:
MOV A, P1
ANL A, #01H
JZ WAIT_RELEASE0 ; 未釋放則等待
ACALL DELAY_20MS ; 釋放消抖
SJMP CHECK_P11 ; 掃下一個鍵
CHECK_P11:
; 檢測 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:
; 檢測 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:
; 檢測 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 ; 抖動,回到總掃描
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ū)動數(shù)碼管)
;====================================================================
ORG 0000H ; 設(shè)置程序起始地址為0000H(復(fù)位向量)
LJMP MAIN ; 無條件跳轉(zhuǎn)到主程序MAIN處執(zhí)行
ORG 0003H ; 設(shè)置外部中斷0(INT0)向量地址
LJMP INT0_HANDLER ; 當(dāng)發(fā)生INT0中斷時,跳轉(zhuǎn)到INT0_HANDLER處理
ORG 0013H ; 設(shè)置外部中斷1(INT1)向量地址
LJMP INT1_HANDLER ; 當(dāng)發(fā)生INT1中斷時,跳轉(zhuǎn)到INT1_HANDLER處理
;====================================================================
; 主程序
;====================================================================
MAIN: MOV SP, #70H ; 設(shè)置堆棧指針SP為70H(避免覆蓋工作寄存器區(qū))
MOV IE, #85H ; 開中斷控制寄存器:
; EA=1(開總中斷),
; EX0=1(開INT0中斷),
; EX1=1(開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(輸出行掃描信號)
; P1.4-P1.7(高4位)=1(輸入列檢測信號)
MAIN_LOOP:
SJMP MAIN_LOOP ; 無限循環(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)用延時子程序消抖(約10ms)
JB P3.2, INT0_EXIT ; 檢查P3.2是否仍為低電平:
; 若為高電平,說明是按鍵抖動,跳轉(zhuǎn)到INT0_EXIT返回
MOV R0, #0 ; 初始化行計數(shù)器R0=0(從第1行開始掃描)
MOV R1, #0FEH ; 初始化行掃描碼R1=11111110B(選中第1行)
KEY_SCAN_0:
MOV P1, R1 ; 將行掃描碼輸出到P1口(低4位)
JNB P1.4, KEY_00 ; 檢測第1列(P1.4):
; 若為低電平,說明第1列有按鍵按下,跳轉(zhuǎn)到KEY_00
JNB P1.5, KEY_01 ; 檢測第2列(P1.5):
; 若為低電平,說明第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 ; 行計數(shù)器R0加1(指向下一行)
CJNE R0, #4, KEY_SCAN_0 ; 比較R0與4:
; 若不等于4,說明未掃描完所有行,繼續(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值并開中斷
;====================================================================
; 后兩列按鍵中斷處理(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)用延時子程序消抖
JB P3.3, INT1_EXIT ; 檢查P3.3是否仍為低電平
; 若為高電平,說明是抖動,跳轉(zhuǎn)到INT1_EXIT返回
MOV R0, #0 ; 初始化行計數(shù)器R0=0
MOV R1, #0FEH ; 初始化行掃描碼R1=11111110B
KEY_SCAN_1:
MOV P1, R1 ; 輸出行掃描碼到P1口
JNB P1.6, KEY_10 ; 檢測第3列(P1.6):
; 若為低電平,跳轉(zhuǎn)到KEY_10
JNB P1.7, KEY_11 ; 檢測第4列(P1.7):
; 若為低電平,跳轉(zhuǎn)到KEY_11
MOV A, R1 ; 復(fù)制當(dāng)前行掃描碼到A
RL A ; 循環(huán)左移生成下一行掃描碼
MOV R1, A ; 保存新的行掃描碼
INC R0 ; 行計數(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 ; 將行號(R0)復(fù)制到累加器A
MOV B, #4 ; 將常數(shù)4放入寄存器B
MUL AB ; 執(zhí)行乘法: A = A × B (行號×4)
MOV R2, A ; 將計算結(jié)果(行號×4)保存到R2
SJMP DISPLAY_KEY ; 跳轉(zhuǎn)到DISPLAY_KEY顯示按鍵值
KEY_01: MOV A, R0 ; 復(fù)制行號到A
MOV B, #4 ; 常數(shù)4放入B
MUL AB ; 行號×4
ADD A, #1 ; 加1(第2列對應(yīng)的偏移量)
MOV R2, A ; 保存按鍵值到R2
SJMP DISPLAY_KEY ; 跳轉(zhuǎn)到顯示處理
KEY_10: MOV A, R0 ; 復(fù)制行號到A
MOV B, #4 ; 常數(shù)4放入B
MUL AB ; 行號×4
ADD A, #2 ; 加2(第3列對應(yīng)的偏移量)
MOV R2, A ; 保存按鍵值到R2
SJMP DISPLAY_KEY ; 跳轉(zhuǎn)到顯示處理
KEY_11: MOV A, R0 ; 復(fù)制行號到A
MOV B, #4 ; 常數(shù)4放入B
MUL AB ; 行號×4
ADD A, #3 ; 加3(第4列對應(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 ; 查表獲取按鍵值對應(yīng)的段碼
; A = 段碼表[按鍵值]
MOV SBUF, A ; 將段碼發(fā)送到串口數(shù)據(jù)緩沖區(qū)SBUF
; 觸發(fā)串口發(fā)送過程
JNB TI, $ ; 等待發(fā)送完成標(biāo)志位TI置位
; $表示當(dāng)前地址,形成原地循環(huán)
CLR TI ; 手動清除發(fā)送完成標(biāo)志位TI
SJMP INT0_EXIT ; 跳轉(zhuǎn)到INT0_EXIT恢復(fù)現(xiàn)場并返回
;====================================================================
; 延時子程序(約10ms @12MHz晶振)
;====================================================================
DELAY_10MS:
MOV R7, #20 ; 設(shè)置外層循環(huán)計數(shù)器R7=20
DELAY_LOOP1:
MOV R6, #248 ; 設(shè)置內(nèi)層循環(huán)計數(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 ; 子程序返回
;====================================================================
; 共陽極數(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機器周期
INC A ;A的值加1 1機器周期
CJNE A ,0FFH ,UP ;如果上次計算的結(jié)果不是0,就跳轉(zhuǎn) 當(dāng)A加到255,再變成0之后就會下降。
DOWN: DEC A ;同上
MOVX @DPTR, A ;4個機器周期
CJNE A ,#00H , DOWN ;條件滿足時使用4個機器周期,條件不滿足時使用3個機器周期
INC A ;1個機器周期
SJMP UP ;2個機器周期
END
|
評分
-
查看全部評分
|