Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 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_DELAY_1MS_COUNT equ .40 ; 1ms delay valum
- ADDR_DELAY_1MS_COUNT equ 0x20 ; Defined temp reg. for 1ms delay
- VAL_DELAY_100MS_COUNT equ .100
- ADDR_DELAY_100MS_COUNT equ 0x21 ; Defined delay reg.
- VAL_DELAY_CUSTOM_COUNT equ .80 ; 1ms delay valum
- ADDR_DELAY_CUSTOM_COUNT equ 0x22 ; Defined temp reg. for 1ms delay
- ADDR_DISP equ 0x26 ;轉 7 Segment
- ADDR_BCD_SOU equ 0x27 ;轉BCD (個位)
- ADDR_BCD_SOU2 equ 0x2F ;轉BCD (2組)
- ADDR_BCD_TEN equ 0x28 ;轉BCD 十位
- ADDR_BCD_HUN equ 0x23 ;轉BCD 百位
- ADDR_BCD_TEMP equ 0x24
- ADDR_MULTIPLIER equ 0x2B
- ADDR_MULTIPLICAND equ 0x2C
- ;### Temp For Interrupt
- ADDR_TEMP_STATUS equ 0x2D
- ADDR_TEMP_W equ 0x2E
- ;ADDR_DISPLAY_MODE equ 0x30 ;<0> = 初始 <1> = 時鐘 <2> = 顯示紀錄
- ;### 時鐘 ###
- ADDR_CLOCK_DIV_1 equ 0x31;
- VAL_CLOCK_DIV_1 equ .121 ;83*3=249 125*2=250
- ADDR_CLOCK_DIV_2 equ 0x32
- VAL_CLOCK_DIV_2 equ .8
- ADDR_CLOCK_SEC equ 0x33 ;秒
- ADDR_CLOCK_MIN equ 0x34 ;分
- ADDR_CLOCK_HUR equ 0x35 ;小時
- ;### 按鈕處理 ###
- ADDR_BUTTON_SCAN_DIV equ 0x36 ;按鈕掃描週期
- NUM_BUTTON_SCAN_DIV equ .20 ;按鈕掃描週期
- ADDR_BUTTON_STATUS equ 0x37 ;按鈕狀態(輸入/出)
- ADDR_BUTTON_COUNT equ 0x38 ;按住計數
- ADDR_BUTTON_S0_PRESSED_COUNT equ 0x39
- ADDR_BUTTON_S1_PRESSED_COUNT equ 0x3A
- ADDR_BUTTON_S2_PRESSED_COUNT equ 0x3B
- ADDR_BUTTON_S3_PRESSED_COUNT equ 0x3C
- VAL_BUTTON_SHORT_PRESSED equ .25
- VAL_BUTTON_LONG_PRESSED equ .25
- BUTTON_RELEASE equ .0
- BUTTON_PRESSED equ .1
- BUTTON_SHORT equ .2
- BUTTON_LONG equ .3
- ;##################
- ADDR_POLL equ 0x25 ;掃描顯示
- VAL_POLL_START equ .0
- VAL_POLL_END equ .7
- ADDR_SEG_DIG0 equ 0x40 ;第0位顯示
- ADDR_SEG_DIG1 equ 0x41 ;第1位顯示
- ADDR_SEG_DIG2 equ 0x42 ;第2位顯示
- ADDR_SEG_DIG3 equ 0x43 ;第3位顯示
- ADDR_SEG_DIG4 equ 0x44 ;第4位顯示
- ADDR_SEG_DIG5 equ 0x45 ;第5位顯示
- ADDR_SEG_DIG6 equ 0x46 ;第6位顯示
- ADDR_SEG_DIG7 equ 0x47 ;第7位顯示
- ;### Timer Configuration ###
- VAL_TMR0_INIT equ .178
- VAL_TMR1_INIT_L equ 0x2C
- VAL_TMR1_INIT_H equ 0xCF
- VAL_TMR2_INIT equ .28
- ;### Temp For Interrupt
- ADDR_TEMP_STATUS equ 0x2D
- ADDR_TEMP_W equ 0x2E
- ;### ADC Configuration ###
- ADDR_ADC_CHANNEL equ 0x48
- VAL_ADC_DIV equ .100
- ADDR_ADC_DIV equ 0x49
- VAL_ADC_CHANNEL_LEN equ .1
- ADDR_ADC_VAL_0 equ 0x4A
- ADDR_ADC_VAL_1 equ 0x4B
- VAL_ADC_CON1 equ b'00001110'
- VAL_ADC_TRISA_SAMPLING equ b'00000001'
- VAL_ADC_TRISA_ORIGINAL equ b'00000001'
- ;### Wave Generator ###
- VAL_WAVE_PIN equ .7
- ;
- ;***************************************
- ; Program start *
- ;***************************************
- org 0x0 ; reset vector
- goto Initial
- org 0x4
- goto INTSUB
- Initial:
- ;Port Configure
- clrw ; W =0
- clrf PCLATH
- banksel TRISA ; Select to bank1
- ;=== Port Configuration ===
- movlw 0x06
- movwf ADCON1
- movlw VAL_ADC_TRISA_ORIGINAL
- movwf TRISA
- clrf TRISD
- clrf TRISE;TEST
- movlw b'01111111'
- movwf TRISB
- ;=== Timer , INT ===
- ;Ext,TMR0,RBPU
- movlw B'00000110'
- movwf OPTION_REG
- ; <1> TMR2IE: TMR2 to PR2 Match Interrupt Enable bit
- ; <0> TMR1IE: TMR1 Overflow Interrupt Enable bit
- movlw B'00000011'
- movwf PIE1
- movlw VAL_TMR2_INIT
- movwf PR2
- banksel PORTA
- ;=== Timer , INT ===
- movlw B'11100000'
- movwf INTCON
- movlw B'0110101'
- movwf T1CON
- movlw B'01111110' ;16x16
- movwf T2CON
- clrf PIR1
- movlw VAL_TMR0_INIT
- movwf TMR0 ; Timer 0 Value
- movlw VAL_TMR1_INIT_L
- movwf TMR1L
- movlw VAL_TMR1_INIT_H
- movwf TMR1H
- clrf TMR2
- ;=== Timer , INT ===
- 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
- 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
- bsf PORTB,7
- clrf ADDR_BCD_SOU2
- clrf ADDR_ADC_CHANNEL
- ;
- ;************ Main *********************
- ;
- Loop:
- ;call test
- call task_adc
- call task_button ;按鈕工作
- call task_clock ;計數工作
- call task_digi_polling ;掃描顯示工作
- call delay_1ms ; Call delay routine
- goto Loop
- ;***************************************
- ; Tasks *
- ;***************************************
- task_digi_polling: ;掃描顯示
- ;Polling the digits pin
- incf ADDR_POLL
- movf ADDR_POLL,W
- sublw VAL_POLL_END
- btfsc STATUS,C
- goto task_digi_polling_fin
- movlw VAL_POLL_START
- movwf ADDR_POLL
- task_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_DIG0,0
- bcf PORTE,1
- goto seg_out
- movf ADDR_SEG_DIG1,0
- bcf PORTE,0
- goto seg_out
- movf ADDR_SEG_DIG2,0
- bcf PORTA,5
- goto seg_out
- movf ADDR_SEG_DIG3,0
- bcf PORTA,4
- goto seg_out
- movf ADDR_SEG_DIG4,0
- bcf PORTA,3
- goto seg_out
- movf ADDR_SEG_DIG5,0
- bcf PORTA,2
- goto seg_out
- movf ADDR_SEG_DIG6,0
- bcf PORTA,1
- goto seg_out
- movf ADDR_SEG_DIG7,0
- bcf PORTA,0
- goto seg_out
- seg_out:
- movwf PORTD
- return
- task_adc:
- btfsc ADCON0,GO
- return
- btfsc PIR1,ADIF
- goto adc_result
- adc_start:
- decfsz ADDR_ADC_DIV,f
- return
- movlw VAL_ADC_DIV
- movwf ADDR_ADC_DIV
- movf ADDR_ADC_CHANNEL,w
- addwf ADDR_ADC_CHANNEL,w
- addwf PCL
- movlw b'01000001'
- goto adc_start_fin
- movlw b'01001001'
- goto adc_start_fin
- adc_start_fin:
- movwf ADCON0
- ;重新設定PORT
- banksel TRISA ; Select to bank1
- movlw VAL_ADC_CON1
- movwf ADCON1
- movlw VAL_ADC_TRISA_SAMPLING
- movwf TRISA
- banksel PORTA
- bsf ADCON0,GO
- return
- adc_result:
- movlw ADDR_ADC_VAL_0
- movwf FSR
- movf ADDR_ADC_CHANNEL,w
- addwf FSR
- movf ADRESH,w
- movwf INDF
- bcf PIR1,ADIF
- banksel TRISA ; Select to bank1
- movlw 0x06
- movwf ADCON1
- movlw VAL_ADC_TRISA_ORIGINAL
- movwf TRISA
- banksel PORTA
- incf ADDR_ADC_CHANNEL
- movlw VAL_ADC_CHANNEL_LEN
- subwf ADDR_ADC_CHANNEL,w
- btfss STATUS,Z
- return
- clrf ADDR_ADC_CHANNEL
- return
- task_display_handle: ;顯示時間至7段
- ;更新秒
- movf ADDR_CLOCK_SEC,0
- call val_to_segment
- movf ADDR_BCD_SOU,0
- movwf ADDR_SEG_DIG0
- movf ADDR_BCD_TEN,0
- movwf ADDR_SEG_DIG1
- ;更新分
- movf ADDR_CLOCK_MIN,0
- call val_to_segment
- movf ADDR_BCD_SOU,0
- movwf ADDR_SEG_DIG2
- bcf ADDR_SEG_DIG2,7 ;小數點
- movf ADDR_BCD_TEN,0
- movwf ADDR_SEG_DIG3
- clrf ADDR_BCD_SOU2
- movf ADDR_ADC_VAL_0,0
- movwf ADDR_BCD_SOU
- call BCD_HUN_2B
- movf ADDR_BCD_SOU,w
- call val_to_segment
- movf ADDR_BCD_SOU,w
- movwf ADDR_SEG_DIG4
- movf ADDR_BCD_TEN,w
- movwf ADDR_SEG_DIG5
- movf ADDR_BCD_HUN,w
- call val_to_segment
- movf ADDR_BCD_SOU,w
- movwf ADDR_SEG_DIG6
- movf ADDR_BCD_TEN,w
- movwf ADDR_SEG_DIG7
- ;更新時
- ;movf ADDR_CLOCK_HUR,0
- ;call val_to_segment
- ;movf ADDR_BCD_SOU,0
- ;movwf ADDR_SEG_DIG4
- ;bcf ADDR_SEG_DIG4,7
- ;movf ADDR_BCD_TEN,0
- ;movwf ADDR_SEG_DIG5
- return
- task_clock: ;達目標次數(1秒),計數一次
- 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
- call task_display_handle
- return
- task_button:
- decfsz ADDR_BUTTON_SCAN_DIV,f
- return
- movlw NUM_BUTTON_SCAN_DIV
- movwf ADDR_BUTTON_SCAN_DIV
- button_s1: ;開始計數
- movlw b'00000010'
- 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,BUTTON_SHORT ;短按檢測
- goto button_s1_fin
- ;### EXECUTE ###
- goto Initial
- ;##### END #####
- goto button_s1_fin
- button_s1_fin:
- return
- ;***************************************
- ; Other *
- ;***************************************
- 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
- clock: ;時鐘
- ;call test
- ;=====SEC======
- incf ADDR_CLOCK_SEC,1
- movlw .60
- subwf ADDR_CLOCK_SEC,0
- btfss STATUS,2
- goto clock_fin
- clrf ADDR_CLOCK_SEC
- ;=====MIN======
- min:
- incf ADDR_CLOCK_MIN,1
- movlw .60
- subwf ADDR_CLOCK_MIN,0
- btfss STATUS,2
- goto clock_fin
- clrf ADDR_CLOCK_MIN
- ;=====HOUR======
- hour:
- incf ADDR_CLOCK_HUR,1
- movlw .24
- subwf ADDR_CLOCK_HUR,0
- btfss STATUS,2
- goto clock_fin
- clrf ADDR_CLOCK_HUR
- clock_fin:
- return
- val_to_segment: ;原值轉 7 段顯示碼
- movwf ADDR_BCD_SOU
- call BCD
- movf ADDR_BCD_SOU,0 ;個位轉SEG
- movwf ADDR_DISP
- call bcd_to_segment
- movwf ADDR_BCD_SOU
- movf ADDR_BCD_TEN,0 ;十位轉SEG
- movwf ADDR_DISP
- call bcd_to_segment
- movwf ADDR_BCD_TEN
- 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
- ;用法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,BUTTON_PRESSED ;表示按住
- 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 ###
- bcf ADDR_BUTTON_STATUS,BUTTON_PRESSED ;
- bsf ADDR_BUTTON_STATUS,BUTTON_LONG ;表長按
- ;####################
- goto button_general_finish
- button_off:
- clrf ADDR_BUTTON_STATUS
- bsf ADDR_BUTTON_STATUS,BUTTON_RELEASE ;表示鬆開
- 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 ###
- bcf ADDR_BUTTON_STATUS,BUTTON_PRESSED
- bsf ADDR_BUTTON_STATUS,BUTTON_SHORT ;表短按
- ;####################
- goto button_general_finish
- ;===== End ======
- button_general_finish:
- movf ADDR_BUTTON_COUNT,w
- return
- INTSUB:
- ;Backup Register
- movwf ADDR_TEMP_W ;Backup W
- swapf STATUS,w ; Backup STATUS (swaped)
- movwf ADDR_TEMP_STATUS
- ;### Exec ###
- btfsc INTCON,TMR0IF
- goto INT_T0
- btfsc PIR1,TMR1IF
- goto INT_T1
- btfsc PIR1,TMR2IF
- goto INT_T2
- goto INTSUB_RESTORE
- ;############
- ;Restore Register
- INT_T0:
- INT_T0_RESTORE:
- bcf INTCON,TMR0IF
- movlw VAL_TMR0_INIT
- movwf TMR0
- goto INTSUB_RESTORE
- INT_T1:
- INT_T1_RESTORE:
- bcf PIR1,TMR1IF
- movlw VAL_TMR1_INIT_H
- movwf TMR1H
- movlw VAL_TMR1_INIT_L
- movwf TMR1L
- goto INTSUB_RESTORE
- INT_T2:
- call task_wave
- INT_T2_RESTORE:
- bcf PIR1,TMR2IF
- goto INTSUB_RESTORE
- INTSUB_RESTORE:
- swapf ADDR_TEMP_STATUS,w
- movwf STATUS
- swapf ADDR_TEMP_W,f
- swapf ADDR_TEMP_W,w
- bcf INTCON,INTF ;Clear Flag
- RETFIE
- task_wave:
- btfss PORTB,VAL_WAVE_PIN
- goto wave_on
- bcf PORTB,VAL_WAVE_PIN
- return
- wave_on:
- bsf PORTB,VAL_WAVE_PIN
- return
- BCD: ;轉 BCD 碼
- clrf ADDR_BCD_TEN
- BCD_TEN:
- movlw .10
- subwf ADDR_BCD_SOU,0
- btfss STATUS,0
- return
- movwf ADDR_BCD_SOU
- incf ADDR_BCD_TEN,1
- goto BCD_TEN
- BCD_HUN_2B:
- clrf ADDR_BCD_HUN
- BCD_HUN_LOOP:
- movlw .100
- subwf ADDR_BCD_SOU,0
- btfsc STATUS,C
- goto BCD_HUN_NOBARROW
- movwf ADDR_BCD_TEMP
- movlw .1
- subwf ADDR_BCD_SOU2,W
- btfss STATUS,C
- return
- movwf ADDR_BCD_SOU2
- movf ADDR_BCD_TEMP,W
- movwf ADDR_BCD_SOU
- incf ADDR_BCD_HUN
- goto BCD_HUN_LOOP
- BCD_HUN_NOBARROW:
- movwf ADDR_BCD_SOU
- incf ADDR_BCD_HUN
- goto BCD_HUN_LOOP
- MULTI:
- clrw
- MULTI_LOOP
- addwf ADDR_MULTIPLICAND,0
- decfsz ADDR_MULTIPLIER,1
- goto MULTI_LOOP
- return
- ;-------- 100 ms delay routine ----------
- delay_100ms:
- movlw VAL_DELAY_100MS_COUNT
- movwf ADDR_DELAY_100MS_COUNT
- loop_ms
- call delay_1ms
- decfsz ADDR_DELAY_100MS_COUNT,f
- goto loop_ms
- return
- ;-------- Cutom ms delay routine -----------
- delay_Custom:
- movlw VAL_DELAY_CUSTOM_COUNT
- movwf ADDR_DELAY_CUSTOM_COUNT
- dec_loop_500u
- call D_short
- decfsz ADDR_DELAY_CUSTOM_COUNT,f
- goto dec_loop_500u
- return
- ;-------- 1 ms delay routine -----------
- delay_1ms:
- movlw VAL_DELAY_1MS_COUNT
- movwf ADDR_DELAY_1MS_COUNT
- dec_loop
- call D_short
- decfsz ADDR_DELAY_1MS_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