Searching \ for '[PIC]: Zero error 1 second timer - again' 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: 'Zero error 1 second timer - again'.

Exact match. Not showing close matches.
PICList Thread
'[PIC]: Zero error 1 second timer - again'
2001\09\10@152342 by Dwayne Reid

flavicon
face
Good day to all.

I am working on a project where I have to incorporate an accurate timer.  A
lively discussion on this very subject occurred a few months ago and I
started with the results of that discussion.

Both piclist.com and Roman Black's web site have various versions of the
routines.  I started with Roman's page
http://centauri.ezy.net.au/~fastvid/one_sec.htm since it contained a nice
description of the concepts.

Roman's routine is described timer tick rates of 256 or 65,536 cycles.  It
was trivial to change the constants to work with my timer tick rate of 1024
cycles (4 MHz oscillator, pre-scale set at 1:4).

In the process of doing the above, I found that the timer routines could be
shortened somewhat.

Roman's routine is:

;enter here every tick
    tstf    bres_mid            ; first test for mid==0
    skpnz                       ; nz = no underflow needed
      decf  bres_hi,f           ; z, so is underflow, so dec the msb

    decfsz  bres_mid,f          ; dec the mid byte (subtract 256)
      goto  main_loop           ; nz, so definitely not one second yet.

    tstf    bres_hi             ; test hi for zero too
    skpz                        ; z = both hi and mid are zero, is one second!
      goto  main_loop           ; nz, so not one second yet.
;1 sec timer elapsed - reload the counters and do whatever you want


I found that I could accomplish the same thing with:
;enter here every tick
    decfsz      bres_mid,F       ;dec mid byte
      incf      bres_hi,F        ;correct following dec unless reach 0
    decfsz      bres_hi,F        ;dec upper byte
      goto      main_loop        ;zero only if upper 2 bytes reached 0
;1 sec timer elapsed - reload the counters and do whatever you want

Note: my version requires that the constant loaded into 'bres_hi' be 1
higher than calculated - this is because the test for 0 happens whenever
the mid byte reaches 0 instead of when it wraps under to 0xFF.

The other change I made was to highlight a potential error:  Roman assumes
that he can just re-load the upper bytes of the counter with the constants,
add the lowest byte constant to the LS byte counter, then propagate a carry
from the LS byte to the mid byte.  If the mid byte constant happens to be
0xFF, any carry would also have to be propagated into the high byte.

Since the constants are just that - constants - the easy way is to test the
mid-byte constant at compile time and add the extra code if required.

The following routine is snipped from the program I'm currently working on
- the labels and register names are different from Roman's code.

; The following RTCC routines are based upon a discussion held on the PICLIST
; and contain ideas expressed by Bob Ammerman and Roman Black.  This version
; is based upon Roman's code but was modifed for a tick period of 1024 cycles
; instead of 256 cycles.
; The routine is a type of Bresenham algorithm where a constant representing
; each tick period is subtracted from a multi-byte counter that was pre-loaded
; with the desired period.  When the upper bytes of the counter reach zero, the
; desired period has been reached and the lowest byte contains the remainder of
; that period.  The counter is reloaded by adding the constant to it - this is
; easy since all but the lowest byte are known to be zero.  Since the counter
; is reset by adding the constant, the remainder from the previous period trims
; the next period.  The long term error is zero.
; To keep the arithmetic simple, the constant representing the current period
; has been set to 256 (dec).  Subtracting 256 from a multi-byte number is
; trivial: decrement the 2nd lowest byte by 1 and propagate any borrows upward.
;
; The desired period is 1 second == 1,000,000 cycles with 4 MHz clock.  Since
; the timer tick rate is 1024 cycles instead of the desired decrement value of
; 256 cycles, the pre-load constant is divided by that ratio (1:4) and becomes
; 250,000 (== 03 D0 90 hex).  The size of the constant shows that 3 bytes are
; needed for the counter.

; 1 sec timer based on 1.024 ms ticks.  This version by Dwayne Reid
S_CONST_L       EQU 0x90        ;
S_CONST_M       EQU 0xD0        ;
S_CONST_H       EQU (0x03+1)    ;+1 'cuz of dec & test instead of test & dec

    decfsz      S_CNT_M,F                ;dec mid byte
      incf      S_CNT_H,F                ;correct following dec unless reach 0
    decfsz      S_CNT_H,F                ;dec upper byte
      goto      Not1sec                  ;zero only if upper 2 bytes reached 0

;1 sec timer tick - first, reload counter
    movlw       S_CONST_L                ;low byte counter contains remainder
    addwf       S_CNT_L,F

    movlw       S_CONST_M
    skpnc                                ;propagate carry if needed
      movlw     (S_CONST_M+1)
    addwf       S_CNT_M,F

    movlw       S_CONST_H
  if (S_CONST_M)==0xFF                   ;carry can happen only if mid
constant is 0xFF
    skpnc
      movlw     (S_CONST_H+1)
  endif
    addwf       S_CNT_H,F

    bsf         _TICK_SEC
Not1sec                                  ;done!


I hope someone else finds this useful.

dwayne


Dwayne Reid   <spam_OUTdwaynerTakeThisOuTspamplanet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax

Celebrating 17 years of Engineering Innovation (1984 - 2001)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Do NOT send unsolicited commercial email to this email address.
This message neither grants consent to receive unsolicited
commercial email nor is intended to solicit commercial email.

--
http://www.piclist.com hint: The list server can filter out subtopics
(like ads or off topics) for you. See http://www.piclist.com/#topics


2001\09\11@103950 by Roman Black

flavicon
face
Dwayne Reid wrote:

{Quote hidden}

Very nice! :o)
Another optimisation is to use some clock
speeds and timer periods that result in a
ZERO value in bottom (bres_low) byte of the
variable. Like with a 16MHz clock is 4,000,000
counts to an exact second, and:
4,000,000 is 0x 3D 09 00 (low byte is zero!)
As this is a common crystal freq for PICs this
can give a VERY fast optimised 1 sec timer. :o)

> The other change I made was to highlight a potential error:  Roman assumes
> that he can just re-load the upper bytes of the counter with the constants,
> add the lowest byte constant to the LS byte counter, then propagate a carry
> from the LS byte to the mid byte.  If the mid byte constant happens to be
> 0xFF, any carry would also have to be propagated into the high byte.
>
> Since the constants are just that - constants - the easy way is to test the
> mid-byte constant at compile time and add the extra code if required.

I did cover this in the code comments, in all cases
"mid" is known, so you know if it is 0xFF or not.
Great idea to include the extra code selected
automatically at compile time!! Another good idea
would be to test for both carrys, I did it this way
in another project, which allows the PIC to change
periods on the fly, to any period, which is handy.


{Quote hidden}

This is very nice Dwayne, and its really handy to
get accurate periods in a few clock cycles worth
of timing code isn't it?

I've used similar systems now a few times. Also as
these periods can be incorporated into an existing
interrupt of any frequency, you can use a couple of
variables to get differing frequencies, all generated
from your original interrupt with a few code words.

Do you mind if I add your letter and code to the
samples on my web page?
-Roman

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


2001\09\11@133209 by Dwayne Reid

flavicon
face
At 11:52 PM 9/11/01 +1000, Roman Black wrote:

>Do you mind if I add your letter and code to the
>samples on my web page?
>-Roman

I'd be honored!  Please do.

dwayne



Dwayne Reid   <.....dwaynerKILLspamspam@spam@planet.eon.net>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax

Celebrating 17 years of Engineering Innovation (1984 - 2001)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Do NOT send unsolicited commercial email to this email address.
This message neither grants consent to receive unsolicited
commercial email nor is intended to solicit commercial email.

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


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