ON 20030521@8:08:58 AM at page: http://www.piclist.com/techref/member/JWN-hotmail-f41/index.htm JWN-hotmail-f41 John W Nall Code:
;
;   General delay routine, for delaying 1 millisecond, 10 milliseconds,
;   100 milliseconds, or 1 second.  Written specifically for the 18F452 chip
;   running at 40Mhz.
;
;   As written, the routine is set up to be assembled as relocable object code,
;   and linked with other object routines.  To use as absolute code, just extract
;   the pertinent code and paste it into your routine.

;   Use:  call d_1_ms (or any of the other entry points) from your routine
;
;   Any change in clock speed will require changes to the constants used.
;
;   We are using Timer0 for the delay, loading a constant value into the counter which
;   the timer increments once each instruction cycle.  Therefore, the only things that
;   need to be changed are the constants.  Since the delay routine offers a choice of
;   1ms, 10ms, 100ms or 1 second delays, there are four constants generated.  Each constant
;   represents 65535 minus the number of instructions cycles to be performed until the
;   specific time value is reached.  Since the timer increments a 16-bit counter and sets
;   a bit when the counter overflows, then we merely have to start the value of the counter
;   at 65535 less the number of instruction cycles.  
;
;   EXAMPLE:  With a 40MHZ clock (10 MHz crystal using the PLL option of the 18F452), the
;   instructions are executed with a 10Mhz clock (40MHZ/4) since the clock speed is divided
;   down by a factor of 4.  Therefore, 10 million instructions are executed every second.
;   One instruction is executed in 100 nanoseconds.
;                             6          -6           -9
;          (1 second)/(10 * 10 ) = .1 * 10   = 100 * 10
;
;   Incrementing a 16-bit counter every 100 nanoseconds, it would not take very long before it
;   overflows.  Luckily, Timer0 has the capability to prescale, using factors of 2, 4, 8, 16,
;   32, 64, 128 or 256.  If we use the 256 prescale, then the counter is only incremented
;   once for each 256 instruction cycles, which makes things a bit more doable.  Specifically,
;   the 16-bit counter would not overflow for 1.664 seconds, if we started at zero.
;
;   If, on the other hand, we used the 128 prescale factor, the timer would overflow in 832
;   milliseconds.  So we would have to make another run to get up to 1 second (although it
;   would work for the others).  So we use 256 to make sure we can get everything up to and
;   including 1 second during just one run of timer.
;
;   Now, since we are dividing our actual clock speed (10 MIPS) by 256, the effective
;   clock speed (for the purpose of incrementing the counter) will be 39.0625 KHz.
;                  6
;          (10 * 10 )/256 = 39062.5 instructions per second
;
;   This means, of course, that rather than being incremented every 100 nanoseconds,
;   the counter is incremented every 25.6 microseconds
;                                  3                -3           -6
;          (1 second)/(39.0625 * 10  ) = 0.0256 * 10  = 25.6 * 10
;
;   Since 39062.5 instructions execute in one second, then what we need to do is to set our
;   one second counter to 65535 - 39063 (rounding up) = 26472.  If it starts there, and we
;   then activate the timer, it will do an additional 39063 increments and set the overflow
;   bit.
;
;   This makes it easy to set the constants for 100 ms, 10 ms and 1 ms, since we just have
;   to divide by some power of ten.  
;
;         100 ms = .1 seconds, 10 ms = .01 seconds, and 1 ms = .001 seconds.
;
;	To get the figure for 100 ms, we have 65535 - 3906 = 61629.
;      
;   Likewise, for 1 ms, the constant is 65496
;                 10 ms, 65144
;                1 second, 26472
;
;   All of which means that we have finally gotten to the routine.

               #include <p18f452.inc>
                global   d_1_ms, d_10_ms, d_100_ms, d_1_sec

		radix dec
;
;	Generate the constants which will be loaded into TMR0L and TMR0H
;	These will have to be changed if a different clock speed is used.
;	Just use the technique as outlined above to calculate new constants.
;	Also note the "radix dec" statement above.  These are decimal numbers. :)

d_1ms_h         equ      65496/256             ;  generate the high order byte			
d_1ms_l         equ      65496 % 256           ;  and the low order byte (modulus 256)
d_10ms_h        equ      65144/256
d_10ms_l        equ      65144 % 256	
d_100ms_h       equ      61629/256
d_100ms_l       equ      61629 % 256
d_1sec_h        equ      26472/256
d_1sec_l        equ      26472 % 256

d_code          code
d_1_ms          movlw   d_1ms_h                 ; if called to delay 1 millisecond
                movwf   TMR0H
                movlw   d_1ms_l
                bra     delay

d_10_ms         movlw   d_10ms_h                ; if called to delay 10 milliseconds
                movwf   TMR0H
                movlw   d_10ms_l
                bra     delay

d_100_ms        movlw   d_100ms_h               ; if called to delay 100 milliseconds
                movwf   TMR0H
                movlw   d_100ms_l
                bra     delay

d_1_sec         movlw   d_1sec_h                ; if called to delay 1 second
                movwf   TMR0H
                movlw   d_1sec_l
delay           movwf   TMR0L                   ; saved a few instructions :-)

;
;		Set the necessary bits for the timer
;
                clrf    T0CON                   ; start with a virgin
;
;	16-bit timer, use internal instruction clock, use prescaler, 1:256
;
                movlw   B'00000111'
                iorwf   T0CON,1
                bcf     INTCON,TMR0IF           ; clear the overflow bit
tlp1            btfsc   INTCON,TMR0IF
                bra     tlp1                    ; make sure overflow bit is clear
                bsf     T0CON,TMR0ON            ; enable the timer
;
;	Now, just hang out, looking cool, and wait for the bit to be set
;

tlp2            btfss   INTCON,TMR0IF
                bra     tlp2
                bcf     T0CON,TMR0ON             ; disable timer
                return
                end
ON 20030521@11:05:21 AM at page: http://www.piclist.com/techref/member/jwn-hotmail-f41/index.htm JMN-EFP-786 James Newton edited the page. Difference: http://www.piclist.com/techref/diff.asp?url=H:\techref\member\jwn-hotmail-f41\index.htm&version=2 ON 20030521@11:09:08 AM at page: http://www.piclist.com/techref/member/JWN-hotmail-f41/TIMER_TUTORIAL.htm JMN-EFP-786 James Newton edited the page. Difference: http://www.piclist.com/techref/diff.asp?url=H:\techref\member\JWN-hotmail-f41\TIMER_TUTORIAL.htm&version=0