 
Also:
James Cameron says:
These SXs are just too fast, we often need a way to have the processor wait around for a while. A series of NOP (no operation) instructions is straightforward, but wasteful of instruction memory. A counted loop is the next common trick, because that lets us tune it.But what are some of the more exotic ways to delay?
) The Common NOP, a delay for one instruction cycle
DELAY nop ; delay one cycleAdvantages: extremely simple, obvious, maintainable, scaleable.
Disadvantages: is it really there for a reason?
) The Common Loop, four times the initial value
DELAY mov W, #95 ;1 380 cycle delay mov COUNTER, W ;2 decsz COUNTER ;3 7 11 15 jmp $-1 ;4 8 12 16Advantages: fairly simple, maintainable, scaleable up to 1024 cycles (counter initialized with zero); after that go for a nested loop.
Disadvantages: costs one file register; though there is a variant using just the W register.
) The Novel GOTO, three instruction cycles in one instruction
jmp $+1 ;three cycle delayAdvantages: third the space of three NOPs.
Disadvantages: obscure unless commented.
) The Call to Nowhere
org 0 jmp MAIN delay6 ret ;six cycle delay function [...] DELAY call delay6Advantages: 1/6 the space of six NOPs, the RET can be reused by other code.
Disadvantages: implementation separate from use, can look odd, uses one stack level.Scott Dattalo says:
...if you want a 4-cycle [ed: in compatible mode] single-instruction delay: call some_return_in_your_code Of course, you run the risk of stack overflow on [some processors]
) The Double Call to Nowhere, 12 cycles
org 0 jmp MAIN delay12 call delay6 delay6 ret [...] DELAY call delay12Advantages: looks simple, allows various size delays to be rapidly constructed during prototyping.
Disadvantages: uses two stack levels.[ed: See the "Stack Recursive Delay" below]
) The Do Something Useful Extension to the Common Loop, six times the initial value
DELAY mov W, #95 ;1 mov COUNTER, W ;2 mov W, TRISM ;3 9 15 fetch port direction mirror mov !RB, w ;4 10 16 reapply it decsz COUNTER ;5 11 17 jmp $-3 ;6 12 18Advantages: allows useful functionality to be placed within the delay.
Disadvantages: increased convolution of code, lower maintainability.
) The Long Delay Using Timer, more of a technique than a code fragment, set the timer, wait for it to roll over.
Advantages: immune to distortion by interrupts, easily scaled using a prescaler, even possible to tune the delay by modifying the preload value.
Disadvantages: allocates a timer.Paul B. Webster says:
I feel that many applications (real-time control, clocks) resolve to a fundamental "tick" or hierarchy thereof, often around a millisecond, which method {7} provides. Counting a thousand of these gives a second, at which point a train of countdowns (semaphores) can lead to various housekeeping actions i.e., if T1 then { T1--; if T1 == 0 then action1 };On the 1 ms "ticks" also, a debounce uses a counter which counts down from 20 (20 ms) to verify a keypress/ release. Other countdowns in ms are used for playing tunes or "tick", "Click" or "blip" noises.
It is highly undesirable to pre-load or fiddle with the TMR0 when you are using it this way, firstly because it interferes with the prescaler in a very inconvenient fashion, and secondly as the 1 ms countdowns can be used for a 500 Hz tone while the TMR0 MSB can be copied to a port for a 1 kHz tone, bit 6 for a 2 kHz tone, etc., controlled as above in even numbers of milliseconds.
You can similarly, wait on those individual bits by polling, for sub- delays. A sub-delay on bit 3 toggling could be used to time a phase accumulator (32 kHz clock) to generate quite a complete range of square wave tones.
So, you may say that method "uses" a timer-counter, but I submit that in a well-designed application, you get an awful lot of "use" out of it!
) The Watchdog Delay, go to sleep and get woken by the watchdog.
Advantages: extremely simple technique, can be varied by changing the WDT prescaler ratio.
Disadvantages: difficult to calibrate.
[ed: Set up a type of state machine that records where the processor should contine executing code after the reset. Make sure you clear it in your non-timed routines. Also see Using the watchdog timer to sense temperature]
) The Data EEPROM Delay, a typically 10ms delay that can be triggered by writing to data EEPROM and waiting for the interrupt.
Advantages: tests the endurance of the EEPROM.
Disadvantages: tests the endurance of the EEPROM.
Tony Nixon says:
  Here's a a simple example [for the SX at 50Mhz], but it won't be accurate
  to the second, so you may have to tweak it. Perhaps you could use it as a
  basis for your code.
  
        mov     W, #x   ; x = hours delay
        mov     hours, W
        call    Hours_Delay
        ; rest of code continues
Hours_Delay
        call    Hour_Delay
        decsz   hours
        jmp     Hours_Delay
        ret
Hour_Delay
        mov     W, #60
        mov     mins, W
Rst_Loop
        mov     W, #60
        mov     secs, W
Hour_Loop
        call    Second_Delay
        ;
        ; maybe some processing in here
        ;
        decsz   secs
        jmp     Hour_Loop
        decsz   mins
        jmp     Rst_Loop
        ret
Second_Delay
        mov     W, #5           ;50e6 / 4 = 12 500 000 = 100*100*250*5
        mov     NbHi, W
        mov     W, #250
        mov     NbLo, W
        mov     W, #100
        mov     NaHi, W
        mov     W, #100
        mov     NaLo, W
DeLoop0
        decsz   NaLo            ;delay1 = NaLo*4 - 2
        jmp     DeLoop0         ;
        decsz   NaHi            ;delay2 = (NaLo*4 - 2) * NaHi + (NaHi*4 - 2) =
        jmp     DeLoop0         ;=  NaLo*NaHi*4 + NaHi*2 - 2
        decsz   NbLo            
        jmp     DeLoop0         
        decsz   NbHi            ;totaldelay ~= 4*NaLo*NaHi*NbLo*NbHi
        jmp     DeLoop0
        ret
The name of the lable you call indicates the number of cycles (Convert cycles to time) that will be executed before returning. This uses an amazingly small number of bytes and is probably more effecient than inline loops or nop's if you are going a lot of little delays of varying times through out your code.
Delay131072     call    Delay16384      ; uses 6 stack levels
Delay114688     call    Delay16384
Delay98304      call    Delay16384
Delay81920      call    Delay16384
Delay65536      call    Delay16384
Delay49152      call    Delay16384
Delay32768      call    Delay16384
Delay16384      call    Delay2048       ;uses 5 stack levels
Delay14336      call    Delay2048
Delay12288      call    Delay2048
Delay10240      call    Delay2048
Delay8192       call    Delay2048
Delay6144       call    Delay2048
Delay4096       call    Delay2048
Delay2048       call    Delay256        ;uses 4 stack levels
Delay1792       call    Delay256
Delay1536       call    Delay256
Delay1280       call    Delay256
Delay1024       call    Delay256
Delay768        call    Delay256
Delay512        call    Delay256
Delay256        call    Delay32 ;uses 3 stack levels
Delay224        call    Delay32
Delay192        call    Delay32
Delay160        call    Delay32
Delay128        call    Delay32
Delay96         call    Delay32
Delay64         call    Delay32
Delay32         call    Delay8  ;uses 2 stack levels
Delay24         call    Delay8
Delay16         call    Delay8
Delay8          nop     ;uses 1 stack level
                nop
                ret
James Newton says:
  I also wrote this god-awful macro for the Parallax SX key asembler that may
  be of use to someone: It produces the smallest and/or tightest loop delays
  inline when you call it with the value and units of time you wish to delay
  for; calculating the number of cycles based on the processor speed. The CpuMhz
  equate must be adjusted to what ever is right for your chip. It should probably
  be called CpuMips vice CpuMhz. The only redeming virtue is that it does not
  use anything other than w (on the SX you can decrement W); no stack use,
  no register use. :
  
        device  pins28, pages1, banks8, turbo, stackx, optionx, carryx
        reset reset_entry
CpuMhz = 50
temp    ds      1
usec    equ     -6
msec    equ     -3
sec     equ     1
cycles  equ     0
mynop   MACRO
        noexpand
        page $>>8
        ENDM
cyclefor MACRO 1
_cycles = \1
IF _cycles > 0
_temp   =       $//4
IF _temp = 2
 IF _cycles < 5
  REPT _cycles
   expand
   mynop
   noexpand
   ENDR
  _cycles = 0
 ELSE
  expand
  mynop
  noexpand
  _cycles = _cycles -1
  ENDIF
 ENDIF
IF _temp = 1
 IF _cycles < 6
  REPT _cycles
   expand
   mynop
   noexpand
   ENDR
  _cycles = 0
 ELSE
  expand
  mynop
  mynop
  noexpand
  _cycles = _cycles -2
  ENDIF
 ENDIF
IF _cycles > 3
        expand
         mov w, #_cycles / 3
         decsz 1        ;dec w
         clrb 2.1       ;modify PC to jump back
        noexpand
 _cycles = _cycles // 3 ;cycles left over
 ENDIF
IF _cycles > 0
  REPT  _cycles
        expand
         mynop
        noexpand
   ENDR
 ENDIF
ENDIF
        ENDM
reset_entry
        mov w,#$7F
        mov !OPTION,w
delayhelp MACRO
        ERROR 'USAGE: delay value, [usec,msec,sec,cycles]'
        ENDM
delay   MACRO   2
noexpand
IF (\2=usec OR \2=msec OR \2=sec) AND (\1<1000 AND \1>0)
 IF \2=sec
  _cycles = (\1 * 1000000 / (1000/CpuMhz))
  ENDIF
 IF \2=msec
  _cycles = (\1 * 1000 / (1000/CpuMhz))
  ENDIF
 IF \2=usec
  _cycles = (\1 / (1000/CpuMhz))
  ENDIF
 IF \2=cycles
  _cycles = \2
  ENDIF
 IF _cycles = 0
  expand
         ;delay less than one cycle at this processor speed'
  noexpand
 ELSE
  IF _cycles > 255
   REPT (_cycles / 256)
    cyclefor 256
    _cycles = _cycles - 256
    ENDR
   ENDIF
  cyclefor _cycles
  ENDIF
ELSE
        delayhelp
ENDIF
        ENDM
        delay 999, usec
        delay 200, usec
        delay 250, usec
        delay 10, usec
        delay 20, usec
        delay 100, msec
| file: /Techref/scenix/lib/flow/delays_sx.htm, 12KB, , updated: 2004/6/10 14:40, local time: 2025/10/30 20:56, 
 
216.73.216.139,10-3-157-36:LOG IN | 
| ©2025 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions? <A HREF="http://massmind.ecomorder.com/Techref/scenix/lib/flow/delays_sx.htm"> SX Microcontroller Delay Program Flow Methods</A> | 
| Did you find what you needed? | 
| Welcome to ecomorder.com! | 
| Ashley Roll has put together a really nice little unit here. Leave off the MAX232 and keep these handy for the few times you need true RS232! | 
.