Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;##############################################
- ;Title : 時鐘 (按鈕控制)
- ;Description : S1 開始 S2 暫停 S3 清除 S4 繼續
- ;Author : TZU-CHIEG ,HSU
- ;##############################################
- list p=16F877A
- #include <p16f877A.inc> ; Include file locate at defult directory
- ; CONFIG
- ; __config 0xFF7A
- __CONFIG _FOSC_XT & _WDTE_OFF & _PWRTE_OFF & _BOREN_ON & _LVP_OFF & _CPD_OFF & _WRT_OFF & _CP_OFF
- ;
- VAL_US equ .40 ; 1ms delay valum
- VAL_MS equ .100
- count equ 0x20 ; Defined temp reg. for 1ms delay
- count_ms equ 0x21 ; Defined delay reg.
- VAL_500u equ .80 ; 1ms delay valum
- count_500u equ 0x37 ; Defined temp reg. for 1ms delay
- ADDR_POLL equ 0x25 ;掃描顯示
- ADDR_DISP equ 0x26 ;轉 7 Segment
- ADDR_SOU equ 0x27 ;轉BCD (個位)
- ADDR_TEN equ 0x28 ;轉BCD 十位
- ADDR_CLOCK_EN equ 0x40
- ADDR_CLOCK_DIV_1 equ 0x29;
- VAL_CLOCK_DIV_1 equ .121 ;83*3=249 125*2=250
- ADDR_CLOCK_DIV_2 equ 0x30
- VAL_CLOCK_DIV_2 equ .8
- ADDR_CLOCK_SEC equ 0x22 ;秒
- ADDR_CLOCK_MIN equ 0x23 ;分
- ADDR_CLOCK_HUR equ 0x24 ;小時
- ADDR_SEG_DIG0 equ 0x31 ;第一位顯示
- ADDR_SEG_DIG1 equ 0x32 ;第二位顯示
- ADDR_SEG_DIG2 equ 0x33 ;第三位顯示
- ADDR_SEG_DIG3 equ 0x34 ;第四位顯示
- ADDR_SEG_DIG4 equ 0x35 ;第五位顯示
- ADDR_SEG_DIG5 equ 0x36 ;第六位顯示
- ADDR_SEG_DIG6 equ 0x37 ;第七位顯示
- ADDR_SEG_DIG7 equ 0x38 ;第八位顯示
- ;### 按鈕處理 ###
- ADDR_BUTTON_SCAN_DIV equ 0x39 ;按鈕掃描週期
- NUM_BUTTON_SCAN_DIV equ .20 ;按鈕掃描週期
- ADDR_BUTTON_STATUS equ 0x3A ;按鈕狀態(輸入/出)
- ADDR_BUTTON_COUNT equ 0x3B ;按住計數
- ADDR_BUTTON_S1_PRESSED_COUNT equ 0x50
- ADDR_BUTTON_S2_PRESSED_COUNT equ 0x51
- ADDR_BUTTON_S3_PRESSED_COUNT equ 0x52
- ADDR_BUTTON_S4_PRESSED_COUNT equ 0x53
- VAL_BUTTON_SHORT_PRESSED equ .25
- VAL_BUTTON_LONG_PRESSED equ .25
- ;##################
- ;### 指示燈 ###
- ADDR_RUNNING_DIV equ 0x41
- VAL_RUNNING_DIV equ .166
- ;
- ;***************************************
- ; Program start *
- ;***************************************
- org 0x00 ; reset vector
- nop ; Reserve for MPLAB-ICD
- Initial:
- ;Port Configure
- clrw ; W =0
- clrf PCLATH
- banksel TRISA ; Select to bank1
- movlw 0x06
- movwf ADCON1
- clrf TRISA
- clrf TRISD
- clrf TRISE;TEST
- movlw b'11111111'
- movwf TRISB
- banksel PORTA
- bsf PORTE,0
- bsf PORTE,1
- movlw .0
- movwf ADDR_POLL
- clrf ADDR_CLOCK_SEC
- clrf ADDR_CLOCK_MIN
- clrf ADDR_CLOCK_HUR
- ;clrf PORTD
- movlw VAL_CLOCK_DIV_1
- movwf ADDR_CLOCK_DIV_1 ;
- movlw VAL_CLOCK_DIV_2
- movwf ADDR_CLOCK_DIV_2
- movlw NUM_BUTTON_SCAN_DIV
- movwf ADDR_BUTTON_SCAN_DIV
- clrf ADDR_CLOCK_EN
- bsf ADDR_CLOCK_EN,1 ;第一次執行
- bcf ADDR_CLOCK_EN,0
- movlw VAL_RUNNING_DIV
- movwf ADDR_RUNNING_DIV
- movlw b'10111111'
- ;movwf ADDR_DISP
- ;call bcd_to_segment
- ;movf ADDR_DISP,0
- movwf ADDR_SEG_DIG0
- movwf ADDR_SEG_DIG1
- movwf ADDR_SEG_DIG2
- movwf ADDR_SEG_DIG3
- movwf ADDR_SEG_DIG4
- movwf ADDR_SEG_DIG5
- ;movlw b'10110011'
- movwf ADDR_SEG_DIG6
- movwf ADDR_SEG_DIG7
- movwf ADDR_SEG_DIG5
- movwf ADDR_SEG_DIG4
- movwf ADDR_SEG_DIG3
- movwf ADDR_SEG_DIG2
- ;
- ;************ Main *********************
- ;
- start:
- ;call test
- call task_button ;按鈕工作
- call task_clock ;計數工作
- call task_running_indcator
- call digi_polling ;掃描顯示工作
- call delay_1ms ; Call delay routine
- goto start
- task_clock: ;達目標次數(1秒),計數一次
- btfss ADDR_CLOCK_EN,0
- return
- decfsz ADDR_CLOCK_DIV_1,f
- return
- movlw VAL_CLOCK_DIV_1
- movwf ADDR_CLOCK_DIV_1
- decfsz ADDR_CLOCK_DIV_2,f
- return
- movlw VAL_CLOCK_DIV_2
- movwf ADDR_CLOCK_DIV_2
- call clock
- return
- ;test:
- ; btfss PORTE,0
- ; goto on
- ; goto off
- ; on:
- ; bsf PORTE,0
- ; return
- ; off:
- ; bcf PORTE,0
- ; return
- digi_clear:
- movlw .0
- movwf ADDR_DISP
- call bcd_to_segment
- movwf ADDR_SEG_DIG0
- movwf ADDR_SEG_DIG1
- movwf ADDR_SEG_DIG2
- bcf ADDR_SEG_DIG2,7
- movwf ADDR_SEG_DIG3
- movwf ADDR_SEG_DIG4
- bcf ADDR_SEG_DIG4,7
- movwf ADDR_SEG_DIG5
- return
- clock: ;時鐘
- ;call test
- ;=====SEC======
- incf ADDR_CLOCK_SEC,1
- movlw .60
- subwf ADDR_CLOCK_SEC,0
- btfss STATUS,2
- goto clock_sec_fin
- clrf ADDR_CLOCK_SEC
- call clock_sec_fin
- ;=====MIN======
- min:
- incf ADDR_CLOCK_MIN,1
- movlw .60
- subwf ADDR_CLOCK_MIN,0
- btfss STATUS,2
- goto clock_min_fin
- clrf ADDR_CLOCK_MIN
- call clock_min_fin
- ;=====HOUR======
- hour:
- incf ADDR_CLOCK_HUR,1
- movlw .24
- subwf ADDR_CLOCK_HUR,0
- btfss STATUS,2
- goto clock_hour_fin
- clrf ADDR_CLOCK_HUR
- call clock_hour_fin
- return
- clock_sec_fin:
- movf ADDR_CLOCK_SEC,0
- call val_to_segment
- movf ADDR_SOU,0
- movwf ADDR_SEG_DIG0
- movf ADDR_TEN,0
- movwf ADDR_SEG_DIG1
- return
- clock_min_fin:
- movf ADDR_CLOCK_MIN,0
- call val_to_segment
- movf ADDR_SOU,0
- movwf ADDR_SEG_DIG2
- bcf ADDR_SEG_DIG2,7
- movf ADDR_TEN,0
- movwf ADDR_SEG_DIG3
- return
- clock_hour_fin:
- movf ADDR_CLOCK_HUR,0
- call val_to_segment
- movf ADDR_SOU,0
- movwf ADDR_SEG_DIG4
- bcf ADDR_SEG_DIG4,7
- movf ADDR_TEN,0
- movwf ADDR_SEG_DIG5
- return
- val_to_segment: ;原值轉 7 段顯示碼
- movwf ADDR_SOU
- call BCD
- movf ADDR_SOU,0 ;個位轉SEG
- movwf ADDR_DISP
- call bcd_to_segment
- movwf ADDR_SOU
- movf ADDR_TEN,0 ;十位轉SEG
- movwf ADDR_DISP
- call bcd_to_segment
- movwf ADDR_TEN
- return
- digi_polling: ;掃描顯示
- ;Polling the digits pin
- incf ADDR_POLL
- btfss ADDR_POLL,3
- goto digi_polling_fin
- clrf ADDR_POLL
- digi_polling_fin:
- movlw b'00111111'
- movwf PORTA
- movlw b'00000011'
- movwf PORTE
- movf ADDR_POLL,0
- addwf ADDR_POLL,0
- addwf ADDR_POLL,0
- addwf PCL
- movf ADDR_SEG_DIG7,0
- bcf PORTA,0
- goto seg_out
- movf ADDR_SEG_DIG6,0
- bcf PORTA,1
- goto seg_out
- movf ADDR_SEG_DIG5,0
- bcf PORTA,2
- goto seg_out
- movf ADDR_SEG_DIG4,0
- bcf PORTA,3
- goto seg_out
- movf ADDR_SEG_DIG3,0
- bcf PORTA,4
- goto seg_out
- movf ADDR_SEG_DIG2,0
- bcf PORTA,5
- goto seg_out
- movf ADDR_SEG_DIG1,0
- bcf PORTE,0
- goto seg_out
- movf ADDR_SEG_DIG0,0
- bcf PORTE,1
- goto seg_out
- seg_out:
- movwf PORTD
- return
- bcd_to_segment: ;BCD 轉 7 段碼
- ;Edge Check
- movlw ADDR_DISP
- sublw .9
- btfsc STATUS,0
- return
- movf ADDR_DISP,0
- addwf PCL
- retlw b'11000000' ;0
- retlw b'11111001' ;1
- retlw b'10100100' ;2
- retlw b'10110000' ;3
- retlw b'10011001' ;4
- retlw b'10010010' ;5
- retlw b'10000010' ;6
- retlw b'11111000' ;7
- retlw b'10000000' ;8
- retlw b'10010000' ;9
- BCD: ;轉 BCD 碼
- clrf ADDR_TEN
- BCD_TEN:
- movlw .10
- subwf ADDR_SOU,0
- btfss STATUS,0
- return
- movwf ADDR_SOU
- incf ADDR_TEN,1
- goto BCD_TEN
- task_running_indcator:
- decfsz ADDR_RUNNING_DIV
- return
- movlw VAL_RUNNING_DIV
- movwf ADDR_RUNNING_DIV
- btfss ADDR_CLOCK_EN,0
- return
- comf ADDR_SEG_DIG7,0
- btfsc STATUS,Z
- bcf ADDR_SEG_DIG7,0
- btfsc ADDR_SEG_DIG7,5
- goto rr_1
- movlw b'11111111'
- movwf ADDR_SEG_DIG7
- bcf ADDR_SEG_DIG7,0
- return
- rr_1:
- bsf STATUS,C
- rlf ADDR_SEG_DIG7
- return
- task_button:
- decfsz ADDR_BUTTON_SCAN_DIV,f
- return
- movlw NUM_BUTTON_SCAN_DIV
- movwf ADDR_BUTTON_SCAN_DIV
- button_s1:
- movlw b'00000001'
- andwf PORTB,W
- movwf ADDR_BUTTON_STATUS
- movf ADDR_BUTTON_S1_PRESSED_COUNT,W
- movwf ADDR_BUTTON_COUNT
- call button_general
- movwf ADDR_BUTTON_S1_PRESSED_COUNT
- btfss ADDR_BUTTON_STATUS,3 ;長按檢測
- goto button_s1_fin
- ;### EXECUTE ###
- btfss ADDR_CLOCK_EN,1
- goto Initial
- bcf ADDR_CLOCK_EN,1
- bsf ADDR_CLOCK_EN,0
- call digi_clear
- ;##### END #####
- button_s1_fin:
- btfsc ADDR_CLOCK_EN,1
- goto button_fin
- button_s2:
- movlw b'00000010'
- andwf PORTB,W
- movwf ADDR_BUTTON_STATUS
- movf ADDR_BUTTON_S2_PRESSED_COUNT,W
- movwf ADDR_BUTTON_COUNT
- call button_general
- movwf ADDR_BUTTON_S2_PRESSED_COUNT
- btfss ADDR_BUTTON_STATUS,2 ;短按檢測
- goto button_s3
- ;### EXECUTE ###
- bcf ADDR_CLOCK_EN,0
- ;##### END #####
- button_s3:
- movlw b'00000100'
- andwf PORTB,W
- movwf ADDR_BUTTON_STATUS
- movf ADDR_BUTTON_S3_PRESSED_COUNT,W
- movwf ADDR_BUTTON_COUNT
- call button_general
- movwf ADDR_BUTTON_S3_PRESSED_COUNT
- btfss ADDR_BUTTON_STATUS,2 ;短按檢測
- goto button_s4
- ;### EXECUTE ###
- call digi_clear
- bcf ADDR_CLOCK_EN,0
- clrf ADDR_CLOCK_SEC
- clrf ADDR_CLOCK_MIN
- clrf ADDR_CLOCK_HUR
- ;##### END #####
- button_s4:
- movlw b'00001000'
- andwf PORTB,W
- movwf ADDR_BUTTON_STATUS
- movf ADDR_BUTTON_S4_PRESSED_COUNT,W
- movwf ADDR_BUTTON_COUNT
- call button_general
- movwf ADDR_BUTTON_S4_PRESSED_COUNT
- btfss ADDR_BUTTON_STATUS,2 ;短按檢測
- goto button_fin
- ;### EXECUTE ###
- btfsc ADDR_CLOCK_EN,0
- goto button_fin
- bsf ADDR_CLOCK_EN,0
- movlw VAL_CLOCK_DIV_1
- movwf ADDR_CLOCK_DIV_1
- movlw VAL_CLOCK_DIV_2
- movwf ADDR_CLOCK_DIV_2
- ;##### END #####
- button_fin:
- return
- ;用法port & mask 後帶入 ADDR_BUTTON_STATUS,按住計數器帶入ADDR_BUTTON_COUNT
- ;結束後 ADDR_BUTTON_STATUS ,W為COUNT
- ;...<3> <2> <1> <0>
- ; 0 0 0 1 ;為鬆開狀態
- ; 0 0 1 0 ;為按住狀態
- ; 0 1 0 0 ;為短按
- ; 1 0 0 0 ;為長按
- button_general:
- movf ADDR_BUTTON_STATUS,w
- btfss STATUS,Z
- goto button_off
- button_on:
- clrf ADDR_BUTTON_STATUS
- bsf ADDR_BUTTON_STATUS,1 ;表示按住
- comf ADDR_BUTTON_COUNT,w ;溢位檢查
- btfsc STATUS,Z
- goto button_general_finish
- incf ADDR_BUTTON_COUNT
- movlw VAL_BUTTON_LONG_PRESSED
- subwf ADDR_BUTTON_COUNT,w
- btfss STATUS,C
- goto button_general_finish
- ;差值 > 0 表示長按,利用移入255達到死鎖
- movlw .255
- movwf ADDR_BUTTON_COUNT
- ;### Long Pressed ###
- bsf ADDR_BUTTON_STATUS,3 ;表長按
- bcf ADDR_BUTTON_STATUS,1 ;
- ;####################
- goto button_general_finish
- button_off:
- clrf ADDR_BUTTON_STATUS
- bsf ADDR_BUTTON_STATUS,0 ;表示鬆開
- movf ADDR_BUTTON_COUNT,w
- btfsc STATUS,Z
- goto button_general_finish
- ;Non Zero means the button has been pressed
- movlw VAL_BUTTON_SHORT_PRESSED
- subwf ADDR_BUTTON_COUNT,w
- clrf ADDR_BUTTON_COUNT
- btfsc STATUS,C
- goto button_general_finish
- ;### Long Pressed ###
- bsf ADDR_BUTTON_STATUS,2 ;表短按
- bcf ADDR_BUTTON_STATUS,1
- ;####################
- goto button_general_finish
- ;===== End ======
- button_general_finish:
- movf ADDR_BUTTON_COUNT,w
- return
- ;-------- 100 ms delay routine ----------
- delay_100ms:
- movlw VAL_MS
- movwf count_ms
- loop_ms
- call delay_1ms
- decfsz count_ms,f
- goto loop_ms
- return
- ;-------- 1 ms delay routine -----------
- delay_500us:
- movlw VAL_500u
- movwf count_500u
- dec_loop_500u
- call D_short
- decfsz count_500u,f
- goto dec_loop_500u
- return
- ;-------- 1 ms delay routine -----------
- delay_1ms:
- movlw VAL_US
- movwf count
- dec_loop
- call D_short
- decfsz count,f
- goto dec_loop
- return
- ;
- ;-------- Delay 5uS ------------- 25ms
- D_short
- call D_ret ; 1uS * 4 + 1uS = 10uS
- call D_ret
- call D_ret
- call D_ret
- nop
- nop
- D_ret return
- ;
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement