diegoaguilar
diegoaguilar

Reputation: 8376

How can I properly code time delays in ASM for PIC18 family?

I got to code the typical example of 8 LEDS turning ON and OFF, then all getting ON. All this within a loop.

I got a PIC 18F4550, and coded this:

    List    P=18F4550               ;Microcontrolador a utilizar
    include <P18F4550.inc>          ;Definiciones de constantes


;**********   Palabra de conficuración  *******************************************
    CONFIG FOSC = INTOSC_EC ;INTOSC_EC          ; Internal oscillator                                
    CONFIG PWRT= ON             ; Power-up Timer Enable bit
    CONFIG BOR=OFF              ; Brown-out Reset disabled in hardware and software
    CONFIG WDT=OFF              ; WDT disabled
    CONFIG MCLRE=ON             ; MCLR pin enabled
    CONFIG PBADEN=OFF           ; PORTB<4:0> pins are configured as digital I/O
    CONFIG LVP=OFF              ; Single-Supply ICSP disabled
    CONFIG DEBUG = OFF                  ; Background debugger disabled
    CONFIG XINST = OFF          ; Extended Instruction disabled
;******************************Variables***********************************
    conta equ 0x00

;**********************************************************************************


    org     0x0000      
    movlw   0x62        
    movwf   OSCCON    
    clrf    TRISD      

CICLO   
    bcf PORTD,0         
    call RETARDO
    bsf PORTD,0       
    bcf PORTD,1
    CALL RETARDO

        bcf PORTD,1         
    call RETARDO
    bsf PORTD,1        
    bcf PORTD,2
    CALL RETARDO

        bcf PORTD,2         
    call RETARDO
    bsf PORTD,2      
    bcf PORTD,3
    CALL RETARDO    

        bcf PORTD,3        
    call RETARDO
    bsf PORTD,3       
    bcf PORTD,4
    CALL RETARDO    

        bcf PORTD,4        
    call RETARDO
    bsf PORTD,4      
    bcf PORTD,5
    CALL RETARDO        

        bcf PORTD,5         
    call RETARDO
    bsf PORTD,5       
    bcf PORTD,6
    CALL RETARDO        

        bcf PORTD,6        
    call RETARDO
    bsf PORTD,6       
    bcf PORTD,7
    CALL RETARDO    

        bcf PORTD,7       
    call RETARDO
    bsf PORTD,7   
        bcf PORTD,0
    CALL RETARDO        


bra  CICLO

RETARDO 
    movlw   .255  
    movwf   conta

    CICLO2
         DECFSZ   conta,F  

    bra  CICLO2

    nop
    nop
    nop
    nop



    return 


    end 

When I simulate, That code is almost working. Sometimes they get turning ON and OFF one after another starting at first led, but sometimes the sequence leaps and some random LEDS get ON unexepectedly.

I tried to add this portion of code before bra CICLO to produce the whole leds ON effect, but it just made it behave the worst.

bcf PORTD,0
bcf PORTD,1
bcf PORTD,2
bcf PORTD,3
bcf PORTD,4
bcf PORTD,5
bcf PORTD,6
CALL RETARDO
bsf PORTD,1
bsf PORTD,2
bsf PORTD,3
bsf PORTD,4
bsf PORTD,5
bsf PORTD,6
bsf PORTD,7
CALL RETARDO

This is a picture of my simulation:

enter image description here

What am I doing wrong? How could I make sure, working at 4 MhZ that delays will be 1 second?

Upvotes: 0

Views: 388

Answers (1)

Mark
Mark

Reputation: 2822

Assuming you're running in a single-threaded environment, the traditional way to delay for a precise amount of time is a busy loop: for example, you might count from 1 to 1000000. You can figure out the exact length of the delay by checking instruction timings on your microcontroller, or by trial and error.

The downside of busy waiting, especially for long (multi-millisecond) delays, is that it consumes power. If that's a concern, you can see if your system has some form of "idle wait with timer interrupt" functionality that will let it go into a low-power state while you're waiting.

Upvotes: 1

Related Questions