hallo allemaal,
ik gebruik een PIC16F877 met een 20MHZ kristal.
om lage frequenties te meten met timer1 als counter,
heb ik een interrupt nodig heb van 1 seconden.
nu probeer ik dat te doen met timer0.
Fosc/4= 4MHz / prescaler / timer0 = interrupt frequentie
prescaler staat op /16
preload timer0 = 6 (256-6=250)
maar dit werkt niet zoals gepland
; Fosc = 20000000 Hz ( 20MHz)
; Fosc/4 = 4000000 Hz ( 4MHz)
; 4MHz/16 = 250000 Hz (250KHz)
; 250KHz/250= 1000 Hz ( 1KHz)
; 1000/1000 = 1 Hz
ik ben al dagen bezig om uit te zoeken hoe dit komt.
daar ben ik net achter gekomen.
timer0 blijft doorlopen.
daar tel ik 6 bij op.
en juist hier gaat het fout!
in de datasheet staat het volgende:
Note: Writing to TMR0, when the prescaler is
assigned to Timer0, will clear the prescaler
count, but will not change the prescaler
assignment.
de prescaler wordt dus gewist!!
en dat was niet de bedoeling, hierdoor klopt de timing niet meer.
hoe moet ik dit gaan oplossen?
ik heb echt geen idee meer.
hopelijk kunnen jullie mij helpen.
hieronder voorbeeld van mijn code:
code:
;***************************************************************************************************************************
; interrupt routine
;***************************************************************************************************************************
org 04h ; begin van interrupt
movwf INT_tempW ;;
swapf STATUS,w ;;
clrf STATUS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movwf INT_tempSTAT ;; opslaan van waardes in W, STATUS en PCLATH register ;;
movf PCLATH,w ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movwf INT_tempPCLATH ;;
clrf PCLATH ;;
;---------------begin van interrupt routine------------------
btfsc INTCON,T0IF ; T0IF: TMR0 Overflow Interrupt Flag bit (must be cleared in software)
goto ADD_CLOCK_PULS
btfsc INTCON,INTF ; INTF: RB0/INT External Interrupt Flag bit (must be cleared in software)
goto $+2;xxx
btfsc INTCON,RBIF ; RBIF: RB Port Change Interrupt Flag bit (must be cleared in software)
nop;goto ;xxx
bcf INTCON,T0IF ; clear TMR0 Overflow Interrupt Flag bit (must be cleared in software)
bcf INTCON,INTF ; clear RB0/INT External Interrupt Flag bit (must be cleared in software)
bcf INTCON,RBIF ; clear RB Port Change Interrupt Flag bit (must be cleared in software)
;---------------einde van interrupt routine------------------
INT_return movf INT_tempPCLATH,w;;
movwf PCLATH ;;
swapf INT_tempSTAT,w ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
movwf STATUS ;; herstellen van waardes in W, STATUS en PCLATH register ;;
swapf INT_tempW,f ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
swapf INT_tempW,w ;;
bcf INTCON,RBIF ;;
retfie ;;
;***************************************************************************************************************************
; init clock
;***************************************************************************************************************************
INIT_CLOCK
BANK1
movlw b'00000011' ; set prescular at /16 on internal osc.
movwf OPTION_REG ; 4000000/16= 250000 CYCLES. /250= 1000 CYCLES
BANK0
clrf seconden
clrf minuten
clrf uren
clrf dagen
clrf TMR0 ; timer0 interrupt will come when timer0 overflows.! (only on startop uP)
movlw 0x03 ; add value of 1000 to devider
movwf CLK_devider_H
movlw 0xe8
movwf CLK_devider_L
bsf INTCON,T0IE ; Enables the TMR0 interrupt
bsf INTCON,GIE ; Enable Global Interrupt.
return
;***************************************************************************************************************************
; clock ADD INT PULS
;***************************************************************************************************************************
ADD_CLOCK_PULS ; from INTERRUPT
LED_gr_ON
LED_gr_OFF
bcf INTCON,T0IF ; clear TMR0 Overflow Interrupt Flag bit (must be cleared in software)
decfsz CLK_devider_L,f ; Fosc = 20000000 Hz ( 20MHz)
goto $+4 ; Fosc/4 = 4000000 Hz ( 4MHz)
decfsz CLK_devider_H,f ; 4MHz/16 = 250000 Hz (250KHz)
goto $+2 ; 250KHz/250= 1000 Hz ( 1KHz)
goto $+4 ; 1000/1000 = 1 Hz
movlw .5 ; preset timer0 to count to 250 (256-6=250)
addwf TMR0
goto INT_return
movlw 0x03
movwf CLK_devider_H
movlw 0xe8
movwf CLK_devider_L
movlw .5 ; preset timer0 to count to 250 (256-6=250)
addwf TMR0
call MAIN_COUNTER_TMR1 ; take counter sample
;***************************************************************************************************************************
; add e second to clock
;***************************************************************************************************************************
CLOCK_ADD
bsf log_byte,0 ; mus be cleared after used.
incf seconden,f
movlw .60
xorwf seconden,w
btfss STATUS,Z
goto DONE_A_second
clrf seconden
incf minuten,f
movlw .60
xorwf minuten,w
btfss STATUS,Z
goto DONE_A_second
clrf minuten
incf uren,f
movlw .24
xorwf uren,w
btfss STATUS,Z
goto DONE_A_second
clrf uren
incf dagen,f
DONE_A_second
goto INT_return
;***************************************************************************************************************************
; END
;***************************************************************************************************************************