?? clock.asm
字號:
MODE_RG EQU 40H ;模式選擇
MODE2 EQU 60H ;MODE值
MODE3 EQU 61H
MODE4 EQU 62H
MODE5 EQU 63H
MODE6 EQU 64H
MODE1 EQU 65H
HOUR EQU 41H ;小時緩沖區
MIN EQU 42H ;分鐘緩沖區
SEC EQU 43H ;秒緩沖區
TEMP EQU 4AH
;*********鬧鐘緩沖區********************
H_ALARM EQU 6AH ;鬧鐘緩沖區
M_ALARM EQU 6BH
S_ALARM EQU 6CH
F_ALARM EQU 6DH
;***********秒表緩沖區******************
M_SEC EQU 76H
S_SEC EQU 77H
;*********LED送顯示臨時變量*************
LED0 EQU 51H
LED1 EQU 52H
LED2 EQU 53H
LED3 EQU 54H
MODE_KEY EQU P3.4
UP_KEY EQU P3.3
DOWN_KEY EQU P3.5
BUF EQU 49H
ORG 0000H
LJMP MAIN
ORG 000BH
LJMP INT_0
ORG 001BH
LJMP INT_1
ORG 0080H
MAIN: MOV SP,#2FH ;堆棧初始化
MOV MODE_RG,#0 ;MODE_RG寄存器值初始化
MOV LED0,#0FEH ;初始化LED
MOV LED1,#0FDH
MOV LED2,#0FBH
MOV LED3,#0F7H
MOV MODE1,#1
MOV MODE2,#2
MOV MODE3,#3
MOV MODE4,#4
MOV MODE5,#5
MOV MODE6,#6
MOV F_ALARM,#0 ;錯誤2:一開始用 CLR F_ALARM,這導致在后面的時候JZ F_ALARM 運行錯誤,
MOV BUF,#0 ;在于 JZ 指令是對累加器A全為0或者全為1進行判斷,CLR只能對一位操作
MOV TMOD,#11H ;定時器初始化:定時器0,方式1,定時器1,方式1
MOV IP,#00001000B ;定時器1優先級高
MOV TH0,#3CH ;定時50MS
MOV TL0,#0B1H
MOV TH1,#0D8H ;定時10MS
MOV TL1,#0F0H
SETB EA
SETB ET0
SETB ET1
SETB TR0 ;啟動定時器
MOV HOUR,#0 ;for test
MOV MIN,#0
MOV SEC,#0 ;定時器計數器,50MS中斷一次,200次則剛好1S
MOV M_SEC,#0
MOV S_SEC,#0
MOV H_ALARM,#0
MOV M_ALARM,#0
MAIN1: LCALL DISPLAY12
LCALL DISPLAY34
;CLR P1.4 TEST
JNB MODE_KEY,KEY_SCAN
MOV A,MODE_RG
CJNE A,MODE6,Y1 ;MODE6 秒表
JNB DOWN_KEY,DEALDOWN ;判斷秒表開關
JNB UP_KEY,DEALUP
Y1: MOV A,F_ALARM ;判斷鬧鐘
JNZ ALARM
LJMP MAIN1
;-----------------------------------秒表開關程序---------------------------
DEALDOWN: LCALL DELY10MS
JB DOWN_KEY,MAIN1
H1: JNB DOWN_KEY,H1
CPL TR1
LJMP MAIN1
DEALUP: LCALL DELY10MS
JB UP_KEY,MAIN1
H2: JNB UP_KEY,H2
MOV M_SEC,#0
MOV S_SEC,#0
CLR TR1
LJMP MAIN1
;-----------------------------------鬧鐘掃描程序---------------------------
ALARM: MOV A,H_ALARM
CPL P1.2
CJNE A,HOUR,EXIT3
MOV A,M_ALARM
CJNE A,MIN,EXIT3
LJMP STARTALARM
EXIT3: SETB P3.6
LJMP MAIN1
STARTALARM: CPL P3.6
JNB DOWN_KEY,OFFALARM
LJMP S1
OFFALARM: LCALL DELY10MS
JB DOWN_KEY,MAIN1
S2: JNB DOWN_KEY,S2
MOV F_ALARM,#0
SETB P3.6
LJMP MAIN1
S1: LCALL DELAY
LJMP MAIN1
;-----------------------------------鍵盤掃描程序---------------------------
KEY_SCAN: LCALL DELY10MS
JB MODE_KEY,MAIN1
INC MODE_RG
;SETB P1.4 測試
K1: JNB MODE_KEY,K1 ;按鍵直到用戶松開按鍵
K2: MOV A,MODE_RG
CJNE A,#0,DEALMODE ;不是在正常顯示模式下則跳轉到模式處理程序
LJMP MAIN1 ;返回主程序
;*******************模式處理程序部分
DEALMODE: MOV TEMP,#0 ;凡轉入MODE處理,則首先清除TEMP
MOV A,MODE_RG ;有MODE_RG值不為5、0
CJNE A,MODE2,M0 ;判斷MODE_RG值,不為1跳轉
LJMP H_GLINT ;模式1,小時位閃爍
M0: CJNE A,MODE3,M1 ;不是模式2,跳轉
LJMP M_GLINT ;模式2,分鐘位閃爍
M1: CJNE A,MODE4,M2 ;不是模式3,跳轉
LJMP H_GLINT
M2: CJNE A,MODE5,M3
LJMP M_GLINT
M3: CJNE A,MODE6,M4
MOV M_SEC,#0
MOV S_SEC,#0
LJMP MAIN1
M4: CJNE A,MODE1,M5
;CLR TR1
LJMP MAIN1
M5: MOV MODE_RG,#0
LJMP MAIN1
;*****************************MODE為1,3,小時位閃爍
//MOV TEMP,HOUR ;將TEMP賦值,防止在加的時候是在隨機值的基礎上增加
H_GLINT: ;CPL P1.0
MOV R0,#28
MOV R1,#28
K4: LCALL DISPLAY12 ;分開顯示
LCALL DISPLAY34
E1: JNB MODE_KEY,K21 ;檢測是否有按鍵按下,有按下則跳轉到分鐘位閃爍
JB UP_KEY,E9 ;判斷加位有無按鍵按下
LJMP UP
E9: DJNZ R0,K4
K6: LCALL DISPLAY34
JNB MODE_KEY,K21 ;檢測是否有按鍵按下,有按下則跳轉延時后進行模式判斷
LJMP G1
K21: LCALL DELY10MS ;延時后確定有MODE按鍵按下,將
JB MODE_KEY,H_GLINT
W: JNB MODE_KEY,W
INC MODE_RG
CPL P1.4
LJMP DEALMODE ;確定有按下,MODE+1后返回MODE處理程序
JNB UP_KEY,UP ;判斷加位有無按鍵按下
G1: DJNZ R1,K6
LJMP H_GLINT ;調用完畢返回,實現閃爍
K3: LJMP MAIN1 ;可省略
;******************************MODE為2,4,分鐘位閃爍
M_GLINT: MOV R0,#28
MOV R1,#28
K23: CPL P1.7
LCALL DISPLAY12
LCALL DISPLAY34
JNB MODE_KEY,KK ;跳轉,確定是否有按鍵按下
JNB UP_KEY,UP ;判斷加位有無按鍵按下
MOV A,MODE_RG
CJNE A,MODE3,E2 ;在MODE5的情況下要判斷鬧鐘確認鍵有沒按下
LJMP E5
E2: JNB DOWN_KEY,F2
LJMP E5
F2: LJMP ONALARM2
E5: DJNZ R0,K23
K24: LCALL DISPLAY12
JNB MODE_KEY,KK ;檢測是否有按鍵按下,有按下則跳轉
JNB UP_KEY,UP ;判斷加位有無按鍵按下
MOV A,MODE_RG ;掃描鬧鐘確認鍵
CJNE A,MODE3,E7 ;在MODE5的情況下要判斷鬧鐘確認鍵有沒按下
LJMP G2
E7: JB DOWN_KEY,E8
CPL P1.3
LJMP ONALARM2
E8: LJMP G2
KK: LCALL DELY10MS ;去抖
JB MODE_KEY,M_GLINT
W1: JNB MODE_KEY,W1
INC MODE_RG
CPL P1.4
LJMP DEALMODE ;確定有按下,MODE+1后返回MODE處理程序
G2: DJNZ R1,K24
LJMP M_GLINT
;*************************位加,處理程序
;***************小時調整
UP: MOV R1,#20
UP11: INC TEMP
UP12: MOV A,MODE_RG ;判斷此時的MODE,根據MODE將臨時變量給對應的賦值
CJNE A,MODE2,AA0 ;不是在MODE2的情況下跳轉
MOV A,TEMP
CJNE A,#24,A_UP1
MOV TEMP,#0
A_UP1: MOV HOUR,TEMP ;為MODE2,將臨時變量賦給小時位
LJMP UP15
AA0: CJNE A,MODE4,UP13 //UP13為分鐘調整入口
MOV A,TEMP
CJNE A,#24,A_UP
MOV TEMP,#0
A_UP: MOV H_ALARM,TEMP ;模式3,將臨時變量賦給鬧鐘的小時位
LJMP UP15 ;UP15為顯示入口
;****************分鐘調整入口
UP13: MOV A,MODE_RG
CJNE A,MODE3,UP14 ;不是模式2,跳轉
MOV A,TEMP
CJNE A,#60,DISOVER2
MOV TEMP,#0
DISOVER2: MOV MIN,TEMP
LJMP UP15
UP14: MOV A,TEMP ;上面判斷不是模式2,則必然是模式4
CJNE A,#60,DISOVER3
MOV TEMP,#0
DISOVER3: MOV M_ALARM,TEMP
LJMP UP15
UP15: LCALL DISPLAY12
LCALL DISPLAY34
DJNZ R1,UP01
MOV R1,#1 ;
JNB UP_KEY,UP11
UP01: JNB UP_KEY,UP12
UP16: MOV A,MODE_RG ;松開鍵以后按照模式判斷該返回哪種狀態,不能返回DEALMODE函數
CJNE A,MODE2,UP17
LJMP H_GLINT
UP17: CJNE A,MODE3,UP18
MOV SEC,#0 ;每次設置完時間后將秒鐘位置零保證時間準確
LJMP M_GLINT
UP18: CJNE A,MODE4,UP19
LJMP H_GLINT
UP19: CJNE A,MODE5,UP20
LJMP M_GLINT
UP20: LJMP MAIN1
ONALARM2: LCALL DELY10MS ;延時10MS,去抖
JB DOWN_KEY,B2 ;抖動所致,返回分鐘位閃爍
LJMP K42
B2: LJMP M_GLINT
K42: JNB DOWN_KEY,K42
MOV F_ALARM,#0FFH
MOV MODE_RG,#0
LJMP MAIN1
;---------------------------------------中斷程序入口---------------------
;*******************時間中斷0*********************
;錯誤1:中斷程序EXIT處用了MAIN1,導致一直處于中斷狀態
INT_0: PUSH ACC
PUSH PSW
MOV TH0,#3CH
MOV TL0,#0B1H
INC BUF
MOV A,BUF
CJNE A,#20,EXIT
TIME: MOV BUF,#0
INC SEC
MOV A,SEC
CJNE A,#60,EXIT
MOV SEC,#00H
INC MIN
MOV A,MIN
CJNE A,#60,EXIT
MOV MIN,#00H
INC HOUR
MOV A,HOUR
CJNE A,#24,EXIT
MOV HOUR,#0
RETI
EXIT: POP PSW POP ACC RETI
;******************時間中斷1***********************
INT_1: MOV TH1,#0D8H ;定時10MS
MOV TL1,#0F0H
INC S_SEC
MOV A,S_SEC
CJNE A,#100,EXIT4
MOV S_SEC,#0
INC M_SEC
MOV A,M_SEC
CJNE A,#100,EXIT4
MOV M_SEC,#0
EXIT4: RETI
;---------------------------------------顯示-----------------------------
DISPLAY12: MOV A,MODE_RG ;判斷模式,決定是顯示鬧鐘時間還是顯示當前時間
CJNE A,MODE4,DIS0 ;模式四,顯示鬧鐘
LJMP DIS01 ;MODE4
DIS0: CJNE A,MODE5,DIS20
DIS01: MOV R7,H_ALARM ;鬧鐘模式
LJMP DIS2
DIS20: CJNE A,MODE6,DIS21
MOV R7,M_SEC ;秒表模式,顯示秒表高位
LJMP DIS2
DIS21: CJNE A,MODE1,DIS1
LJMP DIS22
DIS22: MOV R7,MIN
LJMP DIS2
DIS1: MOV R7,HOUR ;DISPLAY12顯示高位
DIS2: LCALL BCTD ;判斷完畢,調用顯示
;將秒、分 分別轉碼,放到R4,R3
MOV A,R4
MOV R3,A
LCALL DIVIDE
MOV DPTR,#NUMTAB
MOV P2,#0FH
MOV P2,LED0
MOV A,45H ;從拆字的出口獲取值
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
MOV P2,LED1
MOV A,46H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
RET
DISPLAY34: MOV A,MODE_RG ;判斷模式,決定是顯示鬧鐘時間還是顯示當前時間
CJNE A,MODE4,DIS31
LJMP DIS32
DIS31: CJNE A,MODE5,DIS35
DIS32: MOV R7,M_ALARM
LJMP DIS34
DIS35: CJNE A,MODE6,DIS41
MOV R7,S_SEC ;秒表模式,顯示秒表低位
LJMP DIS34
DIS41: CJNE A,MODE1,DIS33
MOV R7,SEC
LJMP DIS34
DIS33: MOV R7,MIN ;DISPLAY34顯示低位
DIS34: LCALL BCTD
MOV A,R4
MOV R3,A
LCALL DIVIDE
MOV P2,LED2
MOV A,47H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
MOV P2,LED3
MOV A,48H
MOVC A,@A+DPTR
MOV P0,A
LCALL DELY10MS
SETB P2.3
RET
;--------------------二翻十:入口:R6R7 出口:R2R3R4----------------------
BCTD: MOV R5,#16
CLR A
MOV R2,A
MOV R3,A
MOV R4,A
LOOP: CLR C
MOV A,R7
RLC A
MOV R7,A
MOV A,R6
RLC A
MOV R6,A
MOV A,R4
ADDC A,R4
DA A
MOV R4,A
MOV A,R3
ADDC A,R3
DA A
MOV R3,A
MOV A,R2
ADDC A,R2
DA A
MOV R2,A
DJNZ R5,LOOP
RET
;-----------------------拆字:入口:R3R4 出口:45H46H47H48H------------------
DIVIDE: MOV A,R3
ANL A,#0FH
MOV 46H,A
MOV A,R3
ANL A,#0F0H
SWAP A
MOV 45H,A ;時拆字 45H放時高位,46H放十低位
MOV A,R4
ANL A,#0FH
MOV 48H,A
MOV A,R4
ANL A,#0F0H
SWAP A
MOV 47H,A ;分拆字 47H放分高位,48H放分低位
RET
;------------------------------------延時----------------------------------
DELY10MS: MOV R6,#10
D1: MOV R7,#248
DJNZ R7,$
DJNZ R6,D1
RET
DELAY: MOV 74H,#2 ;延時子程序,12M晶振延時1.002秒
L3: MOV 72H ,#10
L1: MOV 73H ,#249
L2: DJNZ 73H ,L2
LCALL DISPLAY12
LCALL DISPLAY34
JNB DOWN_KEY,OFFALARM1
LJMP S3
OFFALARM1: LCALL DELY10MS
JB DOWN_KEY,S3
S4: JNB DOWN_KEY,S4
MOV F_ALARM,#0
SETB P3.6
LJMP MAIN1
S3: DJNZ 72H ,L1
DJNZ 74H ,L3
RET
NUMTAB: DB 0C0H,0F9H,0A4H,0B0H,99H,92H,82H,0F8H,80H,90H,88H,83H,0C6H,0A1H,86H,8EH ;碼表
END
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -