Ensamblador 1: Parpadear Led

El objetivo de la primera práctica será hacer parpadear un led cada que pase un segundo, para esto será importante conocer algunos conceptos así como parte del funcionamiento del PIC.

Lo primero será hablar de los registros PORTx y TRISx, donde la “x” indica a que puerto está asociado, por ejemplo PORTA está asociado al puerto A, PORTB al puerto B, etc.

En el registro TRISx escribiremos la información necesario para indicar si el puerto asociado será entrada o salida, en este caso como queremos hacer parpadear un led será puertos de salida, por lo tanto le tendremos que asignar al puerto TRISx el valor 0x00. Se dividirá en dos partes la descripción del código, una parte para trabajar con Miuva (18F4550) y una parte para trabajar con Miuva Pro (18F87J50).

Para escribir un valor en algún registro en particular, utilizaremos primero la instrucción movlw que lo que hará es guardar el valor indicado en el registro de trabajo, para posteriormente utilizar movwf que lo que hará es mover la información del registro de trabajo al registro f.

En Miuva el led RGB está ubicado en el puerto E:

movlw   0x00
movwf   TRISE   ;Configura PUERTO E como salida

Los colores del led RGB de Miuva encienden con un valor lógico “0”, y el valor por defecto del puerto E es “bajo”, por lo tanto en primera instancia todos los colores están encendidos para lo cual se requieren apagar, esto se puede hacer poniendo en alto los pines 0, 1 y 2 del puerto E, o dicho de otra forma, colocando un 0x07 en el registro PORTE:

movlw   0x07   
movwf   PORTE   ;Valores iniciales del puerto E para apagar el led RGB

Vamos a crear ahora un retardo de 1 segundo, para el parpadeo del led, esto puede realizarse de muchas formas, una de ellas será creando diferentes variables, iremos decrementando su valor hasta que lleguen a cero, de esta forma si sabemos a que velocidad están contando y cuando llegaron de un número a otro, podremos saber cuanto tiempo ha pasado; para esto son importantes diferentes conceptos.

Ciclo de reloj

El ciclo de reloj está dado por la frecuencia del oscilador que estemos utilizando, por ejemplo, con una frecuencia del oscilador de 8MHz, el ciclo de reloj está dado por:

Ciclo_reloj = 1/Fosc = 1 / 8MHz =125ns

Ciclo máquina o ciclo de instrucción

Es el tiempo que tarda nuestro CPU en ejecutar una instrucción en lenguaje máquina, esto es equivalente a 4 ciclos de reloj, por lo tanto:

Ciclo_máquina = 4 * ciclo_reloj = 125ns*4 = 500ns

La función que utilizaremos para decrementar el valor de los contadores es DECFSZ la cual según las hojas de especificaciones tarda 3 ciclos máquina en ejecutarse. Por lo tanto, considerando que la variable será de 8 bits, el tiempo que tardará en llegar de 255 a 0 estará dado por:

tiempo = 255 * (3*500ns) = 382.5us

Si utilizamos dos contadores el tiempo será:

tiempo = 255*255*(3*500ns) = 97.5375ms

Si colocamos un tercer contador que vaya del 11 al 0, el tiempo será:

tiempo = 11*255*255*(3*500ns) = 1.073 s

Entonces tendremos que crear tres variables a las que llamaremos retardos, dos iniciadas en 255 y la otra en 11, para que cuando las tres lleguen a 0 haya pasado aproximadamente 1 segundo.

Para reservar un espacio de memoria para las variables se utilizan las siguientes líneas:

CBLOCK  0x000
    Ret1	;Variables para los retardos de 1 segundo
    Ret2
    Ret3
ENDC

Posteriormente tenemos que darle a cada Retx (retardo) el valor indicado:

movlw   D'255'    ;Cargamos los valores de los retardos a las constantes
movwf   Ret1      ;correspondientes
movlw   D'255'
movwf   Ret2
movlw   D'11'
movwf   Ret3

La función DECFSZ decrementará el valor, posteriormente, si el valor es 0 saltará la siguiente línea del código, si el valor es diferente de 0, seguirá con la siguiente línea de código, por ejemplo, utilizando el siguiente código:

Ret1sON
    decfsz  Ret1, F ;Decrementa el valor de Ret1 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    ;Continuación del código

Se decrementa Ret1, si su valor es diferente de 0, se ejecuta la siguiente línea (bra Ret1sON) la cual nos lleva a la etiqueta “Ret1sON”, y vuelve a ejecutarse el decremente, en el momento en que el valor de Ret1 se vuelva 0, saltará la línea “bra” y seguirá con la continuación del código.

De esta forma crearemos una sección para el retardo de 1 segundo y encender el led, y otra para el retardo de 1 segundo y apagar el led. Siendo ambos similares:

Retardo1sON
    movlw   D'255'    ;Cargamos los valores de los retardos a las constantes
    movwf   Ret1    ;correspondientes
    movlw   D'255'
    movwf   Ret2
    movlw   D'11'
    movwf   Ret3
Ret1sON
    decfsz  Ret1, F ;Decrementa el valor de Ret1 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    decfsz  Ret2, F ;Decremente el valor de Ret2 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    decfsz  Ret3, F ;Decremente el valor de Ret3 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    movlw   0x06    
    movwf   PORTE	;Encendemos el led ubicado en E0

Con esto ya tenemos el contenido del código para parpadear el led, solamente habrá que agregar la parte del apagado del led (que es similar a la del encendido) y las líneas de configuración, en ellas debemos especificar el pic que estamos utilizando y agregar la librería correspondiente, posteriormente agregar los fusibles necesarios para el funcionamiento adecuado.

LIST    P = 18F4550	;PIC a utilizar
INCLUDE <P18F4550.INC>

;************************************************************
;Configuración de fusibles
CONFIG  FOSC = HS   
CONFIG  PWRT = ON
CONFIG  BOR = OFF
CONFIG  WDT = OFF
CONFIG  MCLRE = ON
CONFIG  PBADEN = OFF
CONFIG  LVP = OFF
CONFIG  DEBUG = OFF
CONFIG  XINST = OFF

;***********************************************************
;Código

CBLOCK  0x000
    Ret1	;Variables para los retardos de 1 segundo
    Ret2
    Ret3
ENDC

;Código
ORG 0x0000	;Vector de reset
    goto INICIO
;Inicio del programa principal

INICIO    
    movlw   0x0F    
    movwf   ADCON1  ;Configuración de entradas digitales
    movlw   0x00
    movwf   TRISE   ;Configura PUERTO E como salida
    movlw   0x07   
    movwf   PORTE   ;Valores iniciales del puerto E para apagar el led RGB

BUCLE

; Calculo de los valores de las variables para el retardo de aproximadamente
; 1 segundo
;
; fosc = 8MHz 
; Ciclo Reloj = 1/fosc = 1/8M = 125ns
; Ciclo Instruccion = 4*Ciclo Reloj = 500ns
; La funcion DECFSZ tarda 3 ciclos en ejecutarse
; Retardo 15ms
; Tiempo = Ret1*Ret2*Ret3*(3*500ns) 
; Tiempo = Ret1*Ret2*Ret3*(1.5us)
; Ret1 = 255
; Ret2 = 255
; Ret3 = 11
; Tiempo = (255*255*11)(1.5us) = 1.0729 seg

;Retardo de un segundo para encender el LED
Retardo1sON
    movlw   D'255'    ;Cargamos los valores de los retardos a las constantes
    movwf   Ret1    ;correspondientes
    movlw   D'255'
    movwf   Ret2
    movlw   D'11'
    movwf   Ret3
Ret1sON
    decfsz  Ret1, F ;Decrementa el valor de Ret1 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    decfsz  Ret2, F ;Decremente el valor de Ret2 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    decfsz  Ret3, F ;Decremente el valor de Ret3 y salta si es igual a 0
    bra	    Ret1sON ;Saltamos a Ret1sON
    movlw   0x06    
    movwf   PORTE	;Encendemos el led ubicado en E0

;Mismo retardo pero ahora para esperar antes de apagar el LED
Retardo1sOFF
    movlw   .255
    movwf   Ret1
    movlw   .255
    movwf   Ret2
    movlw   .11
    movwf   Ret3
Ret1sOFF
    decfsz  Ret1, F
    bra	    Ret1sOFF
    decfsz  Ret2, F
    bra	    Ret1sOFF
    decfsz  Ret3, F
    bra	    Ret1sOFF
    movlw   0x07
    movwf   PORTE   ;Apaga el LED

    goto    BUCLE   ;Regresa al INICIO

    END             ;Fin de Programa
Menú