¿Cómo producir retrasos en la programación PIC18 ASM?

1

Soy un novato con la programación de microcontroladores. Tengo conocimientos de programación de alto nivel, pero me estoy involucrando en el desarrollo de microcontroladores / CPU de palanca baja.

Quiero hacer este simple ejercicio de encender y apagar una serie de LED durante 1 segundo cada uno.

Probé este ensamblaje (pensando en dos leds):

    List    P=18F4550           
    include <P18F4550.inc>          



    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***********************************
    count equ 0x00

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


    org     0x0000  
    movlw   0x62       
    movwf   OSCCON     ;Working at 4 MhZ
    clrf    TRISD      ;D port as output
    ;leds OFF so far

LGHTLOOP
    bcf PORTD,0         
    call DELAY

    bsf PORTD,0         
    CALL DELAY

    bcf PORTD,1         
    call DELAY

    bsf PORTD,1       
    CALL DELAY

bra  LIGHTLOOP

DELAY
    movlw   .1000  
    movwf   count

    LOOP2
         DECFSZ   count,F  

    bra  LOOP2

    nop

    return 

    end

Intenté simularlo en el software Proteus, teniendo esta configuración:

Realmente puedo ver que los leds se activan y desactivan, pero nada como un segundo, no importa cómo cambie movlw .255 en la subrutina DELAY . Probé con diferentes valores más altos y obtuve el mismo comportamiento extraño.

¿En qué me equivoqué?

Contar los ciclos de instrucciones en subrutinas con movlw .255 debería ser más de 1 segundo, creo. Pero todavía la simulación lo muestra más rápido. Agregar dos leds más hace que parezca aún más rápido.

    
pregunta diegoaguilar

2 respuestas

2

El problema es que la instrucción decfsz funciona implícitamente en un registro de un byte (8 bits). El valor más grande que puede mantener un registro de este tipo es hex FF (decimal 255). Cuando intenta inicializar count al decimal 1000 (hexadecimal 3E8), en realidad solo está configurando ese registro en los 8 bits de orden inferior de ese valor, o E8 (decimal 232).

Para evitar esta limitación de la instrucción decfsz , la técnica habitual es crear un "nido" de dos bucles, cada uno usando una variable separada. Esto le permitiría ejecutar el cuerpo del bucle interno hasta 65535 veces (hex 0xFFFF).

    ; control variable for inner loop
    i equ 0

    ; control variable for outer loop
    j equ 1

    ; initialize j with the MSBs of the loop count
    movlw .1000 >> 8
    movwf j
    ; initialize i with the LSBs of the loop count
    movlw .1000 & 0xFF
    movwf i

loop:

    ; body of loop here

    nop

    ; end of inner loop
    decfsz i
    bra loop

    ; end of outer loop
    decfsz j
    bra loop

Tenga en cuenta que el bucle interno se ejecuta el número de veces que se inicializa i en la primera iteración del bucle externo. Cada vez después de eso, se ejecuta 256 veces.

    
respondido por el Dave Tweed
2

Esto es lo que necesitas:

enlace

Probablemente el sitio más útil jamás creado. (Después de este!)

Debe tenerse en cuenta que si bien esto solucionará su problema, también le enseñará absolutamente nada sobre cómo programar su propio programa, aunque si lee el código que genera, podrá resolverlo.

La otra respuesta debe leerse correctamente si desea una comprensión real. Esto es solo para que las cosas funcionen.

    
respondido por el Tim Mottram

Lea otras preguntas en las etiquetas