Home » Programming » ASM delay subroutines for PIC16 mcu

Posted on Feb 14, 2014  - Last updated on Feb 14, 2014
By Benoit Frigon

These are the delay subroutines i use in my PIC projects. It was written for the PIC16 family but should be compatible with the 18F instruction set as well.

The simplest way to produce delay is to write a subroutine that waste instructions cycles for the desired amount of time. This method should not be used for application that require a high level of precision since the delay subroutine may be halted by interrupts. The delay is offset by the time it takes to execute the interrupt service routine. For short delays however, this should not be a problem.

How many cycles are required

Let’s say that the processor clock runs at 8 MHZ. It takes 4 clock pulse to execute one instruction cycle. At 8 MHZ, the processor is able to execute 2 millions instructions per seconds. It also means that each instructions takes 0.0000005 seconds (0.5 micro seconds) to execute. To produce a 50 milliseconds delay, you then need to execute 100,000 instruction cycles.

Here is the formula to find out the number of instruction required :

i_time = 1 / (fosc / 4)
0.0000005 = 1 / (8000000 / 4)

n = time / i_time
100000 = 0.05 / 0.0000005

The delay subroutines

There are 4 delay subroutines :

delay10cty WREG x 10 cycles
delay100cty WREG x 100 cycles
delay1kcty WREG x 1000 cycles
delay10kcty WREG x 10000 cycles

Each routines can be looped ‘n’ times specified by WREG. For instance, if you put D’50 in WREG before calling delay10cty, the routine will waste 500 instruction cycles. The routines takes into account the time it takes to call the routine itself except for delay10kcty. The 3 cycles it takes to call the routine is negligible over 10000 cycles.

The maximum possible delay using these routines is 2,550,000 instruction cycles or 1.275 second @ 8 MHZ

Usage example

50 milliseconds:

    movlw D'100'
    call  delay1kcty

250 milliseconds:

    movlw D'50'
    call  delay10kcty

The code

;******************************************************************************
;*   Project:      --                                                         *
;*   Version:      --                                                         *
;*                                                                            *
;*   Filename:     delay.asm                                                  *
;*   Description:  Delay subroutines                                          *
;*   Last mod:     11 august 2012                                             *
;*                                                                            *
;*   Author:       Benoit Frigon                                              *
;*   Email:        <bfrigon( a t )gmail.com>                                  *
;*                                                                            *
;******************************************************************************
processor 16f1826
#include <p16f1826.inc>



;==============================================================================
;==============================================================================
;
;                                   Symbols
;------------------------------------------------------------------------------
; *** Subroutines ***
GLOBAL  delay10tcy
GLOBAL  delay100tcy
GLOBAL  delay1ktcy
GLOBAL  delay10ktcy



;==============================================================================
;==============================================================================
;
;                                     Data  
;------------------------------------------------------------------------------
.d_delay        UDATA
d1              RES     0x01                ; Delay counters
d2              RES     0x01                ;
d3              RES     0x01                ;  



;==============================================================================
;==============================================================================
;
;                                Subroutines
;------------------------------------------------------------------------------    
.c_delay        CODE


;******************************************************************************
; delay10tcy : delay 10 cycles (1.25us @ 32Mhz)
;
; Arguments : W= cycles count (W x 10 cycles)
; Return    : None
;******************************************************************************
delay10tcy:
    movwf   d1
    decfsz  d1
    bra     loop_delay10tcy
    nop
    nop
    return
        
loop_delay10tcy:
    nop
    bra     $+1
    nop
    bra     $+1
    nop
        
    decfsz  d1
    bra     loop_delay10tcy
    bra     $+1
    return
        


;******************************************************************************
; delay100tcy : delay 100 cycles (12.5us @ 32Mhz)
;
; Arguments : W= cycles count (W x 100 cycles)
; Return    : None
;******************************************************************************
delay100tcy:
    movwf   d2
        
loop_delay100tcy:
    movlw   D'9'
    call    delay10tcy
        
    decf    d2
    btfsc   STATUS, Z
    bra     delay100tcy_done

    nop
    bra     loop_delay100tcy
    nop

delay100tcy_done:
    return

        

;******************************************************************************
; delay1ktcy : delay 1000 cycles (0.125ms @ 32Mhz)
;
; Arguments : W= cycles count (W x 1000 cycles)
; Return    : None
;******************************************************************************
delay1ktcy:
    movwf   d2
        
loop_delay1ktcy:
    movlw   D'99'
    call    delay10tcy
        
    decf    d2
    btfsc   STATUS, Z
    bra     delay1ktcy_done
        
    nop
    bra     loop_delay1ktcy
    nop

delay1ktcy_done:
    return        

        

;******************************************************************************
; delay10ktcy : delay 10000 cycles (1.25ms @ 32Mhz)
;
; Arguments : W= cycles count (W x 10000 cycles)
; Return    : None
;******************************************************************************
delay10ktcy:
    movwf   d3

loop_delay10ktcy:        
    movlw   D'10'
    call    delay1ktcy
        
    decfsz  d3
    bra     loop_delay10ktcy
        
    return


;==============================================================================
;==============================================================================
        END