please dont rip this site

SX Microcontroller Delay Program Flow Methods


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?

  1. ) The Common NOP, a delay for one instruction cycle

    DELAY   nop     ; delay one cycle

    Advantages: extremely simple, obvious, maintainable, scaleable.
    Disadvantages: is it really there for a reason?

  2. ) 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 16

    Advantages: 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.

  3. ) The Novel GOTO, three instruction cycles in one instruction

            jmp     $+1     ;three cycle delay

    Advantages: third the space of three NOPs.
    Disadvantages: obscure unless commented.

  4. ) The Call to Nowhere

            org     0
            jmp     MAIN
    delay6  ret     ;six cycle delay function
    DELAY   call    delay6

    Advantages: 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]
  5. ) The Double Call to Nowhere, 12 cycles

            org     0
            jmp     MAIN
    delay12 call    delay6
    delay6  ret
    DELAY   call    delay12

    Advantages: looks simple, allows various size delays to be rapidly constructed during prototyping.
    Disadvantages: uses two stack levels.

    [ed: See the "Stack Recursive Delay" below]

  6. ) 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 18

    Advantages: allows useful functionality to be placed within the delay.
    Disadvantages: increased convolution of code, lower maintainability.

  7. ) 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!

  8. ) 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]

  9. ) 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

        call    Hour_Delay
        decsz   hours
        jmp     Hours_Delay

        mov     W, #60
        mov     mins, W
        mov     W, #60
        mov     secs, W
        call    Second_Delay
        ; maybe some processing in here
        decsz   secs
        jmp     Hour_Loop
        decsz   mins
        jmp     Rst_Loop

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

Stack Recursive Delay

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

Macro Example

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
        page $>>8

cyclefor MACRO 1
_cycles = \1
IF _cycles > 0
_temp   =       $//4
IF _temp = 2
 IF _cycles < 5
  REPT _cycles
  _cycles = 0
  _cycles = _cycles -1
IF _temp = 1
 IF _cycles < 6
  REPT _cycles
  _cycles = 0
  _cycles = _cycles -2
IF _cycles > 3
         mov w, #_cycles / 3
         decsz 1        ;dec w
         clrb 2.1       ;modify PC to jump back
 _cycles = _cycles // 3 ;cycles left over
IF _cycles > 0
  REPT  _cycles

        mov w,#$7F
        mov !OPTION,w

delayhelp MACRO
        ERROR 'USAGE: delay value, [usec,msec,sec,cycles]'

delay   MACRO   2
IF (\2=usec OR \2=msec OR \2=sec) AND (\1<1000 AND \1>0)
 IF \2=sec
  _cycles = (\1 * 1000000 / (1000/CpuMhz))
 IF \2=msec
  _cycles = (\1 * 1000 / (1000/CpuMhz))
 IF \2=usec
  _cycles = (\1 / (1000/CpuMhz))
 IF \2=cycles
  _cycles = \2
 IF _cycles = 0
         ;delay less than one cycle at this processor speed'
  IF _cycles > 255
   REPT (_cycles / 256)
    cyclefor 256
    _cycles = _cycles - 256
  cyclefor _cycles


        delay 999, usec
        delay 200, usec
        delay 250, usec
        delay 10, usec
        delay 20, usec
        delay 100, msec

See also:

file: /Techref/scenix/lib/flow/delays_sx.htm, 12KB, , updated: 2004/6/10 14:40, local time: 2017/10/17 11:57,

 ©2017 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?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF=""> SX Microcontroller Delay Program Flow Methods</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.

Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2017 contributors:
o List host: MIT, Site host, Top posters @20171017 RussellMc, Van Horn, David, James Cameron, Sean Breheny, IVP, alan.b.pearce, Neil, David C Brown, Bob Blick, Denny Esterline,
* Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.

Welcome to!