PIC Microcontoller Delay Method

Delay X cycles (11-327690) inclusive by Mike McLaren, K8LH

Here is an updated DelayCy() subsystem for generating precise "fixed" or "constant" delays which can be specified directly in cycles or specified in microseconds or milliseconds using operand multipliers. The subsystem uses a 9 word subroutine and a macro that generates an additional four instructions each time it's invoked.

Here is an example of how you might use the DelayCy() subsystem;

;
;  example "beep" routine generates a precise 500 Hz tone using 
;  almost any clock (4, 8, 12, 16, or 20 MHz)
;
        bsf     beep,5          ; do 32 msec new press beep
dobeep  movf    PORTA,W         ; read PORTA
        xorlw   b'00001000'     ; toggle speaker bit
        movwf   PORTA           ; toggle speaker pin
        DelayCy(1*msecs-6)      ; 1 msec minus 6 cycle loop time
        decfsz  beep,F          ; done?  yes, skip, else
        goto    dobeep          ; toggle speaker pin again


Here's the actual DelayCy() subsystem (macro and subroutine). The subroutine features Mike Bond's 16 bit 5 cycle timing loop using just four instructions and four 'nop' instructions in front to accommodate the delay%5 cycles. Note that the assembler preprocessor does most of the work for us in the macro.

You will need to set the 'clock' equate to your clock frequency (in MHz) if you intend to use the 'usecs' and/or 'msecs' delay operand multipliers.

	radix	dec
clock	equ	4		; setup 4, 8, 12, 16, or 20 MHz
usecs	equ	clock/4		; cycles/microsecond multiplier
msecs	equ	clock/4*1000	; cycles/millisecond multiplier
;
;  DelayCy() macro
;
DelayCy macro	pCycles		; cycles, 11..327690 range
	movlw	high((pCycles-11)/5)+1
	movwf	TMRH
	movlw	low ((pCycles-11)/5)
	call	uDelay-((pCycles-11)%5)
	endm
;
;  example code for simulation testing
;
SimTest	DelayCy(10*msecs-3)	; 10 msecs minus 3 cycles
	nop			; put simulator break point here
;
;  uDelay(11..327690) subroutine     Mike McLaren, K8LH, Mar '09
;
;  9 words, 1 RAM variable, 14-bit core
;
	nop			; entry for (delay-11)%5 == 4     |B0
	nop			; entry for (delay-11)%5 == 3     |B0
	nop			; entry for (delay-11)%5 == 2     |B0
	nop			; entry for (delay-11)%5 == 1     |B0
uDelay	addlw	-1		; subtract 5 cycle loop time	  |B0
	skpc			; borrow? no, skip, else	  |B0
	decfsz	TMRH,F		; done?  yes, skip, else	  |B0
	goto	uDelay		; do another loop		  |B0
	return			;				  |B0

Comments: