You are on page 1of 75

PROGRAMACIN EN ENSAMBLADOR DEL PIC18F4550 CON BOOTLOADER

Por Francisco Javier Garca Olmos Instituto Politcnico Nacional Mxico 2012

NOTA: Para utilizar este manual terico-prctico es necesario tener conocimientos bsicos de electrnica y circuitos, lgica digital y nociones bsicas de programacin de computadoras en cualquier lenguaje. Es necesario tambin tener en cuenta la lectura del manual (data sheet) para manejar los registros necesarios para la configuracin de este microcontrolador.

Dedicado a mis amigos programadores: Francisco y Eduardo.

Hay ms personas pero el mencionar a todas ellas requerira un documento extra para mencionarlas, ya que son muchas. Gracias Por Su Apoyo SNAR.

INTRODUCCIN A MPLAB X
Para iniciar con la programacin en ensamblador primero necesitamos saber acerca del IDE gratuito del cual Microchip nos provee; Microchip es la empresa que fabrica los microcontroladores PIC. Este IDE es el que usaremos para realizar nuestros proyectos, probarlos y compilarlos, ya que es multiplataforma y podemos utilizarlo tanto en Windows como en Linux.

Ambiente de desarrollo MPLAB X


El ambiente de desarrollo tiene la siguiente imagen; tome en cuenta que est mostrado dentro del Sistema operativo Linux.

Del lado izquierdo aparece una lista con los proyectos realizados, archivos y/o clases que se utilizan en MPLAB. Siempre se abrir con la pgina de inicio. Tiene su barra de men, barra de herramientas y en la parte de abajo, oculta ventanas que son necesarias a la hora de compilar, probar y analizar la memoria. Para mayor informacin, verificar un curso completo de MPLAB, ya que aqu solo hablaremos de las partes ms importantes.

Crear un proyecto para Ensamblador


Para crear un proyecto, es necesario dar clic en el segundo icono de la barra de herramientas o seleccionar New Proyect del men File y se abrir una ventana donde pregunta el tipo de proyecto que deseamos crear; seleccionamos Standaalone Proyect y presionamos Siguiente; nos aparecer una lista donde tenemos que seleccionar la familia y el dispositivo a usar, en nuestro caso colocamos Advanced 8-bit MCUs (PIC18) en familia y en dispositivo PIC18F4550, posteriormente seleccionamos siguiente. Nos aparecer una lista de programa dores a usar; nosotros colocaremos Simulator por que usaremos Bootloader y no es necesario un programador mas que solo una vez para ingresarle el Bootloader al PIC. Una vez presionado el botn siguiente (Next) aparecer una lista con lenguajes de programacin, de los cuales vamos a seleccionar MPASM, ya que usaremos el lenguaje ensamblador.

Por ltimo, le damos un nombre al proyecto y lo guardamos en el directorio que nos agrade.

Al realizar los pasos anteriores, se mostrar nuestro proyecto en la parte izquierda del IDE. Ahora es necesario crear un archivo nuevo vaci para comenzar a programar.

Para agregar el nuevo archivo hacemos clic derecho en Source Files del proyecto que estamos creando, y le hacemos clic en New y posteriormente en Empty File y se abrir una ventana donde le colocaremos un nombre. En nuestro caso le llamaremos plantilla.asm por que ser nuestra plantilla para cualquier proyecto que realicemos con bootloader.

Compilar un programa
Para compilar un programa hecho previamente, solo le damos clic al botn que tiene un martillo, se compilar el proyecto y se crear el archivo ejecutable .HEX que es el que se grabar en el PIC con el HID BOOTLOADER. En Windows este programa es grfico y se habilitan los botones una vez que se ac tiva el bootloader de la placa de prueba del PIC. Seleccionamos el archivo .HEX que deseamos grabar y pulsamos sobre el botn Program / Verify y se programar el PIC. 5

En Linux, hay un programa en lnea de comandos que graba de forma satisfactoria el PIC con bootloader y se ejecuta anexando la direccin del archivo .HEX desde la Terminal. Tiene el nombre de hid_bootloader y solo se tiene que ingresar el nombre del archivo .HEX que se desea grabar. El bootloader del PIC se activa pulsando el SWITCH 3 de la placa de prueba del PIC18F4550 junto con el botn RESET, posteriormente soltar RESET quedando solo el swithc 3 y parpadearn los LEDS RC0 y RC1 de la placa de prueba, en ese momento soltar el SWITCH 3. Una vez realizado esto, la computadora reconocer al dispositivo como un Human Interface Device USB. En este momento se puede grabar el programa que hemos realizado con el bootloader.

El PIC18F4550
En este captulo vamos a ver algunas caractersticas del PIC18F4550, que son esenciales para entender la programacin en ensamblador. 1. Es un dispositivo CMOS de bajo consumo de energa, uso de voltaje +5V y uso mximo de corriente de 25mA, no consumir ms de esta corriente ya que si no, podramos daar el pin del microcontrolador. Tambin tener en cuenta que los dispositivos CMOS son delicados a la corriente esttica. 2. Es un microcontrolador que trae en su interior un microprocesador (MPU o ALU), memoria RAM y memoria de programa flash (regrabable) y memoria EEPROM de datos y sus propios bus de datos, control y direcciones internamente. 3. Integrado de 40 pines en su presentacin DIP o 44 pines en su presentacin para montaje superficial. 4. Es un microcontrolador de 8 bits en su bus de datos, osea que solo puede manejar 8 bits por clculo. 5. Tiene 5 puertos de entrada y salida: A, B, C, D y E. Tres de ellos son de 8 bits, uno de 7 bits y uno de ellos es de 4 bits, mas sin embargo, estas caractersticas no son posibles por el uso de pines por oscilador externo (RA5 y RA6), uso de USB (RC4 y RC5) y por ltimo uso de MCLR (Master Clear Reset) en el pin RE4. Esto nos deja con 1 puertos de 6 bits, dos puertos de 8 bits, uno de cinco y uno de 3 bits. 6. Oscilador interno de 8MHz. Nosotros usaremos el externo de 20MHz por el uso del mdulo USB para el BOOTLOADER. 7. Tiene 13 canales analgicos (ADC) de 10 bits. 8. Mdulo USB y posibilidad de usar BOOTLOADER. 9. Modulo USART para comunicacin serial. Si se requiere comunicacin PC-PIC se necesitar un integrado MAX232 para la conversin de voltajes. 10. Tres interrupciones externas. 11. Cuatro temporizadores (Timers) o contadores. 12. Dos modulos capturador/comparador/PWM (CCP). 13. Un mdulo embebido capturador/comparador/PWM (ECCP). 14. Un mdulo Master Synchronous Serial Port (MSSP).

Las conexiones bsicas del PIC18F4550, les de estado y 2 botones de cambio de flanco (SW2 y SW3) para el inicio del bootloader son las siguientes:

Conexiones bsicas: 1. Conexin a VDD y VSS no mostradas en el diagrama. VDD es de +5V y VSS es tierra GND. 2. 1 push button para MCLR con sus respectivas resistencias de PULL-UP externas. 3. Oscilador de 20MHz con dos capacitores de 22pF conectados a tierra. Conexiones extras de la placa de pruebas del PIC18F4550: 1. 2 Leds en RA4 y RA5. 2. 2 Leds en RC0 y RC1 para el estado del Bootloader. 3. 2 push button para las interrupciones de cambio de flanco con sus respectivas resiste ncias de PULL-UP externas (SW2 y SW3).

LO BSICO EN ENSAMBLADOR
Comencemos la programacin en ensamblador definiendo algunos trminos y aclarando algunas situaciones con respecto del bootloader. El bootloader es un programa dentro del microcontrolador PIC que graba otro programa a partir de la direccin 0x1000 de la memoria de programa. Es como un sistema operativo (mas sin embargo no lo es) que se ejecuta cada que presionamos el botn SWITCH 3 despus del RESET. Las direcciones de inicio del PIC son: 0x0000 0x0008 0x0018 MCLR (Master Clear Reset) High Vector Sector Low Vector Sector

Pero como nosotros usamos Bootloader, las direcciones cambian. 0x1000 0x1008 0x1018 Remaped Reset Sector Remaped High Vector Sector Remaped Low Vector Sector

Posteriormente explicar a que se refiere cada una de ellas en el captulo de interrupciones, que abarcaremos ms adelante. La numeracin en ensamblador puede ser hexadecimal colocando 0xNN y el nmero, colocando H'NN' y el nmero o colocando NLh (0Ah), para este tipo de numeracin, se debe de comenzar por un nmero, en caso de ser de dos letras, se utiliza cero (0FFh). La numeracin decimal se realiza colocando un punto y el nmero en decimal. Para la numeracin binaria se procede a colocar B'XXXXXXX' y el nmero en binario, Como vemos, lo que se refiere al bootloader, son las direcciones de inicio y posteriormente veremos que la frecuencia tambin cambia, as que esta programacin tam bin se puede utiliza sin bootloader con el inconveniente que necesitamos un programador como el PICKIT2 para grabar nuestros programas.

La configuracin inicial (La plantilla)


Para iniciar con la plantilla necesitamos incluir el archivo P18F4550.INC que es un archivo que contiene definiciones de registros y sus direcciones de memoria. #include <P18F4550.INC> esta parte del cdigo es para que ensamblador reconozca los registros del pic y las direcciones de memoria. LIST P=18F4550 es para que reconozca el tipo de microcontrolador a programar el ensamblador. 9

Bits de configuracin
Son los que controlan el comportamiento del microcontrolador. Los tres bsicos son: CONFIG FOSC = HS ;Configura el oscilador a usar, los posibles osciladores son RC (oscilador RC), XT (cristal de baja frecuencia), HS (cristal de alta frecuencia). Hay ms, para mayores referencias consultar el manual. CONFIG WDT = OFF ;configura el perro guardin (este es un timer que resetea al pic en caso de que tenga un ciclo infinito) el valor que nosotros manejamos es OFF (apagado). CONFIG LVP = OFF ;configura el bajo voltaje de programacin, nosotros lo apagamos para que programe en alto voltaje. Para el Bootloader (modo que nosotros usaremos) hay ms bits, estn ya colocados en la plantilla y no debern de ser modificados. Para ms informacin ver la ayuda de MPLAB sobre los bits de configuracin.

Sectores de cdigo
Los sectores de cdigo son aquellos que le dicen al programador (PICKIT2, PICKIT3, etc) en que parte de la memoria de programa va a programar el cdigo. Hay dos formas de hacerlo: ORG $direccin o CODE $direccin Ejemplo 1: Colocar el vector de reset en la localidad cero de la memoria. ORG 0x0000 ;localidad cero goto main RESET_VECTOR_SECTOR CODE 0x0000 ;localidad cero (notar que podemos nombrar dicho sector con CODE) goto main Ejemplo 2: Colocar el vector reset en la localidad mil hexadecimal. ORG 0x1000 goto main REMAPED_VECTOR_SECTOR CODE 0x1000 goto main 10

Para usar bootloader el vector de reset se encuentra en 0x1000 ya que el dems espacio es usado por el propio bootloader previamente cargado. La palabra reservada END termina con todos los CODE. Se utiliza para finalizar el cdigo. Solo se pone una vez y hasta el final del programa.

Sectores de memoria
Los sectores de memoria especifican la memoria que va a ser reservada para los registros del microcontrolador o un espacio de memoria que se necesite para guardar algn dato o infromacin. El sector de memoria se ubica debajo de la palabra UDATA, para reservar memoria para registros del microcontrolador, bsicamente para usar informacin que restaure el algunos registros del microcontrolador en la interrupcin del baja prioridad. Para reservar memoria de datos, vamos a hacerlo debajo de la palabra UDATA_ACS y se reserva memoria colocando un nombre al registro de memoria, posteriormente se coloca la palabra RES y finalizar con el nmero de bytes que se desean reservar. Ejemplo: Reservar memoria para un dato, donde el registro de memoria tendr el nombre de DATO1. UDATA_ACS ;UDATA y UDATA_ACS llevan sangra DATO1 RES 1 ;la reserva de memoria no lleva sangra. En el ejemplo anterior reservamos un byte de memoria para un registro llamado DATO1. Podemos hacer la reserva de memoria mientras no terminemos la memoria RAM del microcontrolador. UDATA_ACS DATO1 RES 1 DATO2 RES 1 DATO3 RES 1

Constantes
Para que el lenguaje ensamblador reconozca una constante, es necesario darle un nombre y un nmero al cual sera igualada; para ello se utiliza la palabra reservada EQU. UNO EQU 1 DOS EQU 2 TRES EQU 3 11

Y con esto tenemos a UNO con un valor de 1, DOS con un valor de 2 y a TRES con un valor de 3. Nuestra plantilla quedar de la siguiente forma:
;************************************************************************ ; Autor: Francisco Javier Garca Olmos * ; Fecha: 2 de Enero de 2012 * ; Plantilla para trabajar con BOOTLOADER en Ensamblador * ;************************************************************************ LIST P=18F4550, F=INHX32 #include <P18F4550.INC> ;*************************************************************************** ;Bits de configuracin CONFIG CONFIG CONFIG CONFIG CONFIG CONFIG CONFIG CONFIG CONFIG CONFIG config config config config config config config config config config config config config config config config config config config config config config config config config config PLLDIV CPUDIV USBDIV FOSC FCMEN IESO PWRT BOR BORV VREGEN WDT WDTPS MCLRE LPT1OSC PBADEN CCP2MX STVREN LVP ICPRT XINST CP0 CP1 CP2 CP3 CPB CPD WRT0 WRT1 WRT2 WRT3 WRTB WRTC WRTD EBTR0 EBTR1 EBTR2 = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = 5 OSC1_PLL2 2 HSPLL_HS OFF OFF OFF ON 3 ON OFF 32768 ON OFF OFF ON ON OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF OFF

12

config EBTR3 = OFF config EBTRB = OFF ;*************************************************************************** ;*************************************************************************** ; Definicin de variables ; Variables definidas si se utiliza la interrupcin de baja prioridad UDATA WREG_TEMP STATUS_TEMP BSR_TEMP RES RES RES 1 1 1 ;variable en RAM para guardar contexto ;variable en RAM para guardar contexto ;variable en RAM para guardar contexto

RESET_VECTOR CODE 0x0000 goto main REMAPED_RESET_VECTOR CODE 0x1000 goto main REMAPED_HIGH_VECTOR CODE 0x1008 bra ISRH REMAPED_LOW_VECTOR CODE 0x1018 bra ISRL CODE 0x102A ISRH: ; *** Interrupcin de alta prioridad retfie FAST ISRL: movff STATUS,STATUS_TEMP movff WREG,WREG_TEMP movff BSR,BSR_TEMP ; ;guarda el registro de estado ;guarda el registro de trabajo ;guarda el registro BSR

*** Interrupcin de baja prioridad *** movff BSR_TEMP,BSR movff WREG_TEMP,WREG movff STATUS_TEMP,STATUS retfie ;restaura el registro BSR ;restaura el registro de trabajo ;restaura el registro de estado

main: clrf WREG ; *** La funcin principal va aqu *** ciclo goto ciclo END

13

Instrucciones bsicas del lenguaje ensamblador


Antes de ver las instrucciones veremos cuales son los comentarios en el lenguaje ensamblador. El lenguaje ensamblador toma como comentario cualquier texto que est despus de punto y coma. ;esto es un comentario

Instruccin NOP
Esta instruccin se utiliza para que el microcontrolador no realice operacin alguna. Se utiliza para hacer retardos de tiempo equivalentes a cuatro ciclos del oscilador principal. Su sintaxis es: NOP No realiza operacin alguna.

Instruccin MOV
Mueve datos de un registro a otro. Hay que tomar en cuenta que el los microcontro ladores de Microchip usan el registro de trabajo para realizar este proceso. Este registro es llamado WREG o solamente W. La instruccin MOVLW 0x01 mueve el nmero 0x01 al registro de trabajo. La instruccin MOVWF REGISTRO mueve el contenido guardado en el registro de trabajo a cualquier otro registro. Ejemplo: Configurar el registro ADCON1 con 0x0F MOVLW 0x0F MOVWF ADCON1 Ejemplo mover e nmero 0xF0 a la variable DATO1 MOVLW 0xF0 MOVWF DATO1 La instruccin MOVF se usa para mover contenidos de registros a el mismo registro o al registro W. Su sintaxis es: MOVF REGISTRO, DESTINO 14

Donde DESTINO puede ser 0 o 1. Si es cero, se guarda en el registro W, si es uno se guarda en el mismo registro. Ejemplo: mover el contenido de la direccin de INTCON al registro de trabajo: MOVF INTCON, W Si colocamos MOVF INTCON, 1 movemos el contenido de ese registro al mismo registro. No es muy til hacer esto a menos que sea necesario refrescar la memoria RAM. La instruccin MOVFF se usa mara mover el contenido de un registro a otro registro. Ejemplo: mover el contenido del registro PORTB a un registro de memoria llamado DATO1. MOVFF PORTB, DATO1

Instruccin CLRF
Coloca a cero un registro. Ejemplo: Limpiar el registro de trabajo. CLRF WREG

Instruccin SET
La instruccin SET se utiliza para colocar un todo el un registro con uno, como si colocramos 0xFF al registro. Ejemplo: Colocar en uno todo el registro de trabajo. SET WREG Es idntico que hacer: MOVLW 0xFF

GOTO y Etiquetas
Para usar una etiqueta y GOTO necesitamos colocar sangras (tecla tabulador) y de15

jar las etiquetas sin sangra y las instrucciones con sangra. Las etiquetas se colocan con nombre y puede o no llevar dos puntos al final, pero los dos puntos se recomiendan para funciones o subrutinas. Las etiquetas no se pueden repetir dentro de un programa, hay que cambiar el nombre en caso de que tengamos dos con el mismo, si no, provocar un error en el compilador. El GOTO se usa para dirigirse a una etiqueta colocando enfrente el nombre. Ejemplo: main: ;rutina principal main lleva dos puntos y no lleva sangra. CLRF WREG ;cdigo con sangra infinito ;etiqueta sin sangra GOTO infinito ;ir a la etiqueta infinito (se hace un bucle infinito)

Instruccin BCF
La instruccin BCF coloca un bit en cero de un registro especfico. El conteo de bits es desde del cero hasta el siete. Su sintaxis es la que a continuacin se muestra: BCF REGISTRO, BIT Ejemplo: Colocar el BIT 0 del registro PORTC en cero. BCF PORTC, 0 Tambin podemos usar el nombre del bit, para eso, consultar el manual del microcontrolador y algunos de ellos sern explicados en este documento. Ejemplo: Colocar el BIT RC0 del registro PORTC en cero. BCF PORTC, RC0 o BCF PORTC, 0 Comparando ambos cdigos, es exactamente lo mismo.

16

Instruccin BSF
Es exactamente igual que BCF solo que este coloca en uno el bit indicado de el registro deseado. Ejemplo: Colocar en uno el bit RA4 del registro PORTA. BSF PORTA, RA4

Instruccin RLCF
Esta instruccin realiza un giro a la izquierda de bits del contenido un registro cualquiera pasando por la bandera Carry del registro STATUS. La instruccin que realiza la mis ma operacin sin que pase por la bandera Carry del registro STATUS es RLNCF. Con esta instruccin el contenido ser el mismo pero desplazado un bit a la izquierda. Su sintaxis es: RLCF REGISTRO, DESTINO RLNCF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si es cero, se guarda en el registro W, si es uno, se guarda en el mismo registro (REGISTRO).

Instruccin RRCF
Esta instruccin realiza un giro a la derecha de bits del contenido de cualquier registro pasando por la bandera Carry del registro STATUS. La instruccin que realiza la misma operacin sin que pase por la bandera Carry del registro STATUS es RRNCF. Con esta instruccin el contenido ser el mismo, pero desplazado a la derecha. Su sintaxis es: RRCF REGISTRO, DESTINO RRNCF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si es cero, se guarda en el registro W, si es uno, se guarda en el mismo registro (REGISTRO).

Instruccin COMF
Realiza el complemento de un registro y lo puede guardar en el mismo registro o en el registro W. Su sintaxis es: COMF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si DESTINO es 0, el resultado se guarda en el registro W, si es 1, se guarda en el mismo registro (REGISTRO).

17

Instruccin SWAPF
Cambia el nibble alto por el nibble bajo y viceversa. Su sintaxis es: SWAPF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si es 0, se guarda en el registro W, si es 1, se guarda en el mismo registro. Ejemplo: Si registro contiene 35h. SWAPF REGISTRO, 1 Ahora registro contendr 53h.

Instruccin CALL
Esta instruccin manda a llamar a una subrutina. Las subrutinas son aquellas etiquetas especiales y terminan en la palabra reservada RETURN. Ejemplo: Llamar a la subrutina OPERACION desde la rutina main. OPERACION: RETURN ;regresa al main main: CALL OPERACION ;llama a la subrutina OPERACION ;sigue el programa

Instruccin RETURN
Esta instruccin se utiliza para regresar de una subrutina a la instruccin siguiente de la rutina principal. Solo se coloca RETURN al final de la subrutina. Vease el ejemplo anterior. Si queremos devolver algn valor en el registro de trabajo podemos finalizar la subru tina con la palabra reservada RETLW. Su sintaxis es: RETLW LITERAL Donde LITERAL puede ser cualquier valor dentro del rango 0 a 255. Este valor ser guardado en el registro W.

Instruccin RETFIE
Esta instruccin se utiliza para finalizar una subrutina de interrupcin. Si se finaliza la subrutina de interrupcin de alta prioridad, se coloca FAST frente a la palabra reservada RETFIE.

18

Instruccin RESET
Realiza un RESET desde el software. Se realiza exactamente lo mismo que si se presionara el botn MCLR en la tarjeta de pruebas del PIC.

Comparadores
Estas instrucciones sirven para comparar resultados o bits de estados de distintos re gistros. Sirven para tomar decisiones acerca del comportamiento del programa y cambiar su flujo.

Instruccin TSTFSZ
Esta instruccin comprueba que un registro sea cero; si es verdadero, salta una ins truccin. Su sintaxis es: TSTFSZ REGISTRO Ejemplo: Comparar si el registro PORTB es cero. TSTFSZ PORTB ;no es cero ;es cero

Instruccin CPFSEQ
Esta instruccin compara el registro W con cualquier otro registro. Salta si el contenido de los registros es idntico. Su sintaxis es: CPFSEQ REGITRO Ejemplo: Comparar PORTA con W. CPFSEQ PORTA ;no son identicos ;son idnticos

Instruccin CPFSGT
Compara si un registro con el registro W. Salta si el contenido del registro es ms grande que el contenido de W. Su sintaxis es: CPFSGT REGISTRO

19

Ejemplo: Comparar si el contenido de un registro es mayor al contenido de W. CPFSGT REGISTRO ;no es mayor ;es mayor

Instruccin CPFSLT
Compara un registro con el registro W. Salta si el contenido del registro es ms pequeo que el contenido de W. Su sintaxis es: CPFSLT REGISTRO Ejemplo: Comparar si el contenido de un registro es menor al contenido de W. CPFSLT REGISTRO ;no es menor ;es menor

Instruccin BTFSC
Verifica si un bit especfico de un registro es cero, en caso de que sea verdadero, salta una instruccin. Ejemplo: Verificar que el bit RB4 del registro PORTB sea cero. BTFSC PORTB, RB4 GOTO falso GOTO verdadero En el ejemplo anterior, si la comparacin es falsa, lee la instruccin siguiente la cual es GOTO falso, donde falso es una etiqueta. Si es verdadero, salta la instruccin y lee la instruccin GOTO verdadero, donde verdadero es una etiqueta. Esta instruccin se utiliza para realizar comparaciones y tomar decisiones acerca de un bit especfico de un registro.

Instruccin BTFSS
Es idntico que la instruccin anterior. Verifica que un bit especfico de un registro sea uno, en caso de que sea verdadero, salta una instruccin.

20

Ejemplo: Verificar que el bit RB5 del registro PORTB sea uno. BTFSS PORTB, RB5 GOTO falso GOTO verdadero En el ejemplo anterior, si la comparacin es falsa, lee la instruccin siguiente la cual es GOTO falso, donde falso es una etiqueta. Si es verdadero, salta la instruccin y lee la instruccin GOTO verdadero, donde verdadero es una etiqueta. Al igual que la instruccin anterior, tambin esta se utiliza para realizar comparaciones y tomar decisiones en cuanto un bit especfico de un registro.

Operadores Lgicos
Los operadores lgicos realizan las operaciones del lgebra booleana. Estas operaciones en ensamblador son AND, OR, XOR, que corresponden respectivamente a una operacin AND (Y), operacin INCLUSIVE OR (O inclusiva) y EXCLUSIVE OR (O exclusiva).

Operacin AND
Se puede realizar de dos maneras: ANDWF y ANDLW. La primera realiza la operacin AND entre un registro y el registro W; la segunda, realiza la operacin AND entre el re gistro W y una literal (un nmero). Sus sintaxis respectivas son: ANDWF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si es cero, se guarda en W, si es uno, se guarda en el mismo registro. ANDLW LITERAL Donde LITERAL es un nmero del 0 al 255.

Operacin OR
Igual que la instruccin anterior, se puede realizar de dos maneas: IORWF o con la instruccin IORLW. La primera realiza al operacin OR entre un registro y el registro W, la segunda realiza la operacin OR entre el registro W y una literal. Sus sintaxis respectivas son: IORWF REGISTRO, DESTINO Donde DESTINO puede ser 0 o 1. Si es cero, se guarda en W, si es uno, se guarda en el mismo registro. 21

IORLW LITERAL Donde LITERAL puede ser cualquier nmero del 0 al 255.

Operacin XOR
La operacin XOR al igual que las anteriores tiene dos formas de hacerse entre registros y una a bit. Primero veamos la operacin XOR a registros. Se puede realizar de dos maneras: XORWF o XORLW. La primera realiza la operacin XOR entre el registro W y cualquier otro registro, la segunda realiza la operacin XOR entre un registro y una literal. Sus sintaxis respectivas son: XORWF REGISTRO, DESTINO Donde destino puede ser 0 o 1. Si es cero, se guarda en W, si es uno, se guarda en el mismo registro. XORLW LITERAL Donde LITERAL puede ser cualquier nmero del 0 al 255. Hay un caso particular en donde se puede realizar la operacin XOR a un bit. Lo que realiza esta instruccin es cambiar el estado de un bit, si es cero, lo cambia a 1, si es uno lo cambia a 0. Puede ser tambin visto como una negacin o una operacin toggle (refirindose a flip-flops). Esta instruccin es BTG. Su sintaxis es: BGT REGISTRO, BIT Donde REGISTRO es cualquier registro y BIT, es el nmero de bit entre el 0 y el 7. Bsicamente se puede usar para realizar parpadeos o cambios de estado en un registro.

Operadores aritmticos
Los operadores aritmticos se utilizan para sumar, restar y multiplicar nmeros y registros. Tomar en cuenta que en ensamblador para PIC no existe la operacin DIVISIN, mas sin embargo, se puede realizar una operacin que la realice. Como la operacin mdulo depende de la operacin divisin, tampoco existe dentro de las operaciones bsicas del ensamblador. Una cosa muy importante que hay que tomar en cuenta es que al realizar operacio nes aritmticas se generan cambios en el registro STATUS. Este registro de estado controla el resultado de una operacin aritmtica o lgica. Su descripcin la veremos ms adelante cuando veamos registros y lo explicaremos ampliamente por importancia.

Operador NEGF
Este operador sirve para convertir un nmero contenido en un registro a negativo o viceversa. Su sintaxis es:

22

NEGF REGISTRO Donde REGISTRO es cualquier registro que contiene un nmero entre el -128 a 127.

Suma o adicin
Para realizar la suma o adicin se suelen usar dos instrucciones: ADDWF para hacer la adicin entre el registro W y otro registro o ADDLW para hacer la suma del registro W con una literal. Sus sintaxis respectivas son: ADDWF REGISTRO, DESTINO Donde REGISTRO es cualquier registro y DESTINO puede ser un valor 0 o 1. Si es cero, se guarda el resultado en W, si es uno se guarda el resultado en el mismo registro. ADDLW LITERAL Donde LITERAL es cualquier nmero entre el 0 y el 255. En ambos casos si la suma supera el 255 se encender las banderas de Carrier y Overflow del registro STATUS.

Resta o sustraccin
Para realizar la suma o sustraccin, se suelen usar dos instrucciones: SUBWF para hacer la sustraccin entre el registro W y cualquier otro registro o SUBLW para hacer la resta del registro W con una literal. Sus sintaxis respectivas son: SUBWF REGISTRO, DESTINO Donde REGISTRO es cualquier registro y DESTINO toma el valor de 0 o 1. Si es cero, se guardar el resultado en el registro W, si es uno, se guardara el resultado en el mismo registro. SUBLW LITERAL Donde literal es cualquier nmero entre el 0 y el 255.

Multiplicacin
La multiplicacin se realiza con dos instrucciones: MULWF para realizar la multiplicacin entre el registro W y cualquier otro registro o MULLW para realizar la multiplicacin entre el registro W y una literal. Sus sintaxis respectivas son: MULWF REGISTRO MULLW LITERAL Donde LITERAL puede ser cualquier nmero del 0 al 255. Registro puede ser cual quier registro de estado o memoria.

23

NOTA: El resultado de esta operacin se guarda en los registros PRODH y PRODL que son el resultado de 16 bits en su nible alto y bajo respectivamente.

Incrementos y decrementos
Los incrementos y decrementos se realizan de dos formas, realizando solo su operacin convencional o realizando su operacin con una comparacin. Explicar esto en cada caso.

Incremento
Los incrementos lo que realizan es sumar uno a un determinado registro. Una vez que llegue a 255 el siguiente incremento causar que el contenido del registro sea cero, y se encender la bandera de overflow del registro STATUS. La palabra reservada para realizar un incremento se utiliza la palabra reservada INCF. Su sintaxis es la siguiente: INCF REGISTRO Donde registro es cualquier registro de memoria. Para evitar que estemos comprobando el error de OVERFLOW en la bandera STATUS, tenemos una instruccin que lo hace por nosotros y cuando esto sucede, salta una instruccin. Esta instruccin tiene la palabra reservada INCFSZ que compara cuando el registro vuelve a ser cero y como mencion anteriormente, salta la siguiente instruccin. INCFSNZ realiza lo mismo pero salta la siguiente instruccin si no es cero. Sus sintaxis respectivas son las siguientes: INCFSZ REGISTRO ;No hay overflow ;Hay overflow INCFSNZ REGISTRO ;Hay overflow ;No hay overflow

Decrementos
Los decrementos lo que hacen es restar uno a un determinado registro hasta llegar a cero. La palabra reservada para realizar un decremento es DECF y su sintaxis es la siguien te: DECF REGISTRO Donde REGISTRO es cualquier registro de memoria.

24

Hay una instruccin que comprueba automticamente cuando llega a cero, la cual es DECFSZ y salta la siguiente instruccin cuando esto sucede. DECFSNZ realiza la misma tarea pero salta la siguiente instruccin mientras no sea cero. Sus sintaxis son: DECFSZ REGISTRO ;no es cero ;es cero DECFSNZ REGISTRO ;es cero ;no es cero

25

PROGRAMACIN BSICA DEL PIC18F4550


Ahora en este apartado vamos a ver como se programa el PIC18F4550, pero antes vamos a ver una descripcin de los registros que vamos a utilizar en los primeros pasos.

Registros bsicos del PIC18F4550


Vamos a ver tres registros bsicos del PIC18F4550, los cuales son WREG, TRIS y PORT. Un registro es un mapeo en memoria RAM de algn dispositivo fsico del PIC, como son los puertos de entrada o salida, temporizadores, mdulo usb, modulo serial, modulo ADC, etc.

Registro WREG
El registro WREG se utiliza para guardar datos temporales en RAM para operaciones y el intercambio de datos entre las mismas operaciones. Se puede utilizar para regresar da tos de subrutinas y de tablas.

Registros TRIS
Los registros TRIS sirven para configurar puertos, lo explicar ms adelante. Hay cinco, que son el nmero de puertos que tiene el PIC18F4550, los cuales son TRISA, TRISB, TRISC, TRISD y TRISE. Todos son de 8 bits, excepto TRISE que es de 4 bits (nibble bajo) los dems no tienen efecto.

Registros PORT
Los registros PORT sirven para leer y escribir puertos, y tambin lo explicar ms a delante. Hay cinco, que son el nmero de puertos que tiene el PIC18F4550, los cuales son PORTA, PORTB, PORTC, PORD y PORTE. Todos son de 8 bits excepto PORTE que es de 4 bits y se lee como cero el nibble alto del registro.

Configurar puertos
Antes de configurar los puertos es necesario saber que si usamos el oscilador exter no (que es nuestro caso) el puerto A tendr dos pines menos los cuales son RA6 y RA7. Tambin estn desactivados de forma predeterminada los pines RC4 y RC5 ya que utilizan el mdulo USB y no est disponible RC3; esto nos deja el puerto C de bits, a menos que desactivemos el mdulo USB. El puerto E tiene solo 3 bits ya que RE3 es usado por MCLR. Para configurar todo el puerto A como salida (6 pines que tiene el puerto A por que 26

dos se usan con el oscilador) se realiza lo siguiente: MOVLW 0x00 MOVWF TRISA Configurar el puerto B como salida: MOVLW 0xFF MOVWF TRISB Configurar la primera mitad del puerto como entrada y la segunda mitad del puerto como salida. MOVLW 0xF0 ;nibble bajo salida (0) nibble alto entrada (F) MOVWF TRISD Para los dems puertos es exactamente el mismo procedimiento, considerando las restricciones que tenemos en los pines de los puertos A, C y E.

Leer y escribir puertos


Debemos tener las mismas consideraciones que en el registro TRIS sobre los pines desactivados por el uso de oscilador externo, USB y MCLR. Ahora veamos como se escribe y se leen los puertos. ESCRIBIR: MOVLW 0xFF MOVWF PORTD ;se encienden todos los pines del puerto D LEER: MOVF PORTB, W ;se mueve el dato en PORTB al registro de trabajo.

27

O tambin podemos realizar la lectura hacia un registro de memoria. MOVFF PORTB, VARIABLE ;se mueve el contenido en el registro PORTB a una variable en RAM.

Consideraciones para el flujo del programa


El PIC cuando es borrado, solo tiene instrucciones NOP en su interior las cuales son el cdigo 0xFFF. Para evitar que al terminar un programa vuelva al inicio de la memoria (VECTOR RESET) debemos de realizar un ciclo infinito que evite que se lea la zona de NOP que est al final del programa. Para esto usamos la etiqueta ciclo y el goto ciclo al final de la plantilla. Otra consideracin importante es que cuando encendemos el microcontrolador PIC18F4550 los puertos son configurados como analgicos, para configurar los puertos como digitales tenemos que colocar 0x0F en el registro ADCON1. Ahora no lo explico porque lo vamos a ver ms adelante en Convertidor Analgico Digital. Antes que cualquier instruccin, se debe de limpiar el registro de trabajo W. Debe de ser la primera instruccin despus de la etiqueta main. Ahora veamos un pequeo programa. Colocar solo el cdigo que va dentro de la rutina principal llamada main para evitar colocar toda la plantilla. Ejemplo 1: Encender todo el puerto A. Solucin: Colocar 0xFF o 0x3F en el PORTA y en TRISA 0x00 o 0xC0, considerando los pines que no estn disponibles por el oscilador. Solucin 1.1
main: CLRF WREG ;Limpiamos el registro de trabajo. MOVLW H'0F' ;Configuramos todos los puertos como digitales MOVWF ADCON1 CRLF TRISA ;Configuramos todo el puerto como salida SETF PORTA ciclo GOTO ciclo END

28

Solucin 1.2
main: CLRF WREG ;Limpiamos el registro de trabajo. MOVLW H'0F' ;Configuramos todos los puertos como digitales MOVWF ADCON1 MOVLW H'C0' MOVWF TRISA MOVLW H'3F' MOVWF PORTA ciclo GOTO ciclo END

Las dos soluciones nos dan el mismo resultado. Al escribir este cdigo en el pic con el HID Bootloader, veremos que se enciende todo el puerto. En nuestra placa de prueba, encendern RA4 y RA5. Ejemplo 2: Encender solo el pin RA4. Solucin: Colocamos 0x00 en TRISA y 0x10 en PORTA o usar BSF para encender el PIN RA4. Solucin 2.1
main: CLRF WREG MOVLW H'0F' MOVWF ADCON1 ;Configuramos los puertos como digitales CLRF TRISA MOVLW H'10' MOVWF PORTA ciclo GOTO ciclo END

29

Solucin 2.2
main: CLRF WREG MOVLW H'0F' MOVWF ADCON1 ;Configuramos los puertos como digitales CLRF TRISA ;Todo el puerto como salida CLRF PORTA ;Ponemos el puerto A en ceros BSF PORTA, RA4 ;Encendemos RA4 ciclo GOTO ciclo END

Los dos ejemplos realizan exactamente lo mismo. Como podemos ver, se puede colocar todo el puerto como salida aunque no utilicemos el resto de los pines. Ejemplo 3: Verificar que el puerto B contenga el nmero 55h o AAh, en el primer caso, encender RC0, en el segundo caso encender RC1, cualquier otro caso apagar ambos pines; los dos pines no pueden estar encendidos al mismo tiempo. Hacer la comprobacin de forma indefinida. Solucin: Colocar la comprobacin dentro del ciclo infinito. Utilizar la comparacin de igualdad CPFSEQ.
main: CLRF WREG MOVLW H'0F' MOVWF ADCON1 ;Configuramos los puertos como digitales CLRF TRISC ;Todo el puerto como salida SETF PORTB ;Todo el puerto como entrada CLRF PORTC ;Ponemos el puerto C en ceros ciclo MOVLW H'55' CPFSEQ PORTB GOTO comprueba2 MOVLW H'01' MOVWF PORTC GOTO ciclo

30

comprueba2 MOVLW H'AA' CPFSEQ PORTB GOTO apagapuerto MOVLW H'02' MOVWF PORTC GOTO ciclo apagapuerto CLRF PORTC GOTO ciclo END

Notemos que cada vez que realizamos un programa ms avanzado, va aumentando su tamao. Todo es dependiendo del objetivo a alcanzar. Hay que tener mucha lgica para realizar un programa para microcontrolador.

Retardos
Para realizar un retardo dentro de un programa podemos usar instrucciones NOP, que equivalen a 4 ciclos del oscilador principal, mas sin embargo, esta condicin no se cumple cuando usamos Bootloader, ya que realizamos un aumento en frecuencia para el uso de USB. La frecuencia necesaria para la comunicacin USB es de 48MHz. La frecuencia es una cuarta parte, por que cada instruccin se ejecuta en 4 ciclos del oscilador, por lo tanto, la frecuencia de una instruccin es de 12MHz. Sabemos tambin que el periodo es inverso de la frecuencia, as que, el tiempo que tarda en realizarse cada instruccin es de 83.33ns. T= T= 1 f

1 =20.83ns 48MHz Ti=4T Ti=4x(20.83ns)=83.33ns Tomando en cuenta que cada instruccin toma 83.33ns, realicemos un retardo de 10s. Para ello tenemos que dividir 10s entre 83.33ns; esto nos dar un nmero, al cual le llamaremos nmero mgico de retardo, y lo simbolizaremos con #. #= 10 s =120 83.33 ns

Entonces tenemos que realizar 120 instrucciones consecutivas para realizar el retar do de 10s. 31

Cmo vamos a realizar el retardo o demora? Usaremos decrementos. Primero vamos a generar una variable en RAM y le vamos a cargar el nmero m gico, posteriormente vamos a realizar el decremento hasta llegar a cero. Esto nos garantiza que se realicen # instrucciones. Ejemplo: Realizar un programa que haga que el led RA5 parpadee cada 10s. Solucin: Realizar un retardo de 10s y usar BTG para hacer parpadear el led RA5.
UDATA_ACS RETARDO RES 1 ;Reservamos memoria para el registro RETARDO ;nos saltaremos esta parte de la plantilla retardo: ;Subrutina de retardo MOVLW .120 ;Colocamos 120 decimal en WREG MOVWF RETARDO ;Colocamos el valor de WREG en RETARDO decremento DECFSZ RETARDO ;Realizamos el retardo GOTO decremento RETURN main: CLRF WREG MOVLW H'0F' MOVLW ADCON1 CLRF TRISA CLRF PORTA ciclo BTG PORTA, RA4 CALL retardo GOTO ciclo END

Como podemos observar en el ejemplo anterior, se realiz una subrutina que realiza el retardo de 10s.

32

La divisin y el mdulo
Como ya antes habamos mencionado, la divisin en ensamblador para el PIC18F4550 no existe. Nosotros tenemos que realizarla con un cdigo bastante pequeo. Vamos a las matemticas bsicas: La multiplicacin es una suma sucesiva de nmeros y como la divisin es la operacin contraria, entonces por definicin es una resta sucesiva. Esta operacin la realizaremos restando el divisor al dividendo, hasta que sea ms grande el divisor que el dividendo; en este momento tendremos el resultado que es el nme ro de restas que hemos hecho. Si tomamos en cuenta que el mdulo es el residuo de la divisin, entonces el dividendo que queda al final ser el mdulo. Hagamos un algoritmo para la divisin y posteriormente lo pasaremos al lenguaje ensamblador. 1. Tenemos una variable divisor y una dividendo. 2. Verificamos que el dividendo sea mayor al divisor. Si es cierto seguir, si no ir al paso 6. 3. Restar el divisor al dividendo. 4. Incrementamos uno un contador. 5. Ir al paso 2. 6. El resultado de la divisin es el contador, el resultado del mdulo es el residuo del dividendo. 7. Fin del algoritmo. Ahora hagamos la subrutina en ensamblador.
UDATA_ACS DIVISOR DIVISION RES RES 1 ;Reservamos memoria para el divisor. 1 ;Reservamos memoria para el dividendo. 1 ;Reservamos memoria para el contador de la divisin. DIVIDENDO RES

;Nos saltaremos esta parte de la plantilla. division: CLRF DIVISION ;colocamos en cero el contador. MOVF DIVIDENDO, W ;Colocamos el valor del dividendo en W. comparadiv CPFSLT DIVISOR ;Comparamos W con DIVISOR. GOTO hacerdivision GOTO findivision

33

hacerdivision SUBWF DIVISOR, W ;Realizamos la resta. El resultado se guarda en W. INCF DIVISION ;Incrementamos el contador. GOTO comparadiv findivision MOVF DIVISION, W ;Colocamos el resultado de la divisin en W. ;El resultado se regresar en WREG. RETURN ;Fin del subproceso.

Para el mdulo es exactamente lo mismo, solo cambiaremos el nombre de la subrutina, las etiquetas y el resultado.
modulo: CLRF DIVISION ;colocamos en cero el contador. MOVF DIVIDENDO, W ;Colocamos el valor del dividendo en W. comparamodulo CPFSLT DIVISOR ;Comparamos W con DIVISOR. GOTO hacermodulo GOTO finmodulo hacermodulo SUBWF DIVISOR, W ;Realizamos la resta. El resultado se guarda en W. INCF DIVISION ;Incrementamos el contador. GOTO comparamodulo finmodulo ;el resultado del mdulo est en W que es el sobrante de la resta. ;El resultado se regresar en WREG. RETURN ;Fin del subproceso.

Como podemos observar en los algoritmos anteriores, podemos realizar operaciones con las instrucciones bsicas del PIC.

El display LCD alfanumrico


El display LCD alfanumrico que mostrar en esta seccin, ser de 16 caracteres por dos lneas de matriz de 5x7. Realizar 4 subrutinas para hacer el proceso lo ms fcil posible; no voy a explicar estas subrutinas a fondo, solo mencionar como funcionan y qu 34

es lo que hay que agregar en caso de requerir una funcionalidad extra. Explicar un archivo INC que contiene definiciones de las instrucciones del LCD. Para mayor informacin consultar el manual tcnico (data sheet) del LCD alfanumrico. Comencemos con el archivo LCD.INC. Este archivo contiene algunas constantes con instrucciones del LCD que controlan su funcionamiento.
;***************************************** ; Autor: Garca Olmos Francisco Javier * ; Fecha: 24 de Noviembre de 2011 * ; Archivo: LCD.INC * ; Biblioteca para el display LCD * ;***************************************** ;Acciones del display CLEAR EQU CURSOR_HOME EQU ;Control del display DISPLAY_CONTROL DON CURSOR_ON BLINK_ON ;Modo de entrada DISPLAY_MODE INCREMENT SHIFT EQU EQU EQU H'04' H'02' H'01' H'13' H'17' H'1B' H'1F' H'20' H'10' H'03' H'07' H'0B' H'80' H'C0' H'90' H'D0' EQU EQU EQU EQU H'08' H'04' H'02' H'01' H'01' H'02'

;Shift_Cursor Display SHIFT_CUR_LEFT EQU SHIFT_CUR_RIGHT EQU SHIFT_DISP_LEFT EQU SHIFT_DISP_RIGHT EQU ;Function Set FUNCTION_SET EIGHT_BIT LINE_5x7 LINE_5x10 LINES_5x7 DDRAM_L1 DDRAM_L2 DDRAM_L3 DDRAM_L4 EQU EQU EQU EQU EQU EQU EQU EQU EQU

Ahora mostrar las subrutinas, las cuales se usarn en el proceso de escritura y configuracin del LCD alfanumrico.

35

;Variables necesarias para el funcionamiento del LCD alfanumrico. UDATA_ACS DATO DATOTEMP RTMUL RETARDO1 RETARDO2 RES RES RES RES RES 1 1 1 1 1

;Nos saltaremos esta parte de la plantilla ;Funciones para escritura y configuracin del LCD alfanumrico. Delay1K: retardo0 DECFSZ RTMUL goto retardo1 goto finretardo retardo1 MOVLW .100 MOVWF RETARDO1 ciclo1 DECFSZ RETARDO1 GOTO retardo2 GOTO retardo0 retardo2 MOVLW .10 MOVWF RETARDO2 ciclo2 DECFSZ RETARDO2 GOTO ciclo2 GOTO ciclo1 finretardo RETURN Comando_LCD: MOVFF DATO, DATOTEMP RRCF DATO RRCF DATO RRCF DATO RRCF DATO MOVFF DATO, PORTD BCF PORTD, RD4 BCF PORTD, RD5 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 MOVFF DATOTEMP, PORTD BCF PORTD, RD4 BCF PORTD, RD5 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 RETURN

36

Dato_LCD:

MOVFF DATO, DATOTEMP RRCF DATO RRCF DATO RRCF DATO RRCF DATO MOVFF DATO, PORTD BSF PORTD, RD4 BCF PORTD, RD5 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 MOVFF DATOTEMP, PORTD BSF PORTD, RD4 BCF PORTD, RD5 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 RETURN Inicializa_LCD: MOVLW .137 MOVWF RTMUL CALL Delay1K MOVLW 0x02 MOVWF PORTD BSF PORTD, RD6 MOVLW .60 CALL Delay1K BCF PORTD, RD6 MOVLW .187 MOVWF RTMUL CALL Delay1K MOVLW FUNCTION_SET IORLW LINES_5x7 MOVWF DATO CALL Comando_LCD MOVLW DISPLAY_CONTROL IORLW DON MOVWF DATO CALL Comando_LCD MOVLW CLEAR MOVWF DATO CALL Comando_LCD MOVLW DISPLAY_MODE IORLW INCREMENT MOVWF DATO CALL Comando_LCD RETURN

Las cuatro subrutinas son muy fciles de entender, mas sin embargo, ser tarea ex tra, ya que por motivos de tiempo y espacio, no podr hacer en este documento, solo explica37

r su funcionamiento. La funcin Delay1K sirve para darnos un retardo de 1000 ciclos de mquina (4 de oscilador principal). Esta funcin recibe un parmetro dentro del registro RTMUL que ser el multiplicador, entonces ser un retardo de RTMUL por mil ciclos de mquina. La subrutina Comando_LCD recibe un parmetro en el registro DATO y lo escribe en el LCD en forma de comando. La subrutina Dato_LCD tambin recibe un parmetro en el re gistro DATO pero este lo escribir en el LCD como un DATO y se mostrar. La subrutina Inicializa_LCD no recibe parmetros. Sirve para configurar el LCD como un Display LCD de 16x2, de matriz de 5x7 y de incremento automtico. No se mostrar el cursor y no parpadear el caracter. Si se necesitan estas funciones, cambiarlas en esta subrutina. Procedimiento para escribir en el LCD: 1. Inicializar el LCD. 2. Limpiar pantalla. 3. Moverse a la posicin deseada. 4. Escribir. Bueno, entonces hagamos un pequeo programa que muestre HOLA en la pantalla pero antes mencionar que se conectar al puerto D. Ejemplo 1: Mostrar HOLA en el LCD de 16x2. Solucin: Utilizar las funciones explicadas anteriormente, as como el procedimiento.
; *** Aqu van los registros de memoria *** ; *** Saltaremos esta parte de la plantilla *** ; *** Aqu van las subrutinas o funciones del LCD *** main: CLRF WREG MOVLW H'0F' MOVWF ADCON1 CLRF TRISD CLRF PORTD CALL Inicializa_LCD ;Inicializamos el LCD. MOVLW CLEAR ;Instruccin para limpiar en el LCD (ver LCD.INC). MOVWF DATO ;Movemos al parmetro DATO. CALL Comando_LCD MOVLW DDRAM_L1 ;Instruccin para moverse a la lnea 1 ADDLW .6 ;Sumamos 6 para desplazarnos 6 caracteres y centrar el texto. MOVWF DATO ;Movemos al parmetro DATO. CALL Comando_LCD MOVLW 'H' MOVWF DATO CALL Dato_LCD MOVLW 'O'

38

ciclo

MOVWF DATO CALL Dato_LCD MOVLW 'L' MOVWF DATO CALL Dato_LCD MOVLW 'A' MOVWF DATO CALL Dato_LCD CLRF PORTD ;Limpiamos el puerto D. GOTO ciclo END

Se puede observar que lo ms complicado de entender son los comandos, los datos se mandan consecutivamente sin mayor problema. Un punto importante es que se realiz una suma de 6 para desplazar la memoria y centrar el texto. Si no hubiramos hecho esta suma, el texto hubiera aparecido desde el primer carcter en el LCD. Ahora veamos las conexiones del LCD. El LCD tiene dos pines de alimentacin, uno de contraste, tres de control, ocho de datos y dos extras en caso de que tenga luz de fondo (back light). VSS y VDD se conectan a +5V y tierra, y el contraste VEE se conecta a un potencimetro de 10K, el pin 4 de control RS (decide si es dato o comando) a RD4, el pin 5 de control RW (lectura / escritura) va conectado a RD5 o a tierra, el pin 6 de control E (habilitado) a RD6. De los siguientes ocho pines de datos solo se utilizarn los ltimos 4 (D4, D5, D6, D7) que van conectados a RD0, RD1, RD2, y RD3; los pines D0, D1, D2 y D3 no se conectan. En caso de luz de fondo se conectaran a +5V y tierra los ltimos pines. El siguiente diagrama muestra la forma de conexin del LCD alfanumrico de 16x2.

Forma de conectar el LCD alfanumrico de 16x2 sin luz de fondo.

39

PROGRAMACIN CON INTERRUPCIONES


En este captulo veremos la programacin con interrupciones, veremos ms profundamente las direcciones de los vectores de interrupcin y las rutinas ISRL e ISRH. Veremos los registros INTCON y RCON que son los relacionados con las interrupciones. Primero explicar que es una interrupcin. Bsicamente es una peticin que se le ha ce al microprocesador o microcontrolador (no son lo mismo) para que deje la tarea principal y haga una tarea especfica. Un ejemplo de una interrupcin es el RESET, que deja la tarea principal para reiniciar la memoria del microcontrolador.

Clasificacin de las interrupciones


Se pueden clasificar las interrupciones de tres formas distintas: Por enmascaramiento, por prioridad y por su locacin.

Clasificacin por enmascaramiento


Hay dos tipos de interrupciones: enmascarables y no enmascarables. 1. Las interrupciones enmascarables son aquellas donde el microcontrolador puede decidir si la puede atender o no (enmascara la interrupcin). 2. Las interrupciones no enmascarables son aquellas que forzosamente se tienen que atender, por ejemplo, el RESET.

Clasificacin por prioridad


Hay dos tipos de interrupciones: de alta prioridad y de baja prioridad. 1. Las interrupciones de alta prioridad son aquellas que no pueden interrumpirse mientras son atendidas. 2. Las interrupciones de baja prioridad si pueden interrumpirse por otras mientras son atendidas, mas sin embargo su tiempo de respuesta es ms amplio que el de una de alta prioridad.

Clasificacin por locacin


Hay tres tipos de interrupciones: Internas, cambio de flanco y externas. 1. Las interrupciones internas son las que se provocan por los dispositivos embebidos en el microcontrolador, como son temporizadores, ADC, USB, USART, Comparadores, etc. 2. La interrupcin por cambio de flanco es aquella que se activa al cambiar el estado del 40

nibble alto del puerto B. 3. Las interrupciones externas son las que se provocan al activar los tres primeros pines del puerto B (RB0, RB1 y RB2); se identifican como INT0, INT1 e INT2. INT0 siempre es de alta prioridad.

Vectores de interrupcin
Antes de comenzar, explicar que es un vector. En algunos lenguajes de programacin como C ANSI, C++, BASIC, etc, se pueden realizar vectores de datos y se manejan los datos a travs de un apuntador, el cual contiene una direccin de memoria. Nosotros nos referiremos a un vector de interrupcin a la posicin de memoria a la cual el microcontrolador se va a referir cuando se realice una interrupcin. En los microcontroladores PIC18 hay 3 vectores de interrupcin: RESET, alta prioridad y baja prioridad. Abajo explicare sus direcciones: 0x0000 0x0008 0x0018 MCLR ISRH ISRL Vector de interrupcin de RESET. Vector de interrupcin de alta prioridad. Vector de interrupcin de baja prioridad.

Estas direcciones se cargan automticamente en el stack de direcciones al realizarse una interrupcin. Mas sin embargo, cuando trabajamos con el BOOTLOADER, estas direcciones cambian. 0x1000 0x1008 0x1018 REMAPED MCLR REMAPED ISRH REMAPED ISRL Vector remapeado de RESET. Vector remapeado de alta prioridad. Vector remapeado de baja prioridad.

Como observamos, son las que estn en nuestra plantilla. Podramos hacer la rutina de interrupcin en esta direccin pero el espacio es muy pequeo, lo que realizamos es un salto a las rutinas llamadas main, ISRH e ISRL. En estas rutinas, ya podemos extendernos lo que sea necesario, siempre y cuando nos alcance la memoria de programa del microcontro lador PIC. Declaramos dichos vectores con CODE o con ORG como ya lo habamos mencionado anteriormente. REMAPED_RESET_VECTOR CODE 0x1000 goto main ;saltamos a la rutina main.

41

Configurar las interrupciones


Las interrupciones se configuran cambiando sus bits especficos en los registros de interrupcin INTCON, INTCON2, INTCON3, PIR1, PIR2, IPR1, PIR2, PIE1 y PIE2. Para las interrupciones externas y de cambio de flanco se usan solo los tres primeros registros men cionados anteriormente. La nica interrupcin que no se configura es RESET. El mtodo que se utiliza es el siguiente: 1. Borramos la bandera (FLAG) de interrupcin. 2. Le damos una prioridad ya sea alta o baja, excepto INT0 que es de alta prioridad. 3. Habilitamos la interrupcin. 4. Habilitamos las interrupciones globales con RCON. 5. Habilitar las prioridades globales de las interrupciones con INTCON. Las interrupciones globales son todas aquellas interrupciones enmascarables que hay dentro del microcontrolador. Se activan colocando el bit IPEN del registro RCON en uno. Las prioridades globales se activan colocando en uno el bit GIEH para las interrupciones de alta prioridad y GIEL para las interrupciones de baja prioridad o ambas del registro INTCON. Las interrupciones externas tienen que configurar tambin el flanco en el cual estas trabajan; este flanco puede ser de subida o de bajada, esto significa que al presionar un botn, el voltaje cambia de bajo a alto para subida o de alto a bajo para bajada. Una configuracin adicional es el uso de resistencias PULL-UP. Estas resistencias realizan que el puerto B siempre est estado alto y evitan que se usen resistencias fuera del microcontrolador. Se activan colocando el bit RBPU en cero del registro INTCON2. Al utilizar estas resistencias, el flanco de las interrupciones externas debe de ser de bajada y el botn debe de estar conectado a tierra para hacer un cambio a estado bajo. Para mayor referencia de los registros INTCON, RCON y los dems mencionados anteriormente, revisar el manual.

Revisar las interrupciones


Cuando una interrupcin se ha realizado, se enciende la bandera (FLAG) respectiva de cada interrupcin. Dependiendo de la configuracin verificamos que se ha realizado la interrupcin en las rutinas ISRH o ISRL. La interrupcin externa INT1 tiene su bandera (FLAG) en INTCON. El bit se llama INT0IF y est en cero mientras no se ha producido la interrupcin y cambia a uno cuando se ha realizado. Una accin muy importante es borrar la bandera de forma manual para evitar que se realice el proceso de interrupcin cuando no se ha interrumpido el microcontrolador por esta interrupcin.

42

Ejemplo: Revisar si se realiz la interrupcin INT1 como interrupcin de baja prioridad.


ISRL: movff STATUS,STATUS_TEMP movff WREG,WREG_TEMP movff BSR,BSR_TEMP ;guarda el registro de estado ;guarda el registro de trabajo ;guarda el registro BSR

btfss INTCON3, INT1IF ;Revisar si se realiz por INT1 goto finintl ;No se realiz por INT1 ;si se realiz por INT1 bcf INTCON3, INT1IF ;Borrar la bandera ;Seguir con el proceso de interrupcin. finintl movff BSR_TEMP,BSR movff WREG_TEMP,WREG movff STATUS_TEMP,STATUS retfie ;restaura el registro BSR ;restaura el registro de trabajo ;restaura el registro de estado

Como podemos observar, hay que conservar el cdigo que recupera los estados de BSR, WREG y STATUS, ya que son necesarios para otras operaciones. Observamos tambin que se utiliz el comparador de bits BTFSS y el cambio de estado de bit a cero con la instruccin BCF. Si hubiera ms interrupciones habra que hacer el mismo procedimiento para cada una de ellas.

Interrupciones externas
En este apartado me enfocar solamente en las interrupciones externas. Realizar el cdigo de configuracin de las tres interrupciones y posteriormente realizar su verificacin en las subrutinas ISRH e ISRL. Ejemplo 1: Realizar la configuracin de las interrupciones externas con resistencias de pull-up y flanco de bajada. INT1 es de alta prioridad e INT2 es de baja prioridad. Colocar el Puerto C como salida. Solucin 1: Realizar el procedimiento de configuracin de las interrupciones tomando en cuenta que INT0 siempre es de alta prioridad. Colocar el puerto B como entrada y el puerto C como salida colocando TRISB en uno y TRISC en cero.

43

main:

clrf WREG movlw H'0F' movwf ADCON1 ;configuramos los puertos como digitales. setf TRISB ;Puerto B como entrada. clrf TRISC ;Puerto C como salida. clrf PORTC ;Puerto C apagado.

; *** Configuramos las interrupciones *** ;INT0 BCF INTCON, INT0IF ;Limpiamos la bandera IF. BCF INTCON2, INTEDG0 ;Flanco de bajada. BSF INTCON, INT0IE ;Habilitamos la interrupcin. ;INT1 BCF INTCON3, BCF INTCON2, BSF INTCON3, BSF INTCON3, ;INT2 BCF INTCON3, BCF INTCON2, BCF INTCON3, BSF INTCON3, INT1IF ;Limpiamos la bandera IF. INTEDG1 ;Flanco de bajada. INT1IP ;INT1 de alta prioridad (IP=1). INT1IE ;Habilitamos la interrupcin. INT2IF ;Limpiamos la bandera IF. INTEDG2 ;Flanco de bajada. INT2IP ;INT2 de baja prioridad (IP=0). INT2IE ;Habilitamos la interrupcin.

;Resistencias de PULL-UP BCF INTCON2, RBPU ;Interrupciones Globales BSF RCON, IPEN ;Habilitamos las interrupciones globales. BSF INTCON, GIEH ;Habilitamos las interrupciones globales de alta prioridad. BSF INTCON, GIEL ;Habilitamos las interrupciones globales de baja prioridad. ciclo goto ciclo ;ciclo infinito END

Del ejemplo anterior marque las configuraciones alta y baja prioridad. Ver como cambia BSF por BCF. Ejemplo 2: Usar INT0 para encender RC0, INT1 para encender RC1 e INT2 para apagar ambos bits. Solucin 2: Verificar las interrupciones en las rutinas de alta y baja prioridad con BTFSS. Utilizar BCF y BSF para apagar y encender bits.

44

ISRH: btfss INTCON, INT0IF ;Revisamos si se produjo INT0. goto revisaint1 bcf INTCON, INT0IF ;Limpiamos la bandera. bsf PORTC, RC0 ;Encendemos RC0. revisaint1 btfss INTCON3, INT1IF ;Revisamos si se produjo INT1. goto finisrh bcf INTCON3, INT1IF ;Limpiamos la bandera. bsf PORTC, RC1 ;Encendemos RC1. finisrh retfie FAST ISRL: movff STATUS,STATUS_TEMP movff WREG,WREG_TEMP movff BSR,BSR_TEMP ;guarda el registro de estado ;guarda el registro de trabajo ;guarda el registro BSR

btfss INTCON3, INT2IF ;Revisar si se realiz por INT1 goto finisrl ;No se realiz por INT1 bcf INTCON3, INT2IF ;Borrar la bandera clrf PORTC ;Apagamos el puerto finisrl movff BSR_TEMP,BSR movff WREG_TEMP,WREG movff STATUS_TEMP,STATUS retfie ;restaura el registro BSR ;restaura el registro de trabajo ;restaura el registro de estado

En este ejemplo vemos el cambio de verificacin entre rutinas de baja y alta prioridad y la forma en la que se realizan los procedimientos requeridos para sus tareas respectivas.

Interrupcin del puerto B por cambio de flanco


Esta interrupcin se activa cuando cambiamos el estado del nibble alto del puerto B (RB4, RB5, RB6 y RB7). Se activa cuando pasamos de estado bajo a alto y cuando pasamos de estado alto a bajo, por eso su nombre de cambio de flanco. La interrupcin al igual que las interrupciones externas, se configura y se le asigna prioridad sus respectivos bits y segn su prioridad, se verifica con su bandera (RBIF). Ejemplo 1: Configurar la interrupcin de cambio de flanco como interrupcin de alta prioridad. Utilizar resistencias de PULL-UP. Configurar el puerto C como salida. Solucin 1: Realizar el procedimiento para configurar interrupciones. Se tiene que configurar el puerto B como entrada.

45

main:

clrf WREG movlw H'0F' movwf ADCON1 ;Configuramos todos los puertos digitales. setf TRISB ;Puerto B como entrada. clrf TRISC ;Puerto C como salida. clrf PORTC ;Apagamos el puerto.

;Configuracin de las interrupciones ;Interrupcin de cambio de flanco bcf INTCON, RBIF ;Limpiamos la bandera. bsf INTCON2, RBIP ;Le asignamos prioridad alta. bsf INTCON, RBIE ;Habilitamos la interrupcin. ;Ressitencias de PULL-UP bcf INTCON2, RBPU ;Habilitamos las resistencias de pull up. ;Interrupciones globales bsf RCON, IPEN ;Habilitamos prioridades en interrupciones. bsf INTCON, GIEH ;Habilitamos la interrupciones de alta prioridad. ;No es necesario habilitar las interrupciones globales de baja prioridad ;por que no las usaremos. ciclo goto ciclo ;ciclo infinito

Como observamos en los comentarios, no activamos las interrupciones de baja prioridad ya que no las vamos a usar. Ejemplo 2: Revisar si se provoc una interrupcin por cambio de flanco. Si sucedi, verificar que botn fue apretado. RB4 encender o apagar segn el estado de RC0, RB5 encender o apagar segn el estado de RC1, RB6 cambiar el estado de cada Led y RB7 apagar los Leds. Solucin 2: Verificar con BTFSS que haya sucedido la interrupcin y con BTFSC verificar que botn est en cero (estado apretado). Tomar en cuenta que se utiliza lgica negativa por el uso de las resistencias de PULL-UP.
IRSH:

btfss INTCON, RBIF ;Verificar si se produjo la interrupcin RB. goto finisrh ;Ir al final de la rutina de interrupcin. bcf INTCON, RBIF ;Borrar la bandera. btfsc PORTB, RB4 ;Verificar si se apret el botn RB4. goto revisarb5 ;Revisar el siguiente botn. btg PORTC, RC0 ;Cambiar el estado de RC0 goto finisrh ;Ir al final de la rutina de interrupcin. revisarb5 btfsc PORTB, RB5 ;Verificar si se apret el botn RB5. goto revisarb6

46

btg PORTC, RC1 goto finisrh revisarb6 btfsc PORTB, RB6 ;Verificar si se apret el botn RB6. goto revisarb7 btg PORTC, RC0 ;Cambia el estado de RC0. btg PORTC, RC1 ;Cambia el estado de RC1. goto finirsh revisarb7 btfsc PORTB, RB7 ;Verificar si se apret el botn RB7. goto finisrh ;Ir al final de la rutina de interrupcin. clrf PORTC finisrh retfie FAST

Como podemos observar, adems de preguntar por la interrupcin, hay que pregun tar por el botn que se ha apretado. Como usamos lgica negativa, cuando se presiona un botn, el bit queda en estado bajo y el microcontrolador lo reconoce como cero lgico. Qu pasa si se aprietan dos botones al mismo tiempo? Pues viendo el algoritmo, el ms bajo ser el que reconozca como apretado, el otro, ser desechado. Tambin podramos usar operaciones AND para ver si se apretaron dos al mismo tiempo. Sin embargo por falta de espacio y de tiempo, ser tarea adicional del lector hacerlo. A partir de ahora, todo lo que veamos ser programado con interrupciones. Todos los mdulos embebidos en el microcontrolador tienen interrupciones y se verificarn y configurarn exactamente igual que como lo hicimos con estas dos interrupciones.

47

PROGRAMACIN DE HARDWARE INTERNO Y EXTERNO


En este captulo ensear a programar hardware externo e interno. Como hardware externo, ensear el uso de Display de 7 segmentos, teclado matricial de 4x4 y como conec tar transistores, puente H y compuertas lgicas con el PIC18F4550. Como hardware interno ensear a programar los temporizadores y contadores, as como el mdulo ADC.

Tablas
Antes de comenzar, me gustara ver un tema un poco complicado pero que nos ahorrar mucho cdigo a la hora de realizar codificaciones: Las tablas. Qu son las tablas? Son estructuras de datos guardados en la memoria de progra ma ROM (flash en el caso de PIC18F). Es una alternativa a los apuntadores, ya que el uso de apuntadores es ms complicado an que las tablas. Esto tambin nos ayuda a ahorrar memoria RAM, pues es bastante reducida en caso de microcontroladores PIC18. Cmo funciona una tabla? Realizamos retorno de literales ordenadas una tras otra, y saltamos las instrucciones necesarias para obtener el resultado requerido. Para realizar esta operacin utilizamos el registro PC (Program Counter) que es registro que maneja la memoria de programa. Le sumaremos al PCL (Program Counter Low Byte) el nmero de instrucciones que queremos que salte, pero tomando en cuenta que cada instruccin toma 2 direcciones de memoria, entonces debern de ser el nmero de saltos por dos. Tomar en cuenta que si multiplicamos por dos, el nmero mximo de saltos deber ser de 127. Para realizar una tabla utilizaremos el registro W para colocar el nmero de instrucciones que deseamos saltar y realizaremos una subrutina que realice este procedimiento. Ejemplo 1: Realizar una tabla que retorne el nmero en BCD (Cdigo para display de 7 Segmentos) del 0 al 9. Solucin 1: Realizar una subrutina que realice la suma al registro PCL y retorne el nmero en BCD.
tabla_bcd: mullw H'02' movf PRODL, W ;Movemos el resultado de la multiplicacin a W addwf PCL, F ;Hacer la suma de W con PCL y guardarla en el mismo registro PCL retlw H'3F' ;Cero en BCD retlw H'06' ;Uno en BCD retlw H'5B' ;Dos en BCD

48

retlw retlw retlw retlw retlw retlw retlw

H'4F' H'66' H'6B' H'7B' H'87' H'EF' H'6F'

;Tres en BCD ;Cuatro en BCD ;Cinco en BCD ;Seis en BCD ;Siete en BCD ;Ocho en BCD ;Nueve en BCD

Como vemos, es fcil realizar la tabla, pero lo difcil es colocarla en el lugar correcto del cdigo para que funcione, ya que el PCL es 1 byte (8 bits) y solo podr contar hasta el 255. No habr problema si estamos en un lugar que est entre el 0 y el 246 de PCL, pero si lo har si rebasamos este lmite. Es recomendable hacer tablas pequeas y colocadas exac tamente al principio del cdigo (Antes de las rutinas de Interrupcin). Ahora veamos como recuperar el cdigo. Solo colocar el algoritmo. Ejemplo 2: Realizar el algoritmo de interrupcin de INT0. Para que cada vez se presione, aumente un contador hasta el 9, llegando a este punto, reiniciarlo. Mostar el resultado en BCD en el puerto D. Solucin 2: Realizar el algoritmo en ISRH comprobando la interrupcin INT0, realizando comparaciones, incrementos y llamando a la tabla tabla_bcd realizada anteriormente.
ISRH: btfss INTCON, INT0IF ;Comprobar si se realiz la interrupcin. goto finisrh bcf INTCON, INT0IF ;Limpiar la bandera movlw H'09' cpfseq CONTADOR goto aumenta clrf CONTADOR ;Coloca cero en contador. goto muestra aumenta incf CONTADOR muestra movf CONTADOR, W ;Copiamos el contenido de CONTADOR a W. call tabla_bcd ;Llamar a la tabla. movwf PORTD ;Colocar el valor devuelto de la tabla en PORTD. finisrh retfie FAST

Con este pequeo algoritmo, hemos realizado un contador con interrupciones y un display de 7 segmentos. Nota 1: Como estamos usando lgica positiva, solo podemos usar un display de 7 segmentos de ctodo comn. Utilizar lgica negativa en la tabla para usar un display de nodo comn o utilizar un inversor externo 74LS04 o 74HS04. Nota 2: PRECAUCIN, el PIC18F4550 solo puede manejar corrientes inferiores a 49

los 25mA, si superamos esta corriente podemos quemar el pin, puerto o todo el microcontrolador. Para realizar operaciones con ms corrientes utilizar BUFFER de corriente (74LS245), Inversores (74LS04) o transistores en forma de interruptor.

Teclado Matricial
El teclado matricial que demostrar en este apartado, es uno de 4x4 (16 teclas). Utilizaremos para su decodificacin la interrupcin de cambio de nivel y la mitad del puerto B como salida. Este teclado tiene 4 filas y cuatro columnas, lo cual nos da un nmero de 8 lneas de datos (cables de alimentacin). Todas las lineas de alimentacin del teclado irn al puerto B. La mitad alimentar al teclado y la otra mitad realizar la interrupcin de cambio de nivel cuando una tecla se presione, para ello es necesario activar las resistencias de PULL-UP y colocar el primer nibble en cero. Cuando se realice una interrupcin se tendr que colocar el puerto en 1 e ir cambiando el cero de lugar hasta obtener la tecla que se presion. La comprobacin se hace en cero por el uso de resistencias de PULL-UP, entonces se utiliza la lgica negativa. Procedimiento: 1. El primer paso es colocar en cero el nible bajo o todo el puerto B. 2. Al presionar una tecla se interrumpe el microcontrolador. 3. Colocar el nible bajo en uno o todo el puerto B. 4. Colocar un cero en el bit 0 del puerto B. Si est la tecla, verificar el cdigo en el nibble alto para decodificarla y finalizar, en caso contrario, seguir al paso 5. 5. Colocar un cero en el bit 1 del puerto B. Si est la tecla, verificar el cdigo en el nibble alto para decodificarla y finalizar, en caso contrario, seguir al paso 6. 6. Colocar un cero en el bit 2 del puerto B. Si est la tecla, verificar el cdigo en el nibble alto para decodificarla y finalizar, en caso contrario, seguir al paso 7. 7. Colocar un cero en el bit 3 del puerto B. Decodificar la tecla usando el nibble alto. Si no se encuentra, se ha dejado de apretar la tecla, entonces, salir. Recordemos que al dejar de presionar la tecla se vuelve a realizar la interrupcin por el cambio de flanco, en este caso, no decodificaremos nada y tenemos que salir sin mostrar nada. Para decodificar las teclas se verifica que pin se apaga. Utilizar el nibble bajo como multiplicador el nibble alto como sumador. El nible bajo codifica filas y el alto codifica columnas. Ejemplo: La tecla 8 est en la posicin 9 tomando como referencia la posicin inicial como cero (es la dcima tecla); est en la fila 3 columna 2. Encontraremos presionada la tecla cuando el cero est en RB2 (fila 3) y el pin que se activar ser RB5 (columna 2). Entonces tendramos que realizar una multiplicacin de filas 1 por cuatro (nmero de filas) y sumar columnas 1. Tecla = ((Columnas 1) * 4)+ (Filas 1) = (3 1) * 4 + (2 1) = (2 * 4) + 1 = 8 + 1 = 9. 50

Si realizamos una tabla con valores ASCII (diferentes a los BCD) y recorremos el nmero de tecla y lo mostramos en el LCD alfanumrico, tendremos las teclas decodificadas. Aqu dejo una imagen del teclado matricial para que vean cuales son las teclas que tiene y cual es el orden que tienen cada una de ellas.

En el mercado se puede encontrar el teclado matricial con letras en vez de los smbolos de operaciones aritmticas, en su lugar, letras A, B, C, D, * en vez de ON/C y # en vez de igual. Sin embargo, dependiendo de la codificacin que le demos ser la ejecucin que realizar. En nuestro caso, solo se mostrar la tecla en el LCD alfanumrico. Realicemos un programa completo. En este programa pondremos a prueba todo lo aprendido en los temas anteriores y algo de imaginacin, as como algunos trucos para su realizacin. Ejemplo 1: Realizar el programa de decodificacin del teclado matricial en una interrupcin de cambio de flanco de alta prioridad, realizar la tabla de decodificacin de cdigo ASCII para el teclado mostrado arriba y el cdigo para mostrar en el LCD. Solucin 1: Realizar un programa completo que incluya tablas, LCD, variables e interrupciones. La decodificacin se deber realizar con el procedimiento mencionado anteriormente. Nota: Para evitar perdernos en el programa, ordenaremos las instrucciones en subrutinas. De ahora en adelante el lector debera tomar este hbito para hacer el cdigo ms e legante.

51

;*********************************************************************** ; Autor: Francisco Javier Garca Olmos * ; Fecha: 11 de Enero de 2012 * ; Archivo: teclado.asm * ; Descripcin: Programa para decodificar el teclado matricial * ;*********************************************************************** LIST P=18F4550, F=INHX32 #include <P18F4550.INC> #include <LCD.INC> ;****************************************************************************** ;Bits de configuracin CONFIG PLLDIV = 5 CONFIG CPUDIV = OSC1_PLL2 CONFIG USBDIV = 2 CONFIG FOSC = HSPLL_HS CONFIG FCMEN = OFF CONFIG IESO = OFF CONFIG PWRT = OFF CONFIG BOR = ON CONFIG BORV = 3 CONFIG VREGEN = ON config WDT = OFF config WDTPS = 32768 config MCLRE = ON config LPT1OSC = OFF config PBADEN = OFF config CCP2MX = ON config STVREN = ON config LVP = OFF config ICPRT = OFF config XINST = OFF config CP0 = OFF config CP1 = OFF config CP2 = OFF config CP3 = OFF config CPB = OFF config CPD = OFF config WRT0 = OFF config WRT1 = OFF config WRT2 = OFF config WRT3 = OFF config WRTB = OFF config WRTC = OFF config WRTD = OFF config EBTR0 = OFF config EBTR1 = OFF config EBTR2 = OFF config EBTR3 = OFF config EBTRB = OFF ;******************************************************************************

52

;****************************************************************************** ; Definicin de variables ; Variables definidas si se utiliza la interrupcin de baja prioridad UDATA WREG_TEMP RES STATUS_TEMP RES BSR_TEMP RES 1 1 1 ;variable en RAM para guardar contexto ;variable en RAM para guardar contexto ;variable en RAM para guardar contexto

UDATA_ACS DATO RTMUL RETARDO1 RETARDO2 CONTADOR1 PUERTO TECLA FILAS COLUMNAS ESTADO RES RES RES RES RES RES RES RES RES RES 1 1 1 1 1 1 1 1 1 1

RESET_VECTOR CODE 0x0000 goto main REMAPED_RESET_VECTOR CODE 0x1000 goto main REMAPED_HIGH_VECTOR CODE 0x1008 bra ISRH REMAPED_LOW_VECTOR CODE 0x1018 bra ISRL CODE 0x102A tabla_cadena1: mullw 02h movf PRODL, W addwf PCL, F retlw 'T' retlw 'E' retlw 'C' retlw 'L' retlw 'A' retlw ' ' retlw 'P' retlw 'R' retlw 'E' retlw 'S' retlw 'I' retlw 'O' retlw 'N' retlw 'A' retlw 'D' retlw 'A'

53

retlw H'00' ;Cero es el fin de cadena (Caracter nulo). tabla_teclas: mullw 02h movf PRODL, W addwf PCL, F retlw '7' retlw '8' retlw '9' retlw '/' retlw '4' retlw '5' retlw '6' retlw 'X' retlw '1' retlw '2' retlw '3' retlw '-' retlw 'C' retlw '0' retlw '=' retlw '+' ISRH: ; *** Interrupcin de alta prioridad btfss INTCON, RBIF goto finisrh ;ha entrado la interrupcin bcf INTCON, RBIF ;Limpiar la bandera de interrupcin clrf TECLA clrf FILAS clrf COLUMNAS movlw H'04' movwf CONTADOR1 movlw b'11111110' ;Nmero para comprobar la primer columna movwf ESTADO ;Registro para comprobar columnas leepuerto movf ESTADO, W movwf PORTB movff PORTB, PUERTO swapf PUERTO, F ;Cambiamos los nibles movlw H'F0' iorwf PUERTO, F ;Solo nos interesa el nible bajo, pero todo es lgica ;negativa se usa Inclusive OR comf PUERTO, F ;Realizamos el complemento para usar lgica positiva. ;Iniciamos el test tstfsz PUERTO goto nocero ;Hay tecla apretada rlncf ESTADO, F ;Nos pasamos a la siguiente columna decfsz CONTADOR1 goto leepuerto ;el contador es mayor a cero (VERDAD) clrf PORTB goto finisrh ;Ya no hay ms que leer (FIN) nocero movf CONTADOR1, W sublw H'04' ; Contador es el inverso de las columnas, le restamos 4 ;y nos queda COLUMNAS -1 movwf COLUMNAS ; Tenemos COLUMNAS - 1 btfss PUERTO, 0 ;Comprueba si fue la fila 1

54

goto comp1 movlw H'00' movwf FILAS ;Fila 1 - 1 (0) goto muestra comp1 btfss PUERTO, 1 ;Comprueba si fue la fila 2 goto comp2 movlw H'01' ;Fila 2 - 1 (1) movwf FILAS goto muestra btfss PUERTO, 2 ;Comprueba si fue la fila 3 goto comp3 movlw H'02' movwf FILAS ;Fila 3 - 1 (2) goto muestra

comp2

comp3

btfss PUERTO, 3 ;Comprueba si fue la fila 4 goto finisrh movlw H'03' movwf FILAS ;Fila 4 - 1 (3) muestra movlw H'04' mulwf COLUMNAS ;(Columnas -1) * 4 movf PRODL, W addwf FILAS, W ;(Columnas -1) * 4 + (Filas -1) movwf TECLA movlw DDRAM_L2 addlw H'08' movwf DATO call Comando_LCD movf TECLA, W call tabla_teclas ;Decodificar la tecla movwf DATO ;Mostrar la tecla decodificada call Dato_LCD clrf PORTB finisrh retfie FAST ISRL: movff STATUS,STATUS_TEMP movff WREG,WREG_TEMP movff BSR,BSR_TEMP ; ;guarda el registro de estado ;guarda el registro de trabajo ;guarda el registro BSR

*** Interrupcin de baja prioridad *** movff BSR_TEMP,BSR movff WREG_TEMP,WREG movff STATUS_TEMP,STATUS retfie ;restaura el registro BSR ;restaura el registro de trabajo ;restaura el registro de estado

Delay1K: retardo0 DECFSZ RTMUL goto retardo1 goto finretardo

55

retardo1 MOVLW .100 MOVWF RETARDO1 ciclo1 DECFSZ RETARDO1 GOTO retardo2 GOTO retardo0 retardo2 MOVLW .10 MOVWF RETARDO2 ciclo2 DECFSZ RETARDO2 GOTO ciclo2 GOTO ciclo1 finretardo RETURN Comando_LCD: SWAPF DATO, W MOVWF PORTD BCF PORTD, RD5 BCF PORTD, RD4 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 MOVFF DATO, PORTD BCF PORTD, RD5 BCF PORTD, RD4 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 RETURN Dato_LCD: SWAPF DATO, W MOVWF PORTD BCF PORTD, RD5 BSF PORTD, RD4 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 MOVFF DATO, PORTD BCF PORTD, RD5 BSF PORTD, RD4 BSF PORTD, RD6 MOVLW .60 MOVWF RTMUL CALL Delay1K BCF PORTD, RD6 RETURN

56

Inicializa_LCD: MOVLW .137 MOVWF RTMUL CALL Delay1K MOVLW 0x02 MOVWF PORTD BCF PORTD, RD5 BSF PORTD, RD6 MOVLW .60 CALL Delay1K BCF PORTD, RD6 MOVLW .187 MOVWF RTMUL CALL Delay1K MOVLW FUNCTION_SET IORLW LINES_5x7 MOVWF DATO CALL Comando_LCD MOVLW DISPLAY_CONTROL IORLW DON MOVWF DATO CALL Comando_LCD MOVLW CLEAR MOVWF DATO CALL Comando_LCD MOVLW DISPLAY_MODE IORLW INCREMENT MOVWF DATO CALL Comando_LCD RETURN Cadena_LCD: ;Subrutina para enviar una cadena al LCD. clrf CONTADOR1 ciclocadena movf CONTADOR1, W ;Colocamos el contenido de contador en W call tabla_cadena1 ;Llamamos a la tabla movwf DATO ;Colocamos el retorno en DATO tstfsz DATO ;Comprueba que no haya caracter nulo goto enviacadena goto fincadena enviacadena call Dato_LCD ;Enviamos el dato al LCD incf CONTADOR1 ;Incrementamos el contador goto ciclocadena fincadena return Configura_Puertos: ;Subrutina para configurar los puertos movlw H'0F' movwf ADCON1 movlw H'F0' ;mitad del puerto de salida, la otra mitad de entrada (para las ;interrupciones) movwf TRISB clrf TRISD clrf PORTD return Configura_Interrupciones: ;Subrutina para configurar interrupciones ;Interrupcin de cambio de flanco bcf INTCON, RBIF ;Limpiamos la bandera.

57

main:

bsf INTCON2, RBIP ;Le asignamos prioridad alta. bsf INTCON, RBIE ;Habilitamos la interrupcin. return clrf WREG call Configura_Puertos call Configura_Interrupciones call Inicializa_LCD movlw DDRAM_L1 movwf DATO call Comando_LCD call Cadena_LCD ;Ressitencias de PULL-UP bcf INTCON2, RBPU ;Habilitamos las resistencias de pull up. ;Interrupciones globales bsf RCON, IPEN ;Habilitamos prioridades en interrupciones. bsf INTCON, GIEH ;Habilitamos la interrupciones de alta prioridad.

ciclo

goto ciclo END

La tabla de teclas es para el teclado mostrado en la figura anterior, hay teclados co merciales diferentes con diferentes teclas como ya se mencion anteriormente; hay que cambiar el orden de las teclas para esos teclados. Posiblemente se te haga difcil de entender este programa por su lgica, pero est comprobado, lo arm fsicamente y lo simul en el programa Proteus 7 (Software de simulacin), con un PIC18F4620 parecido al PIC18F4550. Muestro la imagen siguiente de la simu lacin.

58

As como est el programa, no funciona en el software Proteus 7, necesitas cambiar las direcciones de interrupcin como si no tuviera bootloader. Cambiando eso, funciona perfectamente.

Temporizadores y contadores
El PIC18F4550 tiene 4 temporizadores (TIMER) con funciones diferentes pero muy parecidas entre si. Podemos utilizar el Timer como contador de eventos externos, lo explicar ms adelante, ya que explicar su registro de configuracin. En este manual solo explicar dos Timer (Timer 0 y Timer 1), explicar su funcionamiento, y explicar como hacer un segundero, un contador de eventos externos y un generador de frecuencias. Qu se puede hacer con un Timer? Generador de frecuencia. Modulador de ancho de pulso (PWM). Segundero. Reloj con fecha a partir del segundero. Medidor de frecuencia. Medidor de capacitancia a partir del medidor de frecuencia. Medidor de resistencia a partir del medidor de frecuencia. Medidor de inductancias a partir del medidor de frecuencia. Control de motores de CD a partir de PWM. Control de servomotores a partir de PWM. Muestreadores de datos a partir de ADC (ADC lo explicar mas adelante). Reloj de pulsos. Dimmer Digital (Controlador de intensidad de luz de focos de CA). Comunicacin serial a partir del reloj de pulsos.

Por motivos de espacio y de tiempo no dar lo que es comunicacin serial en este manual (USART, USB y otros ms).

Registro de configuracin
Explicar muy brevemente el registro de configuracin del TIMER 0 llamado T0CON. Este registro controla el funcionamiento del Timer para usarse como temporizador o como contador, configura su prescaler y el nmero de bits a usar. El registro T0CON (para el timer 0) tiene los siguientes elementos: 59

bit 7 TMR0ON: Enciende o apaga el Timer. bit 6 T08BIT: En 1 configura el timer a 8 bits, en cero, lo configura a 16 bits. bit 5 T0CS: En uno, selecciona al pin RA4 como entrada de eventos, en cero, selecciona al oscilador principal para el retardo. bit 4 T0SE: Solo se usa para entrada de eventos de RA4, en uno, selecciona flanco de bajada, en cero, selecciona flancos de subida. bit 3 PSA: En 1 no asignamos prescaler, en cero, asignamos prescaler. bits 2 a 0 TOPS: Selector de prescaler en caso de que PSA sea cero. 111 = 1:256 110 = 1:128 Prescale value 101 = 1:64 Prescale value 100 = 1:32 Prescale value 011 = 1:16 Prescale value 010 = 1:8 Prescale value 001 = 1:4 Prescale value 000 = 1:2 Prescale value

Timers
Qu es un Timer? Es un contador de ciclos de mquina o contador de ciclos de un oscilador externo, que al desbordarse produce una interrupcin. Tambin puede contar pulsos externos. Cmo funciona un Timer? Cuenta nmeros del 0 al 255 cuando se configura en 8 bits (lo explico ms adelante) o al 65536 en caso de configurarlo de 16 bits. Puede contar ciclos de mquina (en caso de usar el oscilador principal) o contar eventos externos (usando osciladores externos o pulsos de algn circuito externo como el famosisimo NE555, flip-flops, o simplemente botones PUSH) en un pin especfico del cada timer. Cuando el timer llega a su cuenta mxima ms uno (se desborda) activa una interrupcin. Dicha interrupcin, se puede utilizar como interrupcin de alta prioridad o de baja prioridad (Ver tema configurar interrupciones). Cmo usar un Timer? Antes de comenzar, vamos a definir un trmino que se llama prescaler, que es una divisin de frecuencia. Ejemplo, si tengo una frecuencia principal de 20MHz y un prescaler de 1, tengo la misma frecuencia final de 20MHz, si tengo el prescaler de 2, la frecuencia es de 10MHz, si tengo un prescaler de 4 tengo una frecuencia de 5MHz. Como se observa, el prescaler provoca que mis tiempos sean ms largos y pueda alcanzar una cierta frecuencia ms fcilmente. Para utilizar el timer vamos a recurrir nuevamente al nmero mgico # usado en retardos, pero con una pequea variante, que es la multiplicacin por el prescaler y la posibilidad de usar 16 bits.

60

4presc( 2n #) t= Fosc tFosc n #=2 ( ) 4presc t48 MHz #=2n( ) 4presc Donde: n es el nmero de bits, pueden ser 8 o 16. t es el tiempo del timer. Focs es la frecuencia del oscilador, en caso de bootloader es de 48MHz. Presc es el prescaler utilizado, este valor se puede proponer de 1 a 128. Ejemplo 1: Realizar el clculo del nmero mgico para obtener un retardo de aproximadamente 1.25ms con 8 bits. Proponer el prescaler. Solucin 1: Despus de varios intentos, obtuve un prescaler de 64 para un buen nmero mgico no muy grande, pero tampoco muy pequeo. 1.25ms48MHz ) 464 60000 #=256( ) 256 #=256243.37 #=21.62 #22 Este nmero ser colocado en el registros TMR0L y colocar cero en TMR0H. En caso de ser un nmero de 16 bits, se debe de convertir en hexadecimal y el nibble alto deber de colocarse en TMR0H y el nibble bajo deber de colocarse en TMR0L. #=28( Cmo configuro el timer? Segn el registro de configuracin T0CON deberemos de colocar los siguientes valores: Encender el timer. Configurarlo a 8 bits (para el ejemplo de 1.25ms). Seleccionar el oscilador principal. No importan los flancos. Colocar cero. Asignar prescaler. El prescaler es de 64.

El nmero que se debe de colocar en binario sera B'11000101' en hexadecimal nos quedara 0xC5. 61

Ejemplo 2: Realizar el programa de configuracin del Timer 0 a 8 bits para 1.25ms y realizar su interrupcin de alta prioridad para cambiar el estado de RC0 en este tiempo. Solucin 2: Configurar el programa con los nmeros obtenidos anteriormente y configurar la interrupcin del TIMER0. En la subrutina ISRH colocar la instruccin BTG para cambiar el estado de RC0.
ISRH:

btfsc INTCON, TMR0IF ;compruebo que se realiz la interrupcin. goto finisrh bcf INTCON, TMR0IF ;Limpio la bandera. btg PORTC, RC0 ;Cambio el estado del pin RC0. clrf TMR0H call Configura_Timer ;Configuro el timer nuevamente. finisrh retfie FAST Configura_Puertos: movlw H'0F' movwf ADCON1 ;Todos los puertos como digitales. clrf TRISC ;Puerto C como salida. clrf PORTC ;Apagamos el puerto C. return Configura_Interrupciones: bcf INTCON, TMR0IF ;Limpio la bandera. bsf INTCON2, TMR0IP ;Interrupcin de alta prioridad. bsf INTCON, TMR0IE ;Habilito la interrupcin. return Configura_Timer: clrf TMR0H movlw .22 movwf TMR0L movlw H'C5' movwf T0CON return main: clrf WREG call Configura_Puertos call Configura_Interrupciones call Configura_Timer bsf RCON, IPEN bsf INTCON, GIEH ciclo goto ciclo END

Como observamos en la rutina de interrupcin, volvemos a configurar el Timer ya que, como mencion anteriormente la interrupcin se realiza cuando el contador vuelve a ce ro y debemos volver a cargar el nmero para que cuente nuevamente el ciclo de 1.25ms. Nota: El Timer 1 tiene una configuracin muy parecida al TIMER 0, con la diferencia que el Timer 2 puede contener un oscilador externo en RC0 y RC1 para un conteo de eventos. Si colocamos un oscilador de baja frecuencia, podemos realizar un segundero. Recomiendo usar el de 32KHz (32768 Hz) y cargar en TMR1H 0x80 y TMR0L 0x00. Este programa lo explicar en la seccin segundero. 62

Contadores
Los contadores de eventos son Timers que en vez de contar ciclos de oscilador, cuentan pulsos externos. Si contamos el nmero de pulsos en un segundo, tenemos un frecuenciometro; por el contrario, si queremos que a cierto nmero de cuentas se realice una interrupcin, debemos de colocar un nmero en TMR0L para alcanzar dicha cuenta. En este caso, como no usamos oscilador interno, no dividimos la frecuencia en 4. Para configurar el contador en el registro T0CON debemos de considerar lo siguiente: Encender el Timer Configurarlo a 8 o 16 bits. Seleccionar eventos externos. Seleccionar el flanco del pulso. No asignar prescaler para tiempo real. El prescaler es irrelevante por que no ha sido asignado.

Por lgica digital todos los valores irrelevantes los consideramos cero. El valor obtenido con flancos de subida es 0xF8. Ejemplo 1: Realizar un programa con TIMER0 que interrumpa al microcontrolador cuando sea apretado 5 veces un botn en RA4. La interrupcin deber ser de alta prioridad y el flanco deber de ser de subida y al realizarse deber de cambiar de estado RC0 de forma repetitiva. Tomar en cuenta que RA4 no tiene resistencias de PULL-UP ni PULL-DOWN. Solucin 1: El nmero mgico deber ser 251 para que cuando lleguemos a 255+1 se interrumpa el microcontrolador. El circuito externo deber ser un push conectado a +5V con una resistencia de 1K a tierra. El nodo de la resistencia y botn, deber ser llevado a RA4.
ISRH: btfss INTCON, TMR0IF goto finisrh bcf INTCON, TMR0IF ;Limpiamos la bandera btg PORTC, RC0 ;Cambiar el estado. call Configura_Timer finisrh retfie FAST Configura_Puertos: movlw H'0F' movwf ADCON1 clrf TRISC ;Puerto C como salida clrf PORTC setf TRISA ;Puerto A como entrada return Configura_Interrupciones: bcf INTCON, TMR0IF ;Limpio la bandera. bsf INTCON2, TMR0IP ;Interrupcin de alta prioridad.

63

bsf INTCON, TMR0IE ;Habilito la interrupcin. return Configura_Timer: clrf TMR0H movlw H'05' movwf TMR0L movlw H'F8' movwf T0CON return main: clrf WREG call Configura_Puertos call Configura_Interrupciones call Configura_Timer bsf RCON, IPEN bsf INTCON, GIEH ciclo goto ciclo

Como observamos es realmente similar a un temporizador, pero cambiando solo el nmero de T0CON. Como explique anteriormente podemos desactivar la interrupcin y contar el nmero de pulsos en 1 seg. Leemos el registro TMR0L y/o TMR0H y con eso conseguimos realizar un frecuenciometro.

El Convertidor Analgico Digital


El convertidor analgico digital (Analogic to Digital Converter ADC) es un mdulo embebido en el microcontrolador y su funcin es realizar la cuantificacin de niveles de voltaje en periodos de tiempo discretos (muestreo). Para los que no saben lo que hablo y como no dar clases de comunicaciones digitales o procesamiento digital de seales, lo explicar con las palabras ms concretas que se puedan: Cambia un valor de voltaje analgico en un valor digital en un pequeo instante. Para utilizar el convertidor analgico-digital (ADC) es necesario configurar tres registros: ADCON0, ADCON1 (ya usado anteriormente) y ADCON2. El ms difcil de configurar y de entender es ADCON2, pues este registro configura tiempos de retardo para carga del capacitor de medicin, tiempos de conversin y tiempos de digitalizacin; adems de esto, tam bin configura la justificacin del resultado. ADCON1 configura los puertos analgicos o digitales a usar como ya lo habamos realizado anteriormente, as como fuentes de referencia en caso de usarlas. El registro ADCON0 configura el canal con el que se va a medir y pone en marcha la conversin. El resultado de la conversin puede ser justificado a la izquierda o derecha para obtener un resultado en 8 o 10 bits respectivamente en los registros ADRESH y ADRESL. Justificacin a la derecha me da un resultado de 10 bits. ADRESH -> 0B00000011 ADRESL -> 0B11111111

64

Los bits de mayor peso digital estn en ADRESH y los dems estn en ADRESL. Para la justificacin a la izquierda tenemos lo siguiente: ADRESH -> 0B11111111 ADRESL -> 0B11000000 Los bits de mayor peso tambin estn en ADRESH, y en ADRESL solo tenemos 3 bits que pueden ser descartados por tener menor peso digital, equivalentes a milivolts que podemos despreciar. En este caso solo haremos caso de ADRESH, que es un registro de 8 bits, por ende, tenemos el resultado de 8 bits. Ahora explicare cada uno de los tres registros, comenzando por ADCON2, que es el ms difcil y terminando con ADCON0. El registro ADCON2 puede solo tener un valor siempre, y no se cambiar. Este valor lo calcul con las frmulas y valores que propone el manual del microcontrolador PIC18F4550 y siempre ser el mismo, pero a pesar de esto, explicar el registro con sus bits. bit 7 ADFM: 1 Justificado a la derecha, 0 Justidicado a la izquierda. bit 6 No se usa. bit 5-4 ACQT: Tiempos de adquisicin del dato. Para obtenerlo se usa la frmula M*TAD=2.4ms donde M es el valor de ACQT y TAD es n veces Tosc (n se ver en el siguiente apartado). 111 = 20 TAD 110 = 16 TAD 101 = 12 TAD 100 = 8 TAD 011 = 6 TAD 010 = 4 TAD 001 = 2 TAD 000 = 0 TAD bit 2-0 ADCS Tiempos de carga del ADC. Para obtenerlo se usa la frmula n*Tosc >= 700ns, donde n es el ADCS y Tosc es el inverso de la frecuencia del oscilador (48MHz para bootloader). 111 = FRC (clock derived from A/D RC oscillator) 110 = FOSC/64 101 = FOSC/16 100 = FOSC/4 011 = FRC (clock derived from A/D RC oscillator) 010 = FOSC/32 001 = FOSC/8 65

000 = FOSC/2 El valor a colocar en este registro cuando usamos bootloader es de 0x0E. Sin bootloader este valor es de 0x15. Recordemos que los valores de la frecuencia cambian con el bootloader, por eso, el valor de ADCON2 difiere. El registro ADCON1 se utiliza para configurar las fuentes de referencia, pines analgicos y pines digitales. bit 7-6 No se usan bit 5 VCFG1: Voltaje de referencia negativo, cuando es uno se usa VREF- (AN2), cuando es cero se usa VSS (GND). bit 4 VCFG0: Voltaje de referencia psotivo, cuando es uno se usa VREF+ (AN3), cuando es cero se usa VDD (+5V) bit 3-0 PCFG: Seleccin de canales. (Ver tabla de manual, donde D es pin digital y A es pin analgico). Por motivos de aprendizaje colocar la tabla que viene en el manual. PCF AN12 AN11 AN10 AN9 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 A A A D D D D D D D D D D D D D A A A A D D D D D D D D D D D D A A A A A D D D D D D D D D D D A A A A A A D D D D D D D D D D AN8 A A A A A A A D D D D D D D D D AN7 A A A A A A A A D D D D D D D D AN6 A A A A A A A A A D D D D D D D AN5 A A A A A A A A A A D D D D D D AN4 A A A A A A A A A A A D D D D D AN3 A A A A A A A A A A A A D D D D AN2 A A A A A A A A A A A A A D D D AN1 A A A A A A A A A A A A A A D D AN0 A A A A A A A A A A A A A A A D

Como podemos apreciar en la tabla, si no utilizamos voltajes de referencia y seleccionamos todos los pines digitales, obtenemos el nmero 0x0F, que es el valor por defecto 66

que hasta este momento se utiliz en el registro ADCON1. Ahora, dependiendo de nuestras necesidades, colocaremos el valor respectivo en este registro para seleccionar pines analgicos. El registro ADCON0 se usa para seleccionar el canal a medir, ya que solo podemos medir un canal en un instante de tiempo. Tambin se utiliza para encender el mdulo ADC y para iniciar una conversin. bit 7-6 no se usan. bit 5-2 Seleccin del canal a medir. 0000 = Channel 0 (AN0) 0001 = Channel 1 (AN1) 0010 = Channel 2 (AN2) 0011 = Channel 3 (AN3) 0100 = Channel 4 (AN4) 0101 = Channel 5 (AN5)(1,2) 0110 = Channel 6 (AN6)(1,2) 0111 = Channel 7 (AN7)(1,2) 1000 = Channel 8 (AN8) 1001 = Channel 9 (AN9) 1010 = Channel 10 (AN10) 1011 = Channel 11 (AN11) 1100 = Channel 12 (AN12) 1101 = Unimplemented(2) 1110 = Unimplemented(2) 1111 = Unimplemented(2) bit 1 GO/(!DONE): Estado de la conversin. bit 0 ADCON: Encendido o apagado del ADC. El mdulo ADC al igual que todos los mdulos del PIC18F4550 tiene su interrupcin y se configura como se explic en el captulo interrupciones. Ahora que explique algo acerca de los registros de configuracin del ADC y sus registros de resultado, veamos un pequeo ejemplo. Ejemplo 1: Realizar un programa que codifique el valor obtenido en AN0, sin fuentes de referencia, justificado a la izquierda con resultado de 8 bits. Si el valor obtenido es menor a 1.5v conmutar RC0 a 50ms, si es mayor a 1.5v y menor a 3v, conmutar RC0 a 200ms y si es mayor a 3 volts, conmutar RC0 a 500ms. Utilizar Timer0 para realizar el retardo. Las inte rrupciones sern de alta prioridad. 67

Solucin 1: Configurar ADC como se mencion anteriormente, configurar las interrupciones como se mencion en su captulo respectivo y conectar adecuadamente un potencimetro en el pin RA0 (AN0). Recomendacin 1: Por electrnica lineal, utilizaremos un amplificador en modo seguidor para evitar que el voltaje se modifique por la resistencia de entrada del PIC.

Recomendacin 2: Utilizar el Timer0 a 16 bits. Primero, calculamos el nmero mgico de los tiempos proponiendo el prescaler de 64. 500ms: #= 2^16 - (500ms * 48MHz) / (4 * 64) #=18661 #=0x48E5 200ms: #=2^16 - (200ms * 48MHz) / (4 * 64) #=28036 #=0x6D84 50ms: #=2^16 - (50ms * 48MHz) / (4 * 64) #=56161 68

#=0xDB61 Segundo, calculamos los valores de voltaje: para 1.5 v: resolucin=5v/255 (8bits) res=0.196 n=1.5/res n=76.5 aprox 77 para 3v n=3/res n=153 Ahora con estos valores programamos el cdigo.
;Memoria necesaria para guardar el resultado de la medicin UDATA_ACS VALORADC RES 1 ;*** Saltamos esta parte de la plantilla ISRH: btfsc INTCON, TMR0IF ;Revisamos si se interrumpi por timer. goto revisaadc bcf INTCON, TMR0IF ;Limpiamos la bandera. btg PORTC, RC0 ;Conmutamos el pin RC0. ;Configuramos nuevamente el timer comparando el valor del ADC. movlw .77 ;77 el primer valor calculado en resolucin. cpfslt VALORADC ;Comparamos el .77 con VALORADC. goto volts3 ;Cargamos 0xDB61 al TIMER0 movlw H'DB' movwf TMR0H movlw H'61' movwf TMR0L movlw H'85' movwf T0CON ;Configuramos el TIMER0 a 16 bits y prescaler 64. goto revisaadc ;revisamos si se realiz una conversin. volts3 movlw .153 cpfslt VALORADC ;Comparamos 153 con VALORADC. goto volts5 ;Cargamos 0x6D84 al TIMER0 movlw H'6D' movwf TMR0H movlw H'84' movwf TMR0L movlw H'85'

69

movwf T0CON goto revisaadc votls5 ;Ya no hay comprobacin. ;Cargamos 0x48E5 al TIMER0 movlw H'48' movwf TMR0H movlw H'E5' movwf TMR0L movlw H'85' movwf T0CON revisaadc btfsc PIR1, ADIF ;Revisar si se realiz la interrupcin del ADC. goto finisrh bcf PIR1, ADIF ;Limpiamos la bandera. movff ADRESH, VALORADC ;Movemos el valor de ADRESH a VALORADC bsf ADCON0, GO ;Iniciamos una nueva conversin. finisrh retfie FAST Configura_Puertos: ;No configuraremos ADCON1 en esta parte. clrf TRISC ;Solo utilizaremos PORTC de forma digital. clrf PORTC return Configura_Interrupciones: ;Interrupciones del ADC bcf PIR1, ADIF bsf PIE1, ADIE bsf IPR1, ADIP ;Interrupciones del Timer bcf INTCON, TMR0IF bsf INTCON, TMR0IE bsf INTCON2, TMR0IP return Configura_ADC: movlw H'0E' movwf ADCON2 ;Movemos 0x0E a ADCON2 movwf ADCON1 ;Movemos 0x0E a ADCON1 movlw H'01' movwf ADCON0 ;ADC encendido pero sin realizar conversin return Configura_Timer: ;El valor inicial del timer ser 50ms. movlw H'DB' movwf TMR0H movlw H'61' movwf TMR0L movlw H'85' movwf T0CON return main: clrf WREG clrf VALORADC call Configura_Puertos call Configura_Interrupciones call Configura_ADC

70

call Configura_Timer bsf RCON, IPEN ;Interrupciones globales. bsf INTCON, GIEH ;Prioridades globales. ciclo bsf ADCON0, GO ;Iniciamos la conversin. goto ciclo END

Con este ejemplo podemos verificar que se pueden utilizar varias funciones de los mdulos del PIC18F4550 para realizar un objetivo comn. Estos ejemplos son cosas bsicas que se pueden realizar con el PIC18F4550, hay cosas ms complicadas, elaboradas y divertidas que se pueden realizar con este microcontrolador que con un poco de lgica digital y algunos conocimientos de electrnica se pueden realizar.

71

ALGUNAS COSAS EXTRAS


En este captulo ltimo, mencionar algunas cosas extras que debes saber para realizar proyectos y/o prcticas que te puedan servir en el desarrollo personal del lector. Como mencion anteriormente, solo es cuestin de tener un poco de imaginacin, conocimientos bsicos de lgica digital y algo de electrnica. Tambin lo que el lector debe de realizar es el estudio de las partes recomendadas del Manual Tcnico del PIC18F4550 que se puede obtener de la pgina de Microchip, ya que hay algunas cosas que no se mencionan en este documento que seran esenciales que el lector tuviera en cuenta.

Conversin de Nmeros
En este apartado ensear como obtener los nmeros de Unidad, Decena y Centena de un registro de 8 bits. Esto te servir para poder convertir cada uno en BCD o en ASCII, para un display de 7 segmentos o para el LCD alfanumrico. Una vez obtenidos estos nmeros, debers realizar la tabla correspondiente para BCD o ASCII como te lo mostr en el captulo tablas y tendrs el nmero convertido. Cdigo para obtener Unidad, Decena y Centena. Para este cdigo utilizar cuatro registros: El registro de 8 bits y tres registros para guardar unidad, decena y centena. Tambin utilizar el cdigo de divisin y mdulo.
UDATA_ACS REGISTRO RES 1 UNIDAD RES 1 DECENA RES 1 CENTENA RES 1 ;Aqu van los registros de la divisin y el mdulo ;Nos saltamos esta parte de la plantilla ;Aqu van las funciones de Divisin y mdulo. Obtener_UDC: movff REGISTRO, DIVIDENDO movlw .10 movwf DIVISOR call Modulo ;Hacemos un mdulo 10 a REGISTRO movwf UNIDAD movff REGISTRO, DIVIDENDO movlw .10 movwf DIVISOR call Divisin movwf REGISTRO ;guardamos el resultado nuevamente en registro movff REGISTRO, DIVIDENDO movlw .10 movwf DIVISOR call Modulo ;Hacemos un mdulo 10 a REGISTRO

72

movwf DECENA movff REGISTRO, DIVIDENDO movlw .10 movwf DIVISOR call Divisin movwf REGISTRO ;guardamos el resultado nuevamente en registro movff REGISTRO, DIVIDENDO movlw .10 movwf DIVISOR call Modulo ;Hacemos un mdulo 10 a REGISTRO movwf CENTENA return

Bueno, solo me queda decir que es un algoritmo que solo necesita de divisiones y mdulos, bastante fcil de obtener estos valores. Ahora, ya podemos realizar algunas aplicaciones que tengan que mostrar nmeros en un display de 7 segmentos o en el LCD alfanumrico.

Segundero
Ahora explicar como realizar un segundero con el TIMER1 del PIC18F4550. El registro T1CON se configura exactamente igual que T0CON como ya mencion anteriormente en el captulo Timers, con la excepcin de la entrada de eventos que es en los pines RC0 y RC1. En estos pines colocaremos un oscilador de 32768 Hz que normalmente lo conoceremos como oscilador de 32KHz. Porqu usar un oscilador de baja frecuencia? Recordemos que tenemos un contador con cuenta mxima de 65535 cuentas, recordemos que la frecuencia es el nmero de cambios que se realizan en 1 segundo. Si tenemos una frecuencia menor a 65535, pode mos obtener un nmero mgico para que se desborde en exactamente 1 segundo; nuestro caso es un oscilador de 35768 Hz entonces necesitaremos colocar ese nmero en el conta dor y su desborde ser de exactamente 1 segundo. Este nmero en hexadecimal es 0x8000. Cmo conectar el oscilador? Se conecta el oscilador a los pines RC0 y RC1 junto con un capacitor de 15nF o 22nF a tierra para evitar ruido en la seal.

73

Cmo configurar el Timer 1 para realizar el segundero? Se configuran las interrupciones como se explic en Configurar Interrupciones y el registro TMR1H se carga 0x80 y TMR1L se carga con 0x00, por ltimo, se coloca el nmero 0x8F en el registro T1CON. La interrupcin se realizar cada segundo. Una vez realizado el cdigo del segundero, podra el lector realizar un reloj digital ya sea con un display de 7 segmentos o con el LCD alfanumrico.

74

FIN DEL CURSO


Este curso bsico ha terminado. Como ltimas recomendaciones puedo decir que uses una fuente externa ya que el lector podr causar fallo en los puertos USB de la computadora. Ahora solo me queda decir:

Felicidades, has terminado este curso bsico de programacin en ensamblador del PIC18F4550 con bootloader.
Ahora no me queda mas que agradecerles el leer este documento. xito. Yo se que es un curso bsico, pero con un poquito de imaginacin puedes realizar cosas grandiosas con este microcontrolador de la familia PIC18. Hay muchas cosas por aprender, por conocer y por programar, pero si tu no las haces, nunca sern verdaderas y solo se quedarn en la imaginacin.

75

You might also like