;四位數碼管時鐘顯示(24小時),按下RB0后,可以切換到設置,
;同時所有的數字閃爍,按RB1設置小時,按RB2設置分
;文件名為:TIME.ASM
;作者:牛傳宇
;2006-6
;**************************************
list p=16f84A
#include <p16f84A.inc>
;************變量定義******************
DIGIT EQU 20H ;5MS計數器
MIN_L EQU 21H ;分鐘低位
MIN_H EQU 22H ;分鐘高位
HOU_L EQU 23H ;小時低位
HOU_H EQU 24H ;小時高位
SEC EQU 25H ;秒位
FLAG EQU 26H ;第4位為小時調整標志位,第5位為分鐘調整標志位
W_T EQU 27H ;W現場保護寄存器
ST_T EQU 28H ;STATUS現場保護寄存器
TABADD EQU 29H ;轉換數碼管地址
C1 EQU 30H ;
C2 EQU 31H ;
COUNT1 EQU 33H ;顯示位選擇寄存器
COUNT2 EQU 34H ;
COUNT3 EQU 35H ;
COUNT4 EQU 36H ;
COUNT5 EQU 37H ;
COUNT6 EQU 38H ;
COUNT8 EQU 39H
COUNT9 EQU 40H
;*****************************************
ORG 000H ;程序入口
GOTO MAIN
;**************中斷服務子程序*************
ORG 004H ;
TIME ;現場保護
MOVWF W_T ;W送入現場保護寄存器;W、STATUS現場保護
SWAPF STATUS,W ;交換狀態寄存器的高低位后
MOVWF ST_T ;送入STATUS的現場保護寄存器
;初始化TMR0
MOVLW D'100' ;TMR0重賦初值100
MOVWF TMR0 ;送入TMR0定時器
;清中斷溢出標志
BCF INTCON,T0IF ;TMR0中斷溢出標志清0
;先關閉顯示
BSF PORTB,0
BSF PORTB,1
BSF PORTB,2
BSF PORTB,3
BSF PORTB,4
BSF PORTB,5
BSF PORTB,6
BCF PORTA,0 ;RA2置1
BCF PORTA,1 ;RA3置1
BCF PORTA,2 ;RA4置1
BCF PORTA,3 ;RA5置1
;顯示位加1
INCF COUNT1,F ;COUNT1加1
;分鐘低位顯示檢測
MOVLW 01H ;送1到W
XORWF COUNT1,W ;把COUNT1與W中的1異或
BTFSC STATUS,Z ;若結果不為0,則跳過下一條指令
GOTO SM ;掃描鍵盤
GOTO XSJ1
XSJ
BSF STATUS,5
MOVLW 00H
MOVWF TRISB
BCF STATUS,5
BSF PORTB,0
BSF PORTB,1
BSF PORTB,2
BSF PORTB,3
BSF PORTB,4
BSF PORTB,5
BSF PORTB,6
BCF PORTA,0 ;RA2置1
BCF PORTA,1 ;RA3置1
BCF PORTA,2 ;RA4置1
BCF PORTA,3 ;RA5置1
GOTO DISPMIN_L ;COUNT1為1,轉分鐘低位MIN_L顯示
;分鐘高位顯示檢測
XSJ1
MOVLW 02H ;送2到W
XORWF COUNT1,W ;把COUNT1與W中的2異或
BTFSC STATUS,Z ;若結果不為0,則跳過下一條指令
GOTO DISPMIN_H ;COUNT1為2,轉分鐘高位MIN_H顯示
;小時低位顯示檢測
MOVLW 03H ;送3到W
XORWF COUNT1,W ;把COUNT1與W中的3異或
BTFSC STATUS,Z ;若結果不為0,則跳過下一條指令
GOTO DISPHOU_L ;COUNT1為3,轉小時低位HOU_L顯示
;小時高位顯示檢測
MOVLW 04H ;送4到W
XORWF COUNT1,W ;把COUNT1與W中的4異或
BTFSC STATUS,Z ;若結果不為0,則跳過下一條指令
GOTO DISPHOU_H ;COUNT1為4,轉小時高位HOU_H顯示
;*****************小時高位HOU_H顯示***************************
DISPHOU_H CLRF COUNT1 ;把COUNT1清零
BTFSS FLAG,4 ;檢測FLAG的Bit4,為1則跳過下一條指令
GOTO DISP4 ;否則就跳到DIP4
SETDISP4
INCF COUNT5,F ;COUNT5加1
MOVLW D'25' ;送25到W
SUBWF COUNT5,W ;COUNT5-W,
BTFSS STATUS,C ;檢測進位借位標志,若標志為1,則跳過下一條指令
GOTO DISP4 ;COUNT5<25,C=0,轉DISP4
MOVLW D'50' ;送50到W
XORWF COUNT5,W ;將COUNT5與W異或
BTFSC STATUS,Z ;若結果為0,則執行下一條指令,否則跳過
GOTO M4 ;=50,COUNT5清0,轉
;關閉數碼管顯示
MOVLW 00H ;
MOVWF PORTA ;25<COUNT5<50,小時高位不亮
MOVWF PORTB ;
GOTO LOOP2 ;
DISP4 ;打開數碼管顯示
BSF PORTA,3 ;點亮小時高位
BCF PORTA,1 ;關閉小時低位
BCF PORTA,2 ;關閉分鐘低位
BCF PORTA,0 ;關閉分鐘高位
MOVF HOU_H,W ;小時高位存入W
GOTO DISP ;跳轉到顯示程序
M4
CLRF COUNT5 ;
GOTO SETDISP4 ;
;*****************分鐘低位MIN_L顯示***************************
DISPMIN_L
BTFSS FLAG,5 ;
GOTO DISP1 ;分鐘不調整,轉DISP1
SETDISP1
INCF COUNT2,F ;
MOVLW D'25' ;
SUBWF COUNT2,W ;
BTFSS STATUS,C ;
GOTO DISP1 ;COUNT2<25,C=0
MOVLW D'50' ;
XORWF COUNT2,W ;
BTFSC STATUS,Z ;
GOTO M1 ;=50,COUNT2清0,轉點亮分鐘低位
MOVLW 00H ;25<COUNT5<50,分鐘低位不亮
MOVWF PORTB
MOVWF PORTA
GOTO LOOP2 ;
DISP1
BSF PORTA,0 ;點亮分鐘低位
BCF PORTA,2
BCF PORTA,3
BCF PORTA,1
MOVF MIN_L,W ;
GOTO DISP ;
M1
CLRF COUNT2
GOTO SETDISP1
;*********************分鐘高位MIN_H顯示********************************
DISPMIN_H
BTFSS FLAG,5 ;
GOTO DISP2 ;
SETDISP2
INCF COUNT3,F ;
MOVLW D'25' ;
SUBWF COUNT3,W ;
BTFSS STATUS,C ;
GOTO DISP2 ;
MOVLW D'50' ;
XORWF COUNT3,W ;
BTFSC STATUS,Z ;
GOTO M2
MOVLW 00H ;25<COUNT5<50,分鐘高位不亮
MOVWF PORTA ;
MOVWF PORTB
GOTO LOOP2 ;
DISP2
BSF PORTA,1 ;點亮分鐘高位
BCF PORTA,2
BCF PORTA,3 ;
BCF PORTA,0
MOVF MIN_H,W ;
GOTO DISP ;
M2
CLRF COUNT3
GOTO SETDISP2
;*********************小時低位HOU_L顯示******************************
DISPHOU_L
BTFSS FLAG,4 ;
GOTO DISP3 ;
SETDISP3
INCF COUNT4,F ;
MOVLW D'25' ;
SUBWF COUNT4,W ;
BTFSS STATUS,C ;
GOTO DISP3 ;
MOVLW D'50' ;
XORWF COUNT4,W ;
BTFSC STATUS,Z ;
GOTO M3
MOVLW B'01111111' ;
MOVWF PORTB ;
BCF PORTA,2 ;點亮小時低位
BCF PORTA,3
BCF PORTA,0
BCF PORTA,1
GOTO LOOP2 ;
DISP3
BSF PORTA,2 ;點亮小時低位
BCF PORTA,0 ;
BCF PORTA,3
BCF PORTA,1
MOVF HOU_L,W ;
CALL CONVERT ;
MOVWF PORTB ;
;DP
GOTO LOOP2
M3
CLRF COUNT4
GOTO SETDISP3
;********************顯示************************************
DISP
CALL CONVERT ;調用查表程序
MOVWF PORTB ;送RC口顯示
LOOP2
INCF DIGIT,F ;計數器加1
MOVLW D'100' ;
SUBWF DIGIT,W ;
BTFSS STATUS,C ;
GOTO LOOP11 ;COUNT2<25,C=0
BCF PORTB,7
LOOP12 MOVLW D'200' ;然后與200
XORWF DIGIT,W ;相與,并保存到W
BTFSS STATUS,Z ;檢測零標志位,如果計數值已到200,則跳過下一步
GOTO TIMEND ;否則跳到中斷子程序出口
CLRF DIGIT ;計數器清零
INCF SEC,F ;秒針加1
MOVLW D'60' ;用60
XORWF SEC,W ;和秒針數相與
BTFSS STATUS,Z ;再檢測零標志位,如果秒針為60,則跳過下一步
GOTO TIMEND ;否則跳到中斷子程序出口
CLRF SEC ;秒針清零
INCF MIN_L,F ;分鐘低位加1
MOVLW D'10' ;用10
XORWF MIN_L,W ;和分鐘低位相與
BTFSS STATUS,Z ;若結果為0,則會跳過下一步
GOTO TIMEND ;否則跳到中斷子程序的出口
CLRF MIN_L ;分鐘低位清零
INCF MIN_H,F ;分鐘高位加1
MOVLW D'6' ;用6
XORWF MIN_H,W ;和分鐘高位相與
BTFSS STATUS,Z ;若結果為0,則會跳過下一步
GOTO TIMEND ;否則跳到中斷子程序的出口
CLRF MIN_H ;分鐘高位清零
MOVLW D'2' ;用2
XORWF HOU_H,W ;和小時高位相與
BTFSC STATUS,Z ;若結果為0,則執行下一步
GOTO HOU1 ;跳到小時低位檢測
INCF HOU_L,F ;小時低位加1
MOVLW D'10' ;用10和
XORWF HOU_L,W ;小時低位相與
BTFSS STATUS,Z ;若結果為0,則會跳過下一步
GOTO TIMEND ;否則跳到中斷子程序的出口
CLRF HOU_L ;小時低位清零
INCF HOU_H,F ;小時高位加1
GOTO TIMEND ;跳到中斷子程序的出口
LOOP11 BSF PORTB,7
GOTO LOOP12
HOU1
INCF HOU_L,F ;小時低位加1
MOVLW D'4' ;然后用4和
XORWF HOU_L,W ;小時的低位相與
BTFSS STATUS,Z ;若結果為0,則會跳過下一步
GOTO TIMEND ;跳到中斷子程序的出口
CLRF HOU_L ;小時低位清零
CLRF HOU_H ;小時高低清零
GOTO TIMEND ;跳到中斷子程序的出口
TIMEND ;中斷子程序的出口
SWAPF ST_T,W ;先恢復狀態寄存器
MOVWF STATUS ;
SWAPF W_T,F ;再恢復W
SWAPF W_T,W ;
RETFIE ;
;****************************************************
CONVERT
ADDWF PCL,F ;將W寄存器內的7段顯示碼地址放入PCL ;PCL執行新地址指令, 跳到相對的地址執行?
RETLW H'C0' ;0 ,RETLW指令,將七段顯示碼存入W后返回
RETLW H'F9' ;1
RETLW H'A4' ;2
RETLW H'B0' ;3
RETLW H'99' ;4
RETLW H'92' ;5
RETLW H'82' ;6
RETLW H'F8' ;7
RETLW H'80' ;8
RETLW H'90' ;9
;*******************主程序***********************************
MAIN
CLRF PORTB ;初始化I/O口
CLRF PORTA ;
BSF STATUS,RP0 ;選體1
CLRF TRISA ;定義RA所有相關引腳全部為普通數字I/O腳
MOVLW B'00000100' ;
MOVWF OPTION_REG ;啟用上拉電阻,定時器分配給TMRO,分頻比為1:32
MOVLW 00H
MOVWF TRISB
BCF STATUS,RP0 ;選體0
;----------------------------------------------------------
MOVLW D'100' ;定時器送初值100,定時(256-100)*32US=4.992MS
MOVWF TMR0 ;每隔4。992MS一次中斷
MOVLW 00H ;先熄滅數碼管以免閃爍
MOVWF PORTB ;
BCF PORTA,2 ;
BCF PORTA,3 ;
BCF PORTA,0 ;
BCF PORTA,1 ;
CLRF DIGIT
CLRF MIN_L
CLRF MIN_H
CLRF HOU_L
CLRF HOU_H
CLRF COUNT1
CLRF COUNT2
CLRF COUNT3
CLRF COUNT4
CLRF COUNT5
CLRF COUNT9
CLRF SEC
CLRF FLAG
;------------------------------------------------------------
BCF INTCON,T0IF ;定時器溢出中斷標志清0
BSF INTCON,T0IE ;開放總中斷和TMR0中斷使能
BSF INTCON,GIE ;
LOOPX GOTO LOOPX ;等待中斷
;******************分鐘/小時調整*****************************
SM BSF STATUS,5
MOVLW B'11111111'
MOVWF TRISB
BCF STATUS,5
LOOP6 BTFSS PORTB,0 ;必須保證RB2松開
CALL DELAY
BTFSS PORTB,0
GOTO LOOP7
BTFSS COUNT8,1
GOTO XSJ
GOTO LOOP9
LOOP7
BTFSS PORTB,0
GOTO LOOP7
BTFSC COUNT8,1
GOTO QL
BSF COUNT8,1
LOOP9 BSF FLAG,4
BSF FLAG,5
LOOP8 BTFSS PORTB,1
CALL DELAY
BTFSC PORTB,1
GOTO LOOP10
LOOP15 BTFSS PORTB,1
GOTO LOOP15
INCF MIN_L,1
MOVLW D'10'
XORWF MIN_L,W
BTFSS STATUS,Z
GOTO LOOP8
CLRF MIN_L
INCF MIN_H,1
MOVLW 06H
XORWF MIN_H,W
BTFSS STATUS,Z
GOTO LOOP8
CLRF MIN_H
GOTO LOOP8
LOOP10 BTFSS PORTB,2
CALL DELAY
BTFSC PORTB,2
GOTO XSJ
LOOP16 BTFSS PORTB,2
GOTO LOOP16
MOVLW 02H
XORWF HOU_H,W
BTFSC STATUS,Z
GOTO HOU2
INCF HOU_L,1
MOVLW D'10'
XORWF HOU_L,W
BTFSS STATUS,Z
GOTO LOOP10
CLRF HOU_L
INCF HOU_H,1
GOTO LOOP10
QL BCF COUNT8,1
BCF FLAG,4
BCF FLAG,5
GOTO XSJ
HOU2 INCF HOU_L,1
MOVLW D'4'
XORWF HOU_L,W
BTFSS STATUS,Z
GOTO LOOP10
CLRF HOU_L
CLRF HOU_H
GOTO LOOP10
;*****************0.1S延時子程序*******************
DELAY
MOVLW D'150'
MOVWF C1
L2
MOVLW D'255'
MOVWF C2
L3
DECFSZ C2,F
GOTO L3
DECFSZ C1,F
GOTO L2
RETLW 0
;****************************************************
END