In another thread ("Relocatable code") someone (Mr RB, actually) proposed this method of generating delays using a delay subroutine:
While this will definitely work, there is what I believe is a better way: easier and less code.
What I've done is to create a delay routine that uses a variable, set before being called, as a loop count to control the delay length. So instead of looping in the code, as in Roman's method, all you do is load the variable with the desired delay length value, then call the routine.
Here's my code in SX-28 assembly language: my apologies if this isn't familiar, but it's similar enough to PIC code to be understandable, hopefully. (The SX uses "skip"-type branches instead of the more familiar conditional jumps.) First, the delay subroutine:
Next, here's how you invoke it:
See how easy that is?
I should point out that the way this works is a little indirect with this processor, since the delay routine loads the delay value into a system register, the RTCC (real-time clock counter) which gets decremented in an interrupt service routine (ISR); however, you could use this same scheme by simply decrementing the variable and checking for zero directly in the subroutine.
Now, because of the limit of the maximum value of a variable and the "atomic delay unit" (i.e., the shortest delay possible, if you set the delay variable to 1), I found I had to create both short delay and long delay routines. Still very simple to implement and use.
I like stuff like this, since I'm kind of a fanatic about making code as compact and fast as possible ...
Code:
movlw 230
delay_2point3
call delay_10mS
sublw 1
btfss STATUS,C
goto delay_2point3
While this will definitely work, there is what I believe is a better way: easier and less code.
What I've done is to create a delay routine that uses a variable, set before being called, as a loop count to control the delay length. So instead of looping in the code, as in Roman's method, all you do is load the variable with the desired delay length value, then call the routine.
Here's my code in SX-28 assembly language: my apologies if this isn't familiar, but it's similar enough to PIC code to be understandable, hopefully. (The SX uses "skip"-type branches instead of the more familiar conditional jumps.) First, the delay subroutine:
Code:
;*******************************************************
; Short delay subroutine (~40-255 usec)
;
; On entry:
; W = 256-count to delay (in microseconds)
;
; This routine waits for the flag bit set by the ISR (when the
; RTCC rolls over) to go high.
;*******************************************************
ShortDelay
MOV RTCC_FR, W ;Load RTCC
CLRB Flag.FLAG_RTCC ;Clear rollover flag bit
dloop SB Flag.FLAG_RTCC ;Has bit been set yet?
JMP dloop ;No, keep checking
RET ;Yes, return.
Next, here's how you invoke it:
Code:
MOV W, #DELAY_40uS
CALL ShortDelay
See how easy that is?
I should point out that the way this works is a little indirect with this processor, since the delay routine loads the delay value into a system register, the RTCC (real-time clock counter) which gets decremented in an interrupt service routine (ISR); however, you could use this same scheme by simply decrementing the variable and checking for zero directly in the subroutine.
Now, because of the limit of the maximum value of a variable and the "atomic delay unit" (i.e., the shortest delay possible, if you set the delay variable to 1), I found I had to create both short delay and long delay routines. Still very simple to implement and use.
I like stuff like this, since I'm kind of a fanatic about making code as compact and fast as possible ...