Searching \ for '[PIC:] Preloading Timer0' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/time.htm?key=time
Search entire site for: 'Preloading Timer0'.

Exact match. Not showing close matches.
PICList Thread
'[PIC:] Preloading Timer0'
2004\02\03@091129 by Anno, Jeff

flavicon
face
Hello Pic People,

I am working on a cycle time monitoring project that uses a 16F628 (4.000
MHz, external crystal) with an LCD (16X2) and the built in USART (async at
19200).  When a button is pressed, the time (in milliseconds) is reported to
the computer and the time is reset. I am using TMR0 with a 1:4 TMR0 Rate. I
would like to get an interrupt every 1.0000 ms, but right now it is not
quite correct. Everything seems to be working except getting the exact
interrupt time.

I think that this is true (please let me know if it's not):

Since an instruction cycle runs every 4th clock cycle, at 4MHz, that gives
me 1,000,000 instruction cycles/second.  I am using a 1:4 TMR0 Rate, that
gives me a 250,000 clock to the TMR0 register.  Since the TMR0 register is
8-bit register, an interrupt is generated when rolling over from 0xFF to
0x00 (is this 256 interrupts or 255?). So I get an interrupt every 0.001024
seconds (256 / 250,000).

I read that the TMR0 register can be preloaded with any 8-bit value. So I
thought if I preloaded it with a  0x06 I would get an interrupt every
millisecond (250 / 250000 = 0.001000).

If I preload the TMR0 register the reported time value is totally wrong.  If
I don't preload the value then the actual time is = (reported time from pic
* 1.024) + (constant).  The constant is a fixed value to compensate for
writing to the Serial Port.

This is the portion of my code where I preload the TMR0 register

bcf INTCON,T0IF          ; Clear the TMR0 interrupt flag
movlw D'6'               ; Preload TMR0 with a 6 to get
movwf TMR0               ;  250 inst cycles/interrupt (vs 256)
retfie                   ; Finished, reset GIE


Sorry for the long e-mail, but I didn't want to exclude any relevant info.
Any suggestions?

Thanks in advance,
Jeff

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@093449 by Nigel Orr

flavicon
face
pic microcontroller discussion list wrote:

> This is the portion of my code where I preload the TMR0 register
>
> bcf INTCON,T0IF          ; Clear the TMR0 interrupt flag
> movlw D'6'               ; Preload TMR0 with a 6 to get
> movwf TMR0               ;  250 inst cycles/interrupt (vs 256)
> retfie                   ; Finished, reset GIE

Have you corrected for the time between the interrupt firing and your ISR
getting to the above section?  Count the number of instruction cycles above
the 'movwf TMR0', divide by 4 (your prescale) and add that to the '6'
above.  Don't forget the interrupt latency (typically 3 instruction
cycles).

Nigel
--
Nigel Orr, Design Engineer                 spam_OUTnigelTakeThisOuTspamaxoninstruments.co.uk
Axon Instruments Ltd., Wardes Road,Inverurie,Aberdeenshire,UK,AB51 3TT
              Tel:+44 1467 622332 Fax:+44 1467 625235
                  http://www.axoninstruments.co.uk

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@095606 by Olin Lathrop

face picon face
Anno, Jeff wrote:
> I am working on a cycle time monitoring project that uses a 16F628
> (4.000 MHz, external crystal) with an LCD (16X2) and the built in
> USART (async at 19200).  When a button is pressed, the time (in
> milliseconds) is reported to the computer and the time is reset. I am
> using TMR0 with a 1:4 TMR0 Rate. I would like to get an interrupt
> every 1.0000 ms, but right now it is not quite correct. Everything
> seems to be working except getting the exact interrupt time.

Timer 2 is better suited to this task.  I often use timer 2 to produce a
periodic 1mS interrupt.  At 4MHz oscillator, you have 1000 instructions per
mS.  A period of 250 with a prescaler of 4 will do this.

Take a look at my TIMER2_USEC and TIMER2_SETUP_INTR macros in STD.INS.ASPIC
at http://www.embedinc.com/pic.  These make it very easy to set up timer 2
for this purpose.  You define the oscillator frequency in the main include
file, then specify the desired interrupt period in uS and the macros do most
everything else.  This also means your code won't break when some time later
the 4MHz oscillator is changed to 8MHz, 20MHz, or something else.

{Quote hidden}

You want to add a value into timer 0 each interrupt, not preload it.
However, I sortof remember that this resets the prescaler counter, so you
can't get deterministic results with the prescaler engaged.  This means you
will have to take several timer 0 interrupts and keep a counter to get to
the 1mS period.  Again, use timer 2.  That's what it's for.


*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@095607 by Alan B. Pearce

face picon face
.Since an instruction cycle runs every 4th clock cycle, at 4MHz,
>that gives me 1,000,000 instruction cycles/second.  I am using
>a 1:4 TMR0 Rate, that gives me a 250,000 clock to the TMR0 register.
>Since the TMR0 register is 8-bit register, an interrupt is
>generated when rolling over from 0xFF to 0x00 (is this 256 interrupts
>or 255?). So I get an interrupt every 0.001024
>seconds (256 / 250,000).

Personally I would use a 4.096MHz crystal, and then you do not need to worry
about reloading the timer register.

However I suspect your problem is related to the 2 cycle delay when
reloading the register before the timer starts counting again, possibly
combined with not dealing with the offset count between the interrupt point,
and the count value when you reload.

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@122808 by Scott Dattalo

face
flavicon
face
On Tue, 3 Feb 2004, Anno, Jeff wrote:

> Hello Pic People,
>
> I am working on a cycle time monitoring project that uses a 16F628 (4.000
> MHz, external crystal) with an LCD (16X2) and the built in USART (async at
> 19200).  When a button is pressed, the time (in milliseconds) is reported to
> the computer and the time is reset. I am using TMR0 with a 1:4 TMR0 Rate. I
> would like to get an interrupt every 1.0000 ms, but right now it is not
> quite correct. Everything seems to be working except getting the exact
> interrupt time.

If changing the oscillator frequency or switching to TMR2 do not work then
you may wish to consider another option. At every TMR0 interrupt, a
quantum of time will have passed by. You can easily accumulate these
quanta and convert the time to milliseconds:

TMR0_interrupt:

   increment TMR0_RollOver flag

...


Main code:

 while(TMRO_RollOver flag is greater than 0) {

   decrement TMR0 RollOver flag

   accumulated time = accumulated time + time for a TMR0 rollover

 }

The reason for the counter is that you don't have to be too concerned
about missing an interrupt. Of course, this assumes that the TMR0 rollover
rate is faster than a millisecond. Or you may wish to place this untested
code directly in the interrupt routine.

 radix  dec

 ; uS_hi, uS_lo -- time in microseconds
 ; mS_hi, mS_lo -- time in milliseconds

TMRO_ROLLOVER_TIME  EQU  256 * (TMR0_PRESCALE+1) * FOSC / 1000000 / 4

  MOVLW   LOW(TMRO_ROLLOVER_TIME)
  ADDWF   uS_lo,F

  RLF     known_zero,F    ; pick up the carry
  ADDLW   HIGH(TMRO_ROLLOVER_TIME)
  ADDWF   us_hi,F

; if more than a thousand micro seconds have gone by, then
; subtract 1000 from the micro second counter and increment
; the millisecond counter:

  MOVLW   LOW(-1000)     ;add -1000 is the same as subtracting
  ADDWF   uS_lo,W        ;
  RLF     known_zero,W   ;pick up the borrow
  ADDLW   HIGH(-1000)    ;
  ADDWF   us_hi,W        ;

  SKPC
   RETURN ;or GOTO...    ; less than 1000 uS
                         ; have been accumulated

  ; subtract 1000 from the uS counter
  MOVWF   us_hi          ; W already holds the high byte.
  MOVLW   LOW(-1000)     ;redo the low byte subtraction
  ADDWF   us_lo,F

  INCF    ms_lo,F        ; Increment the millisecond counter
  SKPNZ
   INCF   ms_hi,F

 ;(if the millisecond counter is more than 16-bits wide, then
 ; an extra SKPNZ / INCF  can extend the counter.

Scott

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@143536 by James Nick Sears

picon face
If you are using MPLAB the stopwatch feature is nice for getting rid of
those off by a few cycles timing errors.

Nick

{Original Message removed}

2004\02\03@162742 by Andrew Warren

flavicon
face
Anno, Jeff <.....PICLISTKILLspamspam@spam@mitvma.mit.edu> wrote:

> If I preload the TMR0 register the reported time value is totally
> wrong.  If I don't preload the value then the actual time is =
> (reported time from pic * 1.024) + (constant).  The constant is a
> fixed value to compensate for writing to the Serial Port.

Jeff:

Your math is all correct, but you're missing some subtle details:

   a) There's a certain amount of non-constant interrupt latency
   time for which you need to compensate.

   b) Writing to TMR0 stops the timer for two cycles.

   c) Writing to TMR0 resets the prescaler.

To fix problem a), don't use MOVWF to reload the register; use ADDWF
instead.  This also compensates for the time taken by your serial-
port code, so there's no longer any need to incorporate that time
into your reload value.

To fix problems b) and c), you need to know exactly where in its
count your prescaler is, so you can write to it two cycles before the
TMR0 register increments.  Since you can't read the prescaler value
directly, nor sample and the test the TMR0 register fast enough to
catch the cycle in which it increments, you need to do something like
this to reload TMR0 in your interrupt-service routine:

   ; On entry, value of TMR0 and the prescaler are unknown.

       BTFSS TMR0,0  ; Wait for TMR0's bit 0 to be
       GOTO  $-1     ; set, then wait 2 cycles.

   ; At this point, TMR0 and prescaler values
   ; must be one of the following:
   ;
   ;    TMR0    Prescaler
   ;  xxxxxxx1      2
   ;  xxxxxxx1      3
   ;  xxxxxxx0      0
   ;  xxxxxxx0      1

       BTFSC TMR0,0  ; Wait either 3 or 4 cycles.
       GOTO  $+1     ;
       NOP           ;

   ; At this point, TMR0 and prescaler values
   ; must be one of the following:
   ;
   ;    TMR0    Prescaler
   ;  xxxxxxx0      2
   ;  xxxxxxx0      3
   ;  xxxxxxx1      0

       BTFSS TMR0,0  ; Wait either 4 or 5 cycles.
       GOTO  $+1     ;
       GOTO  $+1     ;

   ; At this point, TMR0 and prescaler values
   ; must be one of the following:
   ;
   ;    TMR0    Prescaler
   ;  xxxxxxx1      3
   ;  xxxxxxx0      0

       BTFSC TMR0,0  ; Wait either 2 or 3 cycles.
       GOTO  $+1     ;

   ; At this point, TMR0 and prescaler value
   ; must be:
   ;
   ;    TMR0    Prescaler
   ;  xxxxxxx0      2

       GOTO  $+1     ;Waste two cycles.

   ; At this point, TMR0 increments.

       MOVLW RELOAD  ; Reload TMR0.  These two
       ADDWF TMR0    ; instructions take 2 cycles,
                     ; then TMR0 stops for 2 cycles,
                     ; so TMR0 will start counting
                     ; again just at the right time,
                     ; 4 cycles after the previous
                     ; increment.

As usual, this code hasn't been tested or even assembled; I just
typed it into my email client.  Let me know if it works.

-Andy

=== Andrew Warren -- aiwspamKILLspamcypress.com
=== Principal Design Engineer
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@163825 by Anno, Jeff

flavicon
face
Andy,

Thank You!!!!  This helped tremendously, I'll try it tomorrow.

Thanks to EVERYONE who helped out.  This list is the best!

-Jeff

{Original Message removed}

2004\02\03@173231 by Andrew Warren

flavicon
face
Anno, Jeff <.....PICLISTKILLspamspam.....mitvma.mit.edu> wrote:

> Thank You!!!!  This helped tremendously, I'll try it tomorrow.

   You're welcome, Jeff, I hope it works.

   Thinking about it now, I realize that it might be off by one...
   You may have to add RELOAD+1 instead of RELOAD.  Not sure,
   though, and don't have any time today to go through it to be
   sure.

   -Andy

=== Andrew Warren -- EraseMEaiwspam_OUTspamTakeThisOuTcypress.com
=== Principal Design Engineer
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@174516 by Olin Lathrop

face picon face
Andrew Warren wrote:
> Thinking about it now, I realize that it might be off by one...
> You may have to add RELOAD+1 instead of RELOAD.  Not sure,
> though, and don't have any time today to go through it to be
> sure.

I know timer 0 can be made to work here, but I still haven't heard a good
reason the OP can't use timer 2.  It's got hardware specifically for
creating a periodic interrupt, and would be "set and forget" in this
application.  What's the problem?


*****************************************************************
Embed Inc, embedded system specialists in Littleton Massachusetts
(978) 742-9014, http://www.embedinc.com

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\03@181805 by Andrew Warren

flavicon
face
Olin Lathrop <PICLISTspamspam_OUTmitvma.mit.edu> wrote:

> I know timer 0 can be made to work here, but I still haven't heard
> a good reason the OP can't use timer 2.  It's got hardware
> specifically for creating a periodic interrupt, and would be "set
> and forget" in this application.  What's the problem?

   There's no "problem"... But he didn't ask about Timer2, so I
   didn't give him an answer that involved Timer2.

   -Andy

=== Andrew Warren -- @spam@aiwKILLspamspamcypress.com
=== Principal Design Engineer
=== Cypress Semiconductor Corporation
===
=== Opinions expressed above do not
=== necessarily represent those of
=== Cypress Semiconductor Corporation

--
http://www.piclist.com hint: The PICList is archived three different
ways.  See http://www.piclist.com/#archives for details.

2004\02\04@102039 by John Hansen

picon face
At 02:54 PM 2/3/2004 +0000, you wrote:
>.Since an instruction cycle runs every 4th clock cycle, at 4MHz,
> >that gives me 1,000,000 instruction cycles/second.
>
>However I suspect your problem is related to the 2 cycle delay when
>reloading the register before the timer starts counting again, possibly

One easy way to set this up is the use the stopwatch in the MPLAB
simulator.  Instead of counting instruction cycles you can simply run the
code between any two points and let the stopwatch tell you how much time
has elapsed.  Then you can adjust the value you are putting into the timer
until you get the amount of time that you want.

John Hansen

--
http://www.piclist.com#nomail Going offline? Don't AutoReply us!
email KILLspamlistservKILLspamspammitvma.mit.edu with SET PICList DIGEST in the body

More... (looser matching)
- Last day of these posts
- In 2004 , 2005 only
- Today
- New search...