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 ; ; * ;******************************************************************