?? wl010.asm
字號:
;********************************************************************************
;* 標題: 偉納電子ME300B單片機開發系統演示程序 - 數碼管顯示簡易電子時鐘 *
;* 文件: wl010.asm *
;* 日期: 2004-1-5 *
;* 版本: 1.0 *
;* 作者: 偉納電子 - Freeman *
;* 郵箱: freeman@willar.com *
;* 網站: http://www.willar.com *
;********************************************************************************
;* 描述: *
;* 簡易電子時鐘,數碼管顯示 *
;* K1---時調整 *
;* K2---分調整 *
;* *
;* *
;********************************************************************************
;* 【版權】 Copyright(C)偉納電子 www.willar.com All Rights Reserved *
;* 【聲明】 此程序僅用于學習與參考,引用請注明版權和作者信息! *
;********************************************************************************
CODE_SEG SEGMENT CODE
DATA_SEG SEGMENT DATA
STACK_SEG SEGMENT IDATA
K1 BIT P1.4
K2 BIT P1.5
RSEG DATA_SEG
KEY_S: DS 1
KEY_V: DS 1
DIS_DIGIT: DS 1
SEC: DS 1
DIS_INDEX: DS 1
HOUR: DS 1
MIN: DS 1
SEC100: DS 1
DIS_BUF: DS 8
BUF_HOUR_H EQU DIS_BUF ; 小時十位
BUF_HOUR_L EQU DIS_BUF+1 ; 小時個位
BUF_MIN_H EQU DIS_BUF+3 ; 分十位
BUF_MIN_L EQU DIS_BUF+4 ; 分個位
BUF_SEC_H EQU DIS_BUF+6 ; 秒十位
BUF_SEC_L EQU DIS_BUF+7 ; 秒個位
RSEG STACK_SEG
STACK: DS 20
;===============================================================================
CSEG AT 0000H
JMP MAIN
CSEG AT 0000BH
LJMP TIMER0
CSEG AT 0001BH
LJMP TIMER1
;===============================================================================
RSEG CODE_SEG
MAIN:
USING 0
MOV SP, #(STACK-1) ;
MOV P0,#0FFH
MOV P2,#0FFH
MOV TMOD,#011H ; 定時器0, 1工作模式1, 16位定時方式
MOV TH0,#0FCH
MOV TL0,#017H
MOV TH1,#0DCH
CLR A
MOV TL1,A
MOV HOUR,#12 ;
CLR A ;
MOV MIN,A
MOV SEC,A
MOV SEC100,A
MOV A,HOUR
MOV B,#10
DIV AB
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_HOUR_H,A ; 時十位
MOV A,HOUR
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_HOUR_L,A ; 時個位
MOV A,MIN
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 分個位
MOV A,SEC
MOV B,#10
DIV AB
MOVC A,@A+DPTR
MOV BUF_SEC_H,A ; 秒十位
MOV A,SEC
MOV B,#10
DIV AB
MOV A,B
MOVC A,@A+DPTR
MOV BUF_SEC_L,A ; 秒個位
MOV BUF_HOUR_H+02H,#0BFH
MOV BUF_HOUR_H+05H,#0BFH
MOV DIS_DIGIT,#0FEH
CLR A
MOV DIS_INDEX,A
MOV IE,#08AH ; 使能timer0,1 中斷
SETB TR0
SETB TR1
MOV KEY_V,#03H
MAIN_LP:
LCALL SCAN_KEY ; 鍵掃描
JZ MAIN_LP ; 無鍵返回
MOV R7,#10 ; 延時10ms
LCALL DELAYMS ; 延時去抖動
LCALL SCAN_KEY ; 再次掃描
JZ MAIN_LP ; 無鍵返回
MOV KEY_V,KEY_S ; 保存鍵值
LCALL PROC_KEY ; 鍵處理
SJMP MAIN_LP ; 調回主循環
;===============================================================================
SCAN_KEY:
; 掃鍵掃描子程序
; 保存按鍵狀態到key_s
; 返回: A --- 按鍵是否按下(BOOL)
CLR A
MOV C,K1 ; 讀按鍵K1
MOV ACC.0,C
MOV C,K2 ; 讀按鍵K2
MOV ACC.1,C
MOV KEY_S,A ; 保存按鍵狀態到key_s
XRL A,KEY_V
RET
;===============================================================================
PROC_KEY:
; 鍵處理子程序
; 傳入參數: KEY_V --- 按鍵值
; 返回值: 無
CLR EA
MOV A,KEY_V
JNB ACC.0,PROC_K1
JNB ACC.1,PROC_K2
SJMP END_PROC_KEY
PROC_K1: ; 按鍵k1處理
LCALL INC_HOUR ; 小時加1
SJMP END_PROC_KEY
PROC_K2: ; 按鍵K2處理
INC MIN ; 分鐘加1
MOV A,MIN ;
SETB C
SUBB A,#59
JC K2_UPDATE_MIN ; 如果分鐘等于60,則分清0,小時加1
CLR A ;
MOV MIN,A
K2_UPDATE_MIN: ; 更新分顯示緩沖區
MOV A,MIN
MOV B,#10
DIV AB ; A = MIN / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 更新分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B ; A = MIN % 10
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 更新分個位
END_PROC_KEY:
SETB EA
RET
;===============================================================================
USING 0
TIMER0:
; 定時器0中斷服程序, 用于數碼管的動態掃描
; DIS_INDEX --- 顯示索引, 用于標識當前顯示的數碼管和緩沖區的偏移量
; DIS_DIGIT --- 位選通值, 傳送到P2口用于選通當前數碼管的數值, 如等于0xfe時,
; 選通P2.0口數碼管
; DIS_BUF --- 顯于緩沖區基地址
PUSH ACC
PUSH PSW
PUSH AR0
MOV TH0,#0FCH
MOV TL0,#017H
MOV P2,#0FFH ; 先關閉所有數碼管
MOV A,#DIS_BUF ; 獲得顯示緩沖區基地址
ADD A,DIS_INDEX ; 獲得偏移量
MOV R0,A ; R0 = 基地址 + 偏移量
MOV A,@R0 ; 獲得顯示代碼
MOV P0,A ; 顯示代碼傳送到P0口
MOV P2,DIS_DIGIT
MOV A,DIS_DIGIT ; 位選通值左移, 下次中斷時選通下一位數碼管
RL A
MOV DIS_DIGIT,A
INC DIS_INDEX ; DIS_INDEX加1, 下次中斷時顯示下一位
ANL DIS_INDEX,#0x07 ; 當DIS_INDEX等于8(0000 1000)時, 清0
POP AR0
POP PSW
POP ACC
RETI
;===============================================================================
USING 0
TIMER1:
; 定時器1中斷服務程序, 產生時基信號10ms
;
;
PUSH PSW
PUSH ACC
PUSH B
PUSH DPH
PUSH DPL
MOV TH1,#0DCH
INC SEC100
MOV A,SEC100
CLR C
SUBB A,#100 ; 是否中斷100次(達到1s)
JC END_TIMER1 ; < 1S
MOV SEC100,#00H ; 達到1s
LCALL INC_SEC ; 秒加1
END_TIMER1:
POP DPL
POP DPH
POP B
POP ACC
POP PSW
RETI ;
;===============================================================================
INC_SEC:
INC SEC
MOV A,SEC
SETB C
SUBB A,#59 ;
JC UPDATE_SEC
CLR A
MOV SEC,A
LCALL INC_MIN
UPDATE_SEC:
MOV A,SEC
MOV B,#10
DIV AB ; A = SEC / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR ;
MOV BUF_SEC_H,A ;
MOV A,SEC
MOV B,#10
DIV AB
MOV A,B ; A = SEC % 10
MOVC A,@A+DPTR
MOV BUF_SEC_L,A
RET
;===============================================================================
INC_MIN:
INC MIN ; 分鐘加1
MOV A,MIN ;
SETB C
SUBB A,#59
JC UPDATE_MIN ; 如果分鐘等于60,則分清0,小時加1
CLR A ;
MOV MIN,A
LCALL INC_HOUR ; 小時加1
UPDATE_MIN: ; 更新分顯示緩沖區
MOV A,MIN
MOV B,#10
DIV AB ; A = MIN / 10
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_MIN_H,A ; 更新分十位
MOV A,MIN
MOV B,#10
DIV AB
MOV A,B ; A = MIN % 10
MOVC A,@A+DPTR
MOV BUF_MIN_L,A ; 更新分個位
RET
;===============================================================================
INC_HOUR:
INC HOUR ; 小時加1
MOV A,HOUR
SETB C
SUBB A,#24
JC UPDATE_HOUR ; 如果小時等于24,則小時清0
CLR A
MOV HOUR,A ; 小時清0
UPDATE_HOUR:
MOV A,HOUR
SETB C
SUBB A,#9
JC UPDATE_HOUR1 ; 如果小時小于10,則十位0不顯示
MOV A,HOUR
MOV B,#10
DIV AB
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR ;
MOV BUF_HOUR_H,A
SJMP UPDATE_HOUR2
UPDATE_HOUR1:
MOV BUF_HOUR_H,#0FFH
UPDATE_HOUR2:
MOV A,HOUR
MOV B,#10
DIV AB
MOV A,B
MOV DPTR,#DIS_CODE
MOVC A,@A+DPTR
MOV BUF_HOUR_L,A
RET
;===============================================================================
DELAYMS:
; 延時子程序
; 傳入參數:R7 --- 延時值(MS)
; 返回值:無
MOV A,R7
JZ END_DLYMS
DLY_LP1:
MOV R6,#185
DLY_LP2:
NOP
NOP
NOP
DJNZ R6,DLY_LP2
DJNZ R7,DLY_LP1
END_DLYMS:
RET
; END OF DELAYMS
;===============================================================================
DIS_CODE:
DB 0C0H
DB 0F9H
DB 0A4H
DB 0B0H
DB 099H
DB 092H
DB 082H
DB 0F8H
DB 080H
DB 090H
DB 0FFH
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -