PIC Microcontoller Delay Method

General Delay Methods

James Cameron says:

These PICs 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
    ...
        DELAY4 ; delay 4 cycles
            NOP
            NOP
            NOP
            NOP
    
    

    Advantages: extremely simple, obvious, maintainable, scaleable.
    Disadvantages: is it really there for a reason? For long delays, uses a lot of instruction memory.

  2. ) The Common Loop, three times the initial value plus three

            DELAY   MOVLW   D'95'           ; 288 cycle delay
                    MOVWF   COUNTER
                    DECFSZ  COUNTER,F
                    GOTO    $-1
    

    Advantages: fairly simple, maintainable, scaleable up to 771 cycles; 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, two instruction cycles in one instruction

                    GOTO   $+1              ; two cycle delay
    

    Advantages: half the space of two NOPs.
    Disadvantages: obscure unless commented.

  4. ) The CALL to Nowhere, four instruction cycles

                    ORG     0
                    GOTO    MAIN
            FOUR    RETURN                  ; four cycle delay function
                    [...]
            DELAY   CALL    FOUR
    

    Advantages: quarter the space of four NOPs, the RETURN can be reused by other code, good use for those three bytes between the reset vector and the interrupt vector on a PIC 16F84.
    Disadvantages: implementation separate from use, can look odd, uses one stack level.

    Scott Dattalo says:

    ...if you want a 4-cycle 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, eight or four cycles

                    ORG     0
                    GOTO    MAIN
            EIGHT   CALL    FOUR
            FOUR    RETURN
                    [...]
            DELAY   CALL    EIGHT
    

    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, five times the initial value plus three

            DELAY   MOVLW   D'95'
                    MOVWF   COUNTER
    
                    MOVF    TRISM           ; fetch TRIS mirror
                    TRIS    TRISB           ; reapply it
                    DECFSZ  COUNTER,F
                    GOTO    $-3
    

    Advantages: good for precise delays that are no multiples of three, 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: Uses the least amount of energy (best when running off batteries). 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.

See also:

Code:

Questions:

Comments: