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.
CÓDIGO FINAL
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