PIC Microcontoller Delay Method

Delay X cycles (12-65547) for 18F chips by Mike McLaren, K8LH

Here's a 16-bit DelayTcy() routine for 18F' devices (16-bit instruction core). The basic routine borrows from Scott Datallo's 3 cycle loop timing example and uses only 8 words of program memory and 1 RAM variable. The DelayTcy macro does much of the work by preprocessing the passed "delay" constant parameter value during assembly. Specify delays in either "microseconds" using the DelayUS() "front end" macro or in "cycles" using the DelayTcy() macro.


;******************************************************************
;                                                                 *
;  DelayUS() Macro                    Mike McLaren, K8LH, Jun'07  *
;                                                                 *
;  simple macro "front end" for a 16-bit DelayTcy() routine that  *
;  allows you to specify delays in 'usecs' instead of 'cycles'.   *
;                                                                 *
;  the 'usec' delay range for a 16-bit target DelayTcy() routine  *
;  is based on clock frequency;                                   *
;                                                                 *
;     4 MHz,  1   cycle /usec, 12..65536 usecs delay              *
;     6 MHz,  1.5 cycles/usec,  8..43690 usecs delay              *
;     8 MHz,  2   cycles/usec,  6..32768 usecs delay              *
;    10 MHz,  2.5 cycles/usec,  5..26214 usecs delay              *
;    12 MHz,  3   cycles/usec,  4..21845 usecs delay              *
;    16 MHz,  4   cycles/usec,  3..16384 usecs delay              *
;    20 MHz,  5   cycles/usec,  3..13107 usecs delay              *
;    24 MHz,  6   cycles/usec,  2..10922 usecs delay              *
;    28 MHz,  7   cycles/usec,  2.. 9362 usecs delay              *
;    32 MHz,  8   cycles/usec,  2.. 8192 usecs delay              *
;    36 MHz,  9   cycles/usec,  2.. 7281 usecs delay              *
;    40 MHz, 10   cycles/usec,  2.. 6553 usecs delay              *
;    48 MHz, 12   cycles/usec,  1.. 5461 usecs delay              *
;                                                                 *
;  the DelayUS() macro requires the following two equates;        *
;                                                                 *
clock           equ   16        ; see list above
cycles_per_usec equ  (10000/(4000/clock))
;                                                                 *
;  DelayUS() macro                                                *
;                                                                 *
DelayUS macro   usecs           ; delay range: see list above
        DelayTcy((usecs*cycles_per_usec)/10)
        endm
;                                                                 *
;******************************************************************
;******************************************************************
;                                                                 *
;  DelayTcy(), 12..65547 Tcy          Mike McLaren, K8LH, Jun'07  *
;                                                                 *
;  requires the use of constant operands known at assembly time!  *
;                                                                 *
;  8 words, 1 RAM variable, 16-bit core                           *
;                           ^^^^^^^^^^^                           *
;  the DelayTcy() macro produces four instructions;               *
;                                                                 *
DelayTcy macro  delay           ; parameter range 16..65547
        movlw   ~(high(delay-12))
        movwf   TMRH
        movlw   low(delay-12)
        rcall   DelayLo-((delay%3)*2)
        endm
;                                                                 *
;  code for simulation testing;                                   *
;                                                                 *
SimTest
;       DelayUS(13)             ; use the DelayUS() macro, or
        DelayTcy(2000)          ; use the DelayTcy() macro
        nop                     ; put simulator breakpoint here
;                                                                 *
;******************************************************************
;                                                                 *
Delay.18F
        nop                     ; entry point for delay%3 == 2
        nop                     ; entry point for delay%3 == 1
DelayLo                         ; entry point for delay#3 == 0
        addlw   -3              ; subtract 3 cycle loop time
        bc      DelayLo         ;
DelayHi
        addlw   -3              ; subtract 3 cycle loop time
        incfsz  TMRH,F          ; delay done? yes, skip, else
        bra     DelayLo         ; loop again
        return                  ;
;                                                                 *
;******************************************************************