For this project ... you should not be using interrupts.
Especially not ON INTERRUPT. There's no guaranteed timing with ON INTERRUPT.
207 isn't a good value to load in the Timer.
Since the Timer will normally overflow in 65536 counts, you just need to set bit-7 of the high byte to make it overflow in 32768 counts.
With a 32768 Hz crystal, it will overflow in exactly 1 second.
Timer1 doesn't free-run. You need to stop and start it so that you can synchronize the Timer0 Gate output with Timer1's 1 second window.
Since the PIC's changed now, the oscillator's changed and interrupts are introduced ...
I think I'll just post my code for the 877A simulation in post #5.
Hopefully you can convert it for your needs with a different PIC.
Code:
; DT_FREQy.pbp
;
; Created : Mon Feb 3 2014
; Processor : PIC16F877A
; Compiler : PicBasic Pro 3.0
;----[Device Configuration]--(See manual section 4.9)---------------------------
#CONFIG
__config _HS_OSC & _WDT_OFF & _PWRTE_OFF & _BODEN_OFF & _LVP_OFF & _CPD_OFF & _WRT_OFF & _DEBUG_OFF & _CP_OFF
#ENDCONFIG
;----[DEFINEs]------------------------------------------------------------------
DEFINE OSC 20
DEFINE LCD_DREG PORTD ; LCD data port
DEFINE LCD_DBIT 4 ; LCD data starting bit 0 or 4
DEFINE LCD_RSREG PORTD ; LCD register select port
DEFINE LCD_RSBIT 2 ; LCD register select bit
DEFINE LCD_EREG PORTD ; LCD enable port
DEFINE LCD_EBIT 3 ; LCD enable bit
DEFINE LCD_BITS 4 ; LCD bus size 4 or 8
DEFINE LCD_LINES 2 ; LCD Number lines on LCD
DEFINE LCD_COMMANDUS 2000 ; LCD Command delay time in us
DEFINE LCD_DATAUS 50 ; LCD Data delay time in us
;----[Aliases]------------------------------------------------------------------
Timer1 VAR WORD EXT : @Timer1 = TMR1L
TMR0IF VAR INTCON.2
TMR0CS VAR OPTION_REG.5
TMR1IF VAR PIR1.0
TMR1CS VAR T1CON.1 ; Timer1 Clock Source Select bit
T1OSCEN VAR T1CON.3 ; Timer1 Oscillator Enable Control bit
TMR1ON VAR T1CON.0 ; Timer1 On bit
T1OSI VAR PORTC.1 ; 32768 Hz input pin
PSCLKOUT VAR PORTA.3 ; pin to clock out the remaining prescaler
PSA VAR OPTION_REG.3 ; Prescaler Assignment bit
;----[Variables]----------------------------------------------------------------
Result VAR WORD[2] ; Final 32-bit Frequency measurement
T0overflow VAR Result[1] ; Counts Timer0 overflows (HighWord of the result)
T0value VAR Result.BYTE1 ; Final Timer0 value
PScount VAR Result.BYTE0 ; Final Timer0 Prescaler value
FreqHigh VAR WORD ; Top five digits of the decimal result
FreqLow VAR WORD ; Bottom 3 digits of the decimal result
MeasCount VAR WORD ; Counts number of measurements
;----[Initialize]---------------------------------------------------------------
ADCON1 = 7 ; All Digital
CMCON = 7
T1OSCEN = 1 ; Start Timer1 oscillator
PAUSE 250 ; LCD Power-Up delay
LCDOUT $FE,1,"DT's FREQy"
MeasCount = 0 ; clear the measurement count
;----[Main Program Loop]--------------------------------------------------------
Main:
GOSUB MeasureFreq ; Get a Frequency Measurement
GOSUB DisplayFreq ; Display the Frequency
MeasCount = MeasCount + 1 ; increment and display measurement count
LCDOUT $FE,$94,"Meas = ", DEC MeasCount
GOTO Main
;----[Measure frequency on T0CKI]-----------------------------------------------
MeasureFreq:
LOW PSCLKOUT ; prevent signal from getting to Timer0
PSA = 0 ; Prescaler is assigned to the Timer0 module
TMR0CS = 1 ; Transition on T0CKI pin
TMR1CS = 1 ; Timer1 Clock source = T1CKI (T1OSC)
TMR1ON = 0 ; Stop Timer1
TMR0IF = 0 ; Clear Timer0 overflow flag
T0overflow = 0 ; Clear Timer0 overflow count
TMR0 = 0 ; Clear Timer0 value
Timer1 = $FFFF ; Timer1 overflows on next cycle of 32768 Hz clock
TMR1IF = 0 ; Clear Timer1 overflow flag
TMR1ON = 1 ; Start Timer1 1 sec. period
WHILE !TMR1IF : WEND ; Synchronize to 32768 clock
INPUT PSCLKOUT ; Start counting freq input
Timer1.15 = 1 ; Set Timer1 to 32768 for 1 Sec. period
TMR1IF = 0 ; Clear Timer1 overflow flag
WHILE !TMR1IF ; while 1 sec. window is open ---|
IF TMR0IF THEN ; count TMR0 overflows | This section
T0overflow = T0overflow + 1 ; | does the actual
TMR0IF = 0 ; | 1-Sec measurement
ENDIF ; | Window
WEND ; ---|
LOW PSCLKOUT ; Stop further counting
T0value = TMR0 ; get Timer0 value
PScount = 0 ; Clock out remaining prescaler
WHILE TMR0 = T0value ; until TMR0 value changes
HIGH PSCLKOUT
PAUSEUS 3
LOW PSCLKOUT
PAUSEUS 3
PScount = PScount + 1
WEND
PScount = -PScount ; negate to get prescaler count
RETURN
;----[Display frequency on LCD]-------------------------------------------------
DisplayFreq
R2 = Result ; Load Result into PBP's system vars for DIV32
R0 = Result[1]
FreqHigh = DIV32 1000 ; get left most 5 digits
FreqLow = R2 ; remainder (R2) is right 3 digits
LCDOUT $FE,$C0,"Freq = "
IF FreqHigh > 0 THEN ; if any left digits
LCDOUT DEC FreqHigh, DEC3 FreqLow," " ; display both left and right
ELSE ; otherwise
LCDOUT DEC FreqLow," " ; display only right digits
ENDIF
RETURN
END
Bookmarks