;************************************************ ; Null Clock REV:1.0 by Jed ; www.xuan.idv.tw ;************************************************ INCLUDE P16F84A.INC LIST P=16F84A,R=Dec CONFIG _XT_OSC&_WDT_OFF ;---------DEFINE CONSTANT-------------------------- RS EQU 0 RD_WR EQU 1 EN EQU 2 ;---------DEFINE DATA RAM-------------------------- TEMP equ 0x12 STACK equ 0x13 PTR equ 0x14 SEC1 equ 0x15 MIN1 equ 0x16 HUR1 equ 0x17 SEC2 equ 0x18 MIN2 equ 0x19 HUR2 equ 0x1A CNT EQU 0x1B HUR24 equ 0x1C DLY1 EQU 0x1D DLY2 EQU 0x1E DLY3 EQU 0x1F TEMP1 EQU 0X20 ORG 0x00 goto main ;Interrupt vector ORG 0x04 MOVLW 256-196 ; 重設 TMR0 內容 MOVWF TMR0 BCF INTCON,T0IF ; 清除中斷旗號 DECFSZ CNT ; 檢查是否中斷 20 次 RETFIE ;50ms*20~=1S MOVLW.20 MOVWF CNT run_sec: MOVF SEC1,W SUBLW.9 GOTO run_sec2 設定 LCD 對應顯示位址 ( 秒個位數 ) 1
INCF SEC1,F ; 將 SEC1+1 作查表取回對應數字 MOVF SEC1,W banksel STRING1 banksel PORTB RETFIE run_sec2: MOVF SEC2,W SUBLW.5 GOTO run_min ; 將秒個位數歸 0 CLRF SEC1 MOVLW 10001001B ;0X09 設定 LCD 對應顯示位址 ( 秒十位數 ) INCF SEC2,F MOVF SEC2,W RETFIE run_min: MOVF MIN1,W SUBLW.9 GOTO run_min2 ; 將秒數歸零 CLRF SEC1 CLRF SEC2 2
設定 LCD 對應顯示位址 ( 分個位數 ) INCF MIN1,F ; 將 MIN1+1 作查表取回對應數字 MOVF MIN1,W RETFIE run_min2: MOVF MIN2,W SUBLW.5 GOTO run_hur CLRF SEC1 CLRF SEC2 CLRF MIN1 MOVLW 10000110B ;0x06 設定 LCD 對應顯示位址 ( 分十位數 ) INCF MIN2,F MOVF MIN2,W RETFIE run_hur: MOVF HUR24,W SUBLW.23 GOTO clr_time MOVF HUR1,W 3
SUBLW.9 GOTO run_hur2 CLRF SEC1 CLRF SEC2 CLRF MIN1 CLRF MIN2 MOVLW 10000110B ;0x06 MOVLW 10000100B ;0x04 設定 LCD 對應顯示位址 ( 時各位數 ) INCF HUR1,F MOVF HUR1,W INCF HUR24,F RETFIE run_hur2: CLRF SEC1 CLRF SEC2 CLRF MIN1 CLRF MIN2 CLRF HUR1 4
MOVLW 10000110B ;0x06 MOVLW 10000100B ;0x04 MOVLW 10000011B ;0x03 INCF HUR24,F INCF HUR2,F MOVF HUR2,W RETFIE STRING1: ADDWF PCL DT "0123456789" retlw 00 main: BSF STATUS,RP0 ;set porta as output MOVLW 11111000B MOVWF TRISA MOVLW 11010111B ; 設定預除值 MOVWF OPTION_REG BCF STATUS,RP0 CALL INIT_LCD ;start lcd module MOVLW 00000001B ;CLEAR LCD MOVLW.20 MOVWF CNT ; 將時分秒變數歸 0 5
MOVLW.0 MOVWF SEC1 MOVLW.0 MOVWF SEC2 MOVLW.0 MOVWF MIN1 MOVLW.0 MOVWF MIN2 MOVLW.0 MOVWF HUR1 MOVLW.0 MOVWF HUR2 MOVLW.0 MOVWF HUR24 ; 設定初始畫面 00:00:00 MOVLW 10000011B ;0x03 MOVLW 10000100B ;0x04 MOVLW 10000101B ;0x05 MOVLW ':' MOVLW 10000110B ;0x06 MOVLW 10001000B ;0x08 MOVLW ':' D:\MCU\DS1820\main.ASM 6
MOVLW 10100000B ; 接受中斷 ; 接受 TMR0 溢位中斷 MOVWF INTCON GOTO chk_set -- ; 初始化程序完成 -- MAIN2: MOVLW 10000000B ; 將 E 字取消 MOVLW ' ' BSF INTCON,7 ; 致能中斷總開關 chk_set: btfss PORTA,4 ; 檢查 PORTA4 是否為 0 goto set_mode ; 是, 進入設定模式 goto chk_set ; 否, 返回重新偵測 set_mode: ; 按住 5 秒進入設定模式 MOVLW.250 call DELAY btfsc PORTA,4 ; 防止開關彈跳 goto chk_set ; 以及確認三秒進入設定模式 ; 進入設定模式 BCF INTCON,7 ; 解除中斷總開關 MOVLW 10000000B ;0X00 顯示 E 代表進入設定模式 MOVLW 'E' ; 秒數閃爍兩下 MOVLW.2 SEC_SET: MOVLW ' ' 7
MOVLW ' ' MOVLW.25 MOVF SEC1,W MOVF SEC2,W MOVLW.25 DECFSZ TEMP1,F GOTO SEC_SET MOVLW.50 SEC_SET1: BTFSS PORTA,4 GOTO CHANG_SEC MOVLW.5 DECFSZ TEMP1,F GOTO SEC_SET1 GOTO MIN_SET ; 超過等待時間跳到更改分時間 CHANG_SEC: MOVLW.5 BTFSC PORTA,4 GOTO SEC_SET1 ; 防止機械彈跳 ; 更改秒數程序 MOVLW.10 call chg_sec ; 程序更改結束 MOVLW.50 GOTO SEC_SET1 8
; 分閃爍 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MIN_SET MOVLW.2 MIN_SET1: MOVLW ' ' MOVLW 10000110B ;0x06 MOVLW ' ' MOVLW.25 MOVF MIN1,W MOVLW 10000110B ;0x06 MOVF MIN2,W MOVLW.25 DECFSZ TEMP1,F GOTO MIN_SET1 MOVLW.50 MIN_SET2: BTFSS PORTA,4 GOTO CHANG_MIN MOVLW.5 DECFSZ TEMP1,F GOTO MIN_SET2 GOTO HUR_SET ; 超過等待時間跳到更改時時間 CHANG_MIN: MOVLW.5 9
BTFSC PORTA,4 GOTO MIN_SET2 ; 防止機械彈跳 ; 更改分數程序 MOVLW.10 call chg_min ; 程序更改結束 MOVLW.50 GOTO MIN_SET2 ; 時閃爍 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; HUR_SET MOVLW.2 HUR_SET1: MOVLW 10000100B ;0x04 MOVLW ' ' MOVLW 10000011B ;0x03 MOVLW ' ' MOVLW.25 MOVLW 10000100B ;0x04 MOVF HUR1,W MOVLW 10000011B ;0x03 MOVF HUR2,W MOVLW.25 DECFSZ TEMP1,F GOTO HUR_SET1 MOVLW.50 HUR_SET2: 10
BTFSS PORTA,4 GOTO CHANG_HUR MOVLW.5 DECFSZ TEMP1,F GOTO HUR_SET2 GOTO MAIN2 ; 超過等待時間跳出設定模式 CHANG_HUR: MOVLW.5 BTFSC PORTA,4 GOTO HUR_SET2 ; 防止機械彈跳 ; 更改時數程序 MOVLW.10 call chg_hur ; 程序更改結束 MOVLW.50 GOTO HUR_SET2 ; 秒更改程序 ----------------------------------------------- chg_sec: MOVF SEC1,W SUBLW.9 GOTO chg_sec2 設定 LCD 對應顯示位址 ( 秒個位數 ) INCF SEC1,F ; 將 SEC1+1 作查表取回對應數字 MOVF SEC1,W banksel STRING1 banksel PORTB chg_sec2: MOVF SEC2,W SUBLW.5 GOTO chg_sec_over ;over value ; 將秒個位數歸 0 CLRF SEC1 11
MOVLW 10001001B ;0X09 設定 LCD 對應顯示位址 ( 秒十位數 ) INCF SEC2,F MOVF SEC2,W chg_sec_over: CLRF SEC1 CLRF SEC2 ; 分更改程序 ----------------------------------------------- chg_min: MOVF MIN1,W SUBLW.9 GOTO chg_min2 設定 LCD 對應顯示位址 ( 分個位數 ) INCF MIN1,F ; 將 MIN1+1 作查表取回對應數字 MOVF MIN1,W chg_min2: MOVF MIN2,W SUBLW.5 GOTO chg_min_over CLRF MIN1 12
MOVLW 10000110B ;0x06 設定 LCD 對應顯示位址 ( 分十位數 ) INCF MIN2,F MOVF MIN2,W chg_min_over: CLRF MIN1 CLRF MIN2 MOVLW 10000110B ;0x06 ; 時更改程序 ----------------------------------------------- chg_hur: MOVF HUR24,W SUBLW.23 GOTO chg_hur_over MOVF HUR1,W SUBLW.9 GOTO chg_hur2 MOVLW 10000100B ;0x04 設定 LCD 對應顯示位址 ( 時各位數 ) INCF HUR1,F MOVF HUR1,W INCF HUR24,F chg_hur2: CLRF HUR1 MOVLW 10000100B ;0x04 13
MOVLW 10000011B ;0x03 INCF HUR24,F INCF HUR2,F MOVF HUR2,W chg_hur_over: clrf HUR24 CLRF HUR1 CLRF HUR2 MOVLW 10000100B ;0x04 MOVLW 10000011B ;0x03 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; DLY1 SET ;OSC:4MHz ;1MC=(1/(4000000/4))=0.000001=1us ;DLY1 is 50=B'00110010' = 1s ; is 25=B'00011001' = 0.5s ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DELAY: ; MOVLW.250;1MC(250) ; ;1MC MOVLW.250 ;20*1MC(250) MOVWF DLY2 ;20*1MC INNER2: MOVLW.25 ;20*250*1MC(25) MOVWF DLY3 ;20*250*1MC(25) INNER1: DECFSZ DLY3,1 ;20*25*250*1MC GOTO INNER1 ;20*25*250*2MC DECFSZ DLY2,1 ;250*20*1MC GOTO INNER2 ;250*20*2MC DECFSZ DLY1,1 ;5*1MC GOTO DELAY ;2MC 14
RETURN ;1MC clr_time: CLRF SEC1 CLRF SEC2 CLRF MIN1 CLRF MIN2 CLRF HUR1 CLRF HUR2 CLRF HUR24 ; 設定初始畫面 00:00:00 MOVLW 10000011B ;0x03 MOVLW 10000100B ;0x04 MOVLW 10000101B ;0x05 MOVLW ':' MOVLW 10000110B ;0x06 MOVLW 10001000B ;0x08 MOVLW ':' 15
RETFIE INIT_LCD: MOVLW 00101000B MOVLW 00001110B MOVLW 00000110B RETURN CHK_BUSY: CALL READ_IR BTFSC TEMP,7 GOTO CHK_BUSY RETURN - READ_IR: BSF STATUS,RP0 ;SELECT BANK 1 MOVLW 11111111B ;SET PORTB INPUT MODE MOVWF TRISB BCF STATUS,RP0 ;RETURN TO BANK 0 BCF PORTA,RS ;SELECT INSTRUCTION REGISTER BSF PORTA,RD_WR ;READ MODE BSF PORTA,EN ;SET ENABLE LINE MOVF PORTB,W ;READ DATA IN W REGISTER BCF PORTA,EN ;CLEAR ENABLE LINE ANDLW 11110000B MOVWF TEMP ; BSF PORTA,EN ;SET ENABLE LINE MOVF PORTB,W ;READ DATA IN W REGISTER BCF PORTA,EN ;SET ENABLE LINE ANDLW 11110000B SWAPF TEMP IORWF TEMP SWAPF TEMP RETURN WRITE_IR: CALL CHK_BUSY BSF STATUS,RP0 ;SELECT BANK 1 16
MOVLW 00001111B ;SET PORTB OUTPUT MODE MOVWF TRISB BCF STATUS,RP0 ;RETURN TO BANK 0 BCF PORTA,RS ;SELECT INSTRUCTION REGISTER BCF PORTA,RD_WR ;WRITE MODE BSF PORTA,EN ;SET ENABLE LINE MOVF STACK,W ;WRITE HIGH NIBBLE MOVWF PORTB ;WRITE DATA TO INS. REGISTER BCF PORTA,EN ;CLEAR ENABLE LINE BSF PORTA,EN ;SET ENABLE LINE SWAPF STACK,W ;WRITE LOW NIBBLE MOVWF PORTB ;WRITE DATA TO INS. REGISTER BCF PORTA,EN ;CLEAR ENABLE LINE RETURN WRITE_DR: CALL CHK_BUSY BSF STATUS,RP0 ;SELECT BANK 1 MOVLW 00001111B ;SET PORTB OUTPUT MODE MOVWF TRISB BCF STATUS,RP0 ;RETURN TO BANK 0 BSF PORTA,RS ;SELECT DATA REGISTER BCF PORTA,RD_WR ;WRITE MODE BSF PORTA,EN ;SET ENABLE LINE MOVF STACK,W ;WRITE HIGH NIBBLE MOVWF PORTB ;WRITE DATA TO INS. REGISTER BCF PORTA,EN ;CLEAR ENABLE LINE ; BSF PORTA,EN ;SET ENABLE LINE SWAPF STACK,W ;WRITE LOW NIBBLE MOVWF PORTB ;WRITE DATA TO INS. REGISTER BCF PORTA,EN ;CLEAR ENABLE LINE RETURN ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; END 17