;四位数码管时钟显示(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