> At 04:55 9/01/00 -0700, you wrote:
> >On a 16f84, TMR0 prescale = 256, 4MHz crystal, I have the interrupt routine
> >shown below. This once-per-second interrupt occurs every 1.25 seconds or
> >somewhere close to that. It's got to be something obvious, but I'm missing
> >it - what is causing the extra 1/4 second?
> Sorry to come in late on this but I have been away. This works for me
> although I'm sure someone can dot more elegantly.
>
> ;Program "Timer"
> ;General purpose program for counting seconds.
> ;Assumes a 4Mhz Osc (ceramic resonator in my case). If the resonator wobbles
> ;that's not too bad in the long term. If drift causes a problem
> ; get a crystal!
>
> ;Assuming the Osc is accurate at 4 Mhz, the following applies.
> ;Driving TMRO from Osc/4 (1Mhz) and not using the prescaler, an interrupt
> ;occurs every 256 us. The 16 bit counter (tickhi,ticklo) is loaded with
> ;D 3906 which gives a count every 256 x 3906 = 999936 us. 4us short
> ;of a second amounts to 2.1 seconds/non leap year...good enough for me.
>
> ;The constants coarse and fine can be altered to account for variations in
> ;Osc freq. In this example, the value used is
> ;16x256+40=4136 hence my Osc is 4136X256x4= 4.235264 Mhz
>
> ; Assembly code for PIC16F84 microcontroller
> ; CPU configuration
> ; (It's a 16F84, ceramic oscillator,
> ; watchdog timer off, power-up timer on)
>
> processor 16f84
> include <p16f84.inc>
> __config _XT_OSC & _WDT_OFF & _PWRTE_ON
>
> ; Declare variables
> ticklo equ H'10' ;lo byte of tick counter
> tickhi equ H'11' ;hi byte of tick counter
> tmpstatus equ H'12' ;push and pop status reg here during interrupts
> tmpW equ H'13' ;same for W register
> secs equ H'14' ;increments every second
> constant coarse = D'16' ;adjust for variations
> constant fine = D'40' ;in Osc freq
> ; Program
> org 0 ; start at address 0
> goto start
> nop
> nop
> nop
> goto isr ;interrupt service routine
> start:
> bsf STATUS,RP0 ;select bank1
> movlw B'11011000' ;assign timer0 to system clock/4
> movwf OPTION_REG ;and prescaler to the WDT
> bcf STATUS,RP0 ;select bank 0
> movlw B'10100000' ;set global int enable and TMRO int.
> movwf INTCON
> movlw coarse ;coarse adustment
> movwf tickhi ;initialise the 16 bit counter
> movlw fine ;fine adjustment
> movwf ticklo
> clrf PORTA
> clrf PORTB
> ;set port directions for test rig
> bsf STATUS, RP0 ;select bank 1
> movlw B'11111'
> movwf TRISA ;all portA as inputs
> clrf TRISB ;all port B bits as output
> bcf STATUS, RP0 ;select bank 0
> mloop:
> movf secs,W ;do whatever
> movwf PORTB ;you want here.
> goto mloop
>
> isr: ;
> ;Push status and W registers
> movwf tmpW
> swapf STATUS,W
> movwf tmpstatus
> ;service interrupt here
>
> decfsz ticklo,1
> goto endisr
> decfsz tickhi,1
> goto endisr
> ;1 sec is up! increment the seconds counter
> ;and reload the tick counter
> ;We arrive here every 999936 usecs so we lose
> ;2 secs per year...big deal
> incf secs,1
> movlw coarse
> movwf tickhi ;initialise the 16 bit counter
> movlw fine ;
> movwf ticklo
>
> endisr: ;Pop status and W registers
> swapf tmpstatus,W
> movwf STATUS
> movf tmpW,W
> bcf INTCON,2 ;clear interrupt flag
> retfie ;piss off
>
> end
> Bob Jenner
> Trading as RAJE Consulting
> 3 Cahill Cr Nakara NT 0810
> Tel 08 89 455 796
> Fax 08 89 275147
>
http://www.coolspot.com.au