Curso Micros

CURSO_MICROS Módulo 1 Índice Capítulo 1: Los microcontroladores      ¿Qué son los micros y para qué sirven? Clas

Views 93 Downloads 0 File size 3MB

Report DMCA / Copyright

DOWNLOAD FILE

Recommend stories

Citation preview

CURSO_MICROS

Módulo 1 Índice Capítulo 1: Los microcontroladores  

  

¿Qué son los micros y para qué sirven? Clasificación de los microcontroladores o Según la longitud del bus de datos o Según sus recursos o Según el set de instrucciones o Según su arquitectura interna o Según el fabricante Por qué empezar con los PICs Características de los PICs Clasificación de los PICs

Capítulo 3: Arquitectura de los PIC16F    



 



Introducción Características de los PIC16F84A y PIC16F87xA Diagrama de bloques del PIC16FXXX La memoria de programa o El Contador de Programa o La Pila o STACK La memoria RAM o Registros SFR o Registros GPR Diferencias entre los PIC16F87xA Fuses de Configuración o Selección del oscilador o El Watchdog o Power Up Timer o Protección de Código o Escribir memoria FLASH o Modo ICD o Protección de EEPROM o Programación LPV o Brown Out Reset El registro STATUS

Capítulo 4: Los Puertos de los PIC 

  

Descripción de los puertos o El puerto B o El puerto A o El puerto C o El puerto D o El puerto E Configuración de puertos Resistencias de Pull-up Práctica 4-1 o Ensamblado del programa

Página |1

CURSO_MICROS  

Página |2

Práctica 4-2 Práctica 4-3

Capítulo 7: Proteus VSM      



   

¿Qué es Proteus VSM? ISIS Proteus Dibujando el circuito Edición de objetos Simulación del diseño Depuración del programa o Ventanas de depuración o Ventana Watch Window Instrumentos virtuales o COUNTER TIMER o OSCILLOSCOPE Gráficos de simulación Depuración con *.sdi Propiedades avanzadas Tutorial de Proteus: Resumen del capítulo

1 - Los microcontroladores Los PICs Por qué empezar con los PICs  

 



Por su fácil adquisición. Se pueden conseguir en casi cualquier tienda de electrónica. Por su pequeño set de instrucciones, que no logra ser igualado por ningún otro microcontrolador. Es casi mágica la forma cómo se pueden implementar fácilmente casi cualquier algoritmo de programa con solo sus 35 instrucciones básicas. Por su bajo costo. Los PICs son tal vez los microcontroladores más baratos con las características que poseen. Por su fácil aprendizaje. Los PICs cuentan con el menor conjunto de instrucciones, y no por ello menos eficientes, que los convierten de lejos en los de mejor aprendizaje. Por la disponibilidad de herramientas. Las herramientas de hardware y software son de amplio alcance. Eso nos permitirá empezar muy pronto con la experimentación sin la preocupación por mayores recursos.

Características de los PICs Algunas de las características y recursos generales y comunes a casi todos los PICs son: 

Están fabricados con tecnología CMOS. Aunque los dispositivos CMOS son más lentos que los TTL, son ideales para los microcontroladores porque requieren de menor consumo de energía. Es posible implementar sistemas que solo se alimenten de baterías corrientes. La tecnología CMOS, como sabemos, también

CURSO_MICROS

     

Página |3

significa que los transistores, al ser mucho menos, ocupan mucho menor espacio en el chip. Memorias de programa (FLASH, OTP o ROM), memoria de datos estática (SRAM) y memoria EEPROM internas. Puertos de E/S bidireccionales configurables independientemente pin por pin. Suministro de alta corriente en los puertos de E/S. Timer‘s. Temporizadores de alta precisión o contadores de pulsos externos. WatchDog. Monitoriza que el PIC funcione adecuadamente a lo que se esperaba y no se cuelgue. ICSP (In Circuit Serial Programming). Permite realizar la programación del PIC utilizando una interface serial con muy pocos pines. Bits de Configuración. A veces llamados fuses, permiten establecer un determinado modo de funcionamiento del PIC, como el tipo de oscilador que utilizará o si el código grabado podrá o no ser leído después de la programación.

Otros recursos, más avanzados, son específicos a cada familia de PICs y pueden ser:     

 

 

Módulos PWM. Generadores de ondas PWM (Pulse Width Modulation). Son particulamente útiles para controlar la velocidad de los motores DC. Convesores Análogico-Digital, ADC. Para recibir señales del mundo analógico. Puerto Serial Síncrono, MSSP. Para la comunicación con dispositivos que utilizan los buses I2C o SPI. Puerto Paralelo Esclavo, SPP. Por ejemplo, para conectarse directamente con el puerto paralelo del PC. USART, Transmisor Receptor Síncrono Asíncrono Universal. Para comunicarse mediante los protocolos RS232 con cualquier dispositivo que también lo soporte. Por ejemplo, podemos conectar nuestro PIC al puerto serie del PC o a cuanquier otro microcontrolador con USART. Módulo Comparador Analógico. Nos puede ahorrar un OP-AMP y algo más. Módulo CAN. Para facilitarle al PIC su conexión con otros microcontroladores en una pequeña red LAN con un protocolo robusto para trabajar en codiciones extremas. Módulo USB. Casi todos los dispositivos digitales modernos presentan interface USB. Con esto podemos diseñar sistemas que no tengan nada que envidiarles. Etc., etc.

Clasificación de los PICs Considerando solo a los microcontroladores de 8 bits, Microchip establece una división en cuatro grandes familias: 



La familia Baseline. Conformada por los grupos PIC10, PIC12, algunos PIC16 y el PIC14000. Todos tienen instrucciones de 12 bits. La mayoría presenta un set de 33 instrucciones y opera a 1MIPS, en tanto que otros cuantos tienen 35 instrucciones y alcanzan los 5MIPS. Tienen muy poca memoria y en cuanto a recursos periféricos, son los menos dotados. La familia Mid-range. Es la familia más distintiva de los PICs. Engloba los PIC16 y algunos PIC12. Todos tienen 35 instrucciones de 14 bits y ninguno supera los 5MIPS. Sus memorias pueden alcanzar las 8092 palabras de 14 bits. En general, en ellos se pueden encontrar casi todos los recursos hadware buscados en un microcontrolador de 8 bits, por eso se suele tomar de aquí algunos modelos como punto de partida de aprendizaje.

CURSO_MICROS 



Página |4

La familia High-end. Compuesta por los PIC17, esta familia no llegó a tener gran difusión. La pronta aparición de los PIC18 ni siquiera le dejó tiempo a Microchip para pensar en los modelos con memoria flash. El hecho es que los medios hardware y software de desarrollo requeridos han sido relegados y, por tanto, no vale la pena preocuparse por ellos. La familia High-performance o Enhanced. Está formada por los PIC18. Para un mejor trabajo con los compiladores de alto nivel, su repertorio básico consta de 75 instrucciones, de 16 bits, y algunos modelos incluyen un pequeño conjunto de instrucciones extendidas. De todos modos, siempre se mantiene la compatibilidad con las 35 instrucciones de los PICs Mid-range. Todos alcanzan velocidades de operación de hasta 10 MIPS y los PIC18 con USB están optimizados para trabajar hasta a 12 MIPS. Están provistos de un modelo de memoria plano, con lo que se ahorran las tediosas operaciones de cambio de banco.

A la vez, puede haber varias decenas de PICs dentro de cada familia, pero las diferencias entre ellos son cada vez menores, como tener algunos pines de E/S más o menos, tener algo de memoria más o menos, tener un Timer más o menos, emplear otro tipo de memoria, y demás detalles de ese tipo

Arquitectura de los PIC16F84A y PIC16F87xA Introducción Aprender a programar microcontroladores significa aprender a usar todos sus recursos para luego aplicarlos en el diseño deseado. Es un proceso continuo, sistemático y que demanda algo de paciencia. En este capítulo empezaremos por conocer el hardware del PIC. Características del PIC16F84A y PIC16F87xA A continuación se citan las características más notables del PIC16F84A. Naturalmente, muchas de ellas no las comprenderás de plano. Puedes tomar eso como referencia para medir tu avance en el dominio del PICmicro. CPU RISC de Alta Performance:       

Solo 35 instrucciones que aprender Velocidad de operación de hasta 20 MHz (modelo PIC16F84A-20) 1024 palabras de memoria de programa (FLASH) 68 bytes de RAM de Datos estática 64 bytes de EEPROM de Datos Pila hardware de 8 niveles Cuatro fuentes de interrupción:

Características de los Periféricos:   

13 pines de E/S con control de dirección individual Suministro de hasta 25 mA de corriente por pin en los puertos TMR0: temporizador/contador de 8-bits con prescaler programable

CURSO_MICROS

Página |5

Características Especiales del Microcontrolador:       

Memoria de programa FLASH para 10 000 ciclos de borrado/escritura típicamente Memoria EEPROM para 10 000 000 de ciclos de borrado/escritura típicamente Programación Serial en el Circuito, ICSP Watchdog timer con su propio oscilador RC Capacidad de protección de código Modo SLEEP para ahorrar energía Opciones para seleccionar el oscilador

Tecnología FLASH/EEPROM CMOS mejorada:  

Amplio rango de voltaje de operación: 2.0 V a 5.5 V Máxima disipación de potencia: 800 mW

Y ahora las características de los PIC16F87xA: CPU RISC de Alta Performance:       

Solo 35 instrucciones que aprender Velocidad de operación de hasta 20 MHz (200 ns por instrucción básica) Hasta 8 K de palabras de 14 bits de memoria de programa (FLASH) Hasta 368 bytes de RAM de Datos estática Hasta 256 bytes de EEPROM de Datos Pila hardware de 8 niveles Hasta 15 fuentes de interrupción

Características de los Periféricos:          

Hasta 33 pines de E/S con control de dirección individual Suministro de hasta 25 mA de corriente por pin en los puertos Timer0: temporizador/contador de 8-bits con prescaler programable Timer1: temporizador/contador de 16-bits con prescaler programable Timer2: temporizador de 8-bits con prescaler y postcaler programables Dos módulos CCP, Capture, Compare, PWM. El PWM es de 10 bits MSSP: Puerto Serie Síncrono Maestro con operaciones en modos I2C y SPI. USART: Puerto serie Transmisor Receptor Síncrono Asíncrono Universal PSP: Puerto Paralelo Esclavo de 8 bits y con controles RD, WR y CS. BOR: Circuito de Detección de Bajo Voltaje

Características Especiales del Microcontrolador:      

Memoria de programa FLASH para 100 000 ciclos de borrado/escritura típicamente Memoria EEPROM para 1 000 000 de ciclos de borrado/escritura típicamente Watchdog timer Capacidad de protección de código Modo SLEEP para ahorrar energía Opciones para seleccionar el oscilador

CURSO_MICROS    

Página |6

Programación Serial en el Circuito, ICSP Autoprogramación por control software Programación en bajo voltaje (5V) Soporte ICD vía dos pines

Características analógicas:  

Conversor ADC de 10 bits de hasta 8 canales Módulo Comparador

Diagrama de pines del PIC16F84A y PIC16F877A/874A en encapsulado PDIP.

Diagrama de bloques del PIC16FXXX El siguiente diagrama muestra los principales elementos de un PIC y que tarde o temprano los tendrás que memorizar.

CURSO_MICROS

Página |7

Diagrama de bloques simplificado de los PIC16FXXX Ahora una somera descripción de lo que representan estos bloques. 

 

  



El CPU es el circuito encargado de leer, decodificar y ejecutar las instrucciones del programa. Su principal componenete a tener en cuenta es el ALU (Unidad Aritmético Lógica) que se encarga de las operaciones de suma, resta, AND lógica, OR lógica, etc. La Memoria de Programa contiene las instrucciones del programa del PIC. Es una memoria permanente pero que se puede reprogramar para cambiar de tarea. La Memoria de Datos aloja las variables temporales que procesa el CPU. Algunos registros de esta memoria (llamados SFR) pueden controlar los recursos periféricos, como el Timer0, la EEPROM, etc., e inclusive los puertos de E/S. El Contador de Programa es un registro que evoluciona para indicar cuál será la siguiente instrucción que debe ejecutar el CPU. La Pila o Stack es una memoria limitada que solo guarda el valor del Contador de Programa cuando sea necesario. Los periféricos del PIC son elementos que se pueden usar para una determinada tarea; por ejemplo, el Timer0 sirve para temporizaciones. El USART para comunicaciones seriales RS232, etc. Casi todos ellos serán estudiados en un capítulo aparte. Los puertos de E/S PORTA,... PORTE son las líneas hacia/desde el exterior donde se pueden conectar los dispositivos a controlar, como LEDs, transistores, LCDs, etc.

Hay más recursos presentes dentro de un PIC que también son imprescindibles pero cuyo trabajo queda en segundo plano. Algunos de ellos serán abordados con detalle en otro momento. La memoria de programa En los PIC16Fxxx es de tipo flash, por eso la F. Aquí es donde se aloja el programa que el CPU ejecutará. Se puede modificar por completo mediante un dispositivo programador por varios miles de veces. Pero tampoco te alegres tanto. No conozco a nadie que haya llegado a ese límite con un solo PIC. Lo más probable es que, por más cuidado que tengas, llegues a freir tu PIC antes de tiempo en algún accidente. Eso es algo muy ―normal‖.

CURSO_MICROS

Página |8

En los PIC16 la memoria de programa se cuantifica en palabras, de 14 bits cada una. Son de 14 bits porque cada instrucción es de 14 bits. Esto suele impresionar un poco al novel, quien está habituado a medir la capacidad de las memorias en bytes (8 bits). El PIC16F84A tiene 1 k (1024) palabras de memoria. En tiempo de ejecución son de solo lectura. Con 1 k puede almacenar hasta 1024 instrucciones de código ensamblador. Los PIC16F877A/876A tienen 8 k (8192) palabras de memoria de programa mientras que los PIC16F874A/873A tienen 4 k (4192). Los cuatro PICmicros ofrecen la posibilidad de escribir en su memoria de programa incluso en tiempo de ejecución. Esta función puede ser aprovechada para almacenar datos procesados por el usuario o para permitir la autoprogramación del PIC. En las siguientes figuras las memorias de programa del PIC están acompañadas por el PC (Program Counter) y la Pila (Stack). Es así porque hay una extrecha relación en su trabajo.

Contador de Programa, Pila y Memoria de programa del PIC16F84A y PIC16F87xA. El Contador de Programa, PC El PC es un registro que indica la siguiente instrucción que debe ejecutar el CPU. Si vale 0x0000, ejecutará la primera instrucción de la memoria; si vale 0x0002 ejecutará la tercera instrucción, y así... Al arrancar microcontrolador, el PC vale 0x0000 y se va incrementando automáticamente, con lo que el PIC debería ejecutar una a una desde la primera hasta la última instrucción del programa. En realidad, en el código habrá instrucciones que modifiquen el valor del PC de modo que el programa nunca termine.

CURSO_MICROS

Página |9

En los PICs de la familia Mid-Range el PC es de 13 bits, pudiendo direccionar un máximo de 8 k palabras de memoria de programa. La Pila o STACK Es una memoria que almacena temporalmente el valor del PC (Program Counter) cuando el programa llama a una subrutina o cuando salta al Vector de Interrupción, en una interrupción. En los PICs de la familia Mid-Range la Pila tiene únicamente 8 niveles y se administra a nivel hardware, esto es, no hay instrucciones para acceder a ella directamente. Su operación es enteramente en background. Solo debemos cuidar de que no se llegue a desbordar. La memoria RAM A diferencia de las RAMs de los microcontroladores convencionales, que tienen mapa de memoria plano, la RAM de los PICs de familia Mid-range está dividida en sectores denominados bancos. Cada byte de la RAM se conoce como registro. Hay dos tipos de registros de RAM: los registros de función especial SFR y los registros de propósito general GPR. No todos los registros están implementados físicamente. La escritura en dichas locaciones no significa nada y siempre se leen como 0. El PIC16F84A es de los muy pocos que tienen 2 bancos de RAM; el resto de los PIC16F, que son la gran mayoría, tienen 4 bancos. La existencia de los bancos solo es de consideración (y un dolor de cabeza) cuando se programa en lenguaje ensamblador. Registros de Funciones Especiales, SFR Antes dije que para programar PICs primero había que conocer sus recursos. Pues bien, todos ellos se pueden controlar mediante los registros SFR. Los registros SFR (Special Function Register) están ubicados en las primeras posiciones de cada banco de RAM, los que en la figura anterior aparecen con nombre propio, como TMR0, PORTA, etc. Su principal función es controlar las operaciones del microprocesador y de los módulos periféricos. Como se ve, algunos de esos registros aparecen duplicados en los bancos; eso es para facilitarnos su acceso porque son de uso muy frecuente o porque son un poquito más especiales, como STATUS, INTCON o PCL. Registros de Propósito General, GPR También son registros de 1 byte cada uno. Los registros GPR (General Purpose Register) sirven para almacenar los datos o variables que se procesan en el programa. El PIC16F84A tiene 68 registros GPR, todos ubicados en el banco 0, entre las direcciones 0x0C y 0x4F. En el banco 1 no hay registros GPR, solo hay accesos a los registros del banco 0. Dicho en otras palabras, los registros GPR del banco 1 son un reflejo de los GPR del banco 0.

CURSO_MICROS

P á g i n a | 10

Mapa de la RAM de datos del PIC16F84A. Los PIC16F877A/876A tienen 368 registros GPR. Los últimos 16 registros de los bancos 1, 2 y 3 son los mismos que del banco 0. Los PIC16F874A/873A tienen 192 registros GPR. Su mapa de RAM es un poco diferente debido principalmente a los accesos repetidos. Todas estas diferencias serán de preocupación solo cuando se programe en ensamblador.

CURSO_MICROS

Mapa de la RAM de datos de los PIC16F877A y PIC16F876A.

P á g i n a | 11

CURSO_MICROS

P á g i n a | 12

Mapa de la RAM de datos de los PIC16F874A y PIC16F873A. Los registros GPR no tienen nombres propios, pero los compiladores de alto nivel saben cómo administrarlos para almacenar las variables del programa. Por otro lado, si se programa en ensamblador, se les debe acceder mediante sus direcciones, ya sea directamente usando números, o asignándoles nombres a las direcciones con algunas directivas, como equ o cblock. Por ejemplo, en el siguiente código se designan los nombres var1 y var2 a los registros de direcciones 0x25 y 0x30, respectivamente.

CURSO_MICROS

var1 var2

equ equ

P á g i n a | 13

0x25 0x30

Luego se podrán usar esos nombres para acceder a los registros designados. Por ejemplo, el siguiente código copia el contenido del primer registro al segundo. movf var1, W movwf var2

; Mover var1 a W ; Mover W a var2

El diseñador puede elegir cualesquiera registros GPR como sus variables de programa. Para ello debe recordar siempre dónde se localizan. Según las figuras de arriba, en el PIC16F84A están mapeados a partir de la dirección 0x0C. En los PIC16F87xA empiezan en la dirección 0x20 en el banco 0; los otros bancos se usan raramente en ensamblador. Los Fuses de Configuración Los fuses del microcontrolador establecen una característica importante en su operación, tan importante que solo se puede modificar en el momento de programarlo. Por ejemplo, no se podría escoger el tipo de oscilador a usar después de haber iniciado el programa (sería como cambiarle los neumáticos a un automóvil en marcha). Los fuses se programan mediante los llamados Bits de Configuración, los cuales están contenidos en un registro de EEPROM especial denominado Configuration Word. Este registro está situado en la dirección 0x2007, aunque tiene poco sentido saberlo porque es inaccesible desde el programa en tiempo de ejecución. Cada aplicación puede requerir una configuración particular y si no se establecen los fuses correctos, el programa puede funcionar mal, suponiendo que funcione :). El PIC16F84A tiene 4 fuses y los PIC16F87xA tienen 9. Por tanto habrá diferencias en sus palabras de configuración. Ésta es la Palabra de Configuración del PIC16F84A:

Ésta es la Palabra de Configuración del PIC16F87xA:

La Palabra de Configuración de los PIC16F87xA incluye todos los bits del PIC16F84A, aunque varíen algunos nombres. De todos modos, esos nombres son raramente usados como tal. Los fuses se suelen programar usando máscaras que los representan. Por fortuna, las máscaras sí son iguales. La Palabra de Configuración se puede cambiar en el momento de ―quemar‖ el PIC en el IDE del software de programación, pero sería mejor que sus valores se cargaran desde el archivo *.hex junto con el código ejecutable. En seguida se muestra un ejemplo de

CURSO_MICROS

P á g i n a | 14

cómo establecer los fuses en el código fuente del programa en lenguaje ensamblador, mediante la directiva __config: __config _XT_OSC & _WDT_OFF & _PWRTE_ON Esta línea pone tres máscaras (_XT_OSC, _WDT_OFF y _PWRTE_ON) enlazadas por el operador &. Cada máscara indica el estado de un fuse. En este caso se indica: adaptar el circuito interno de oscilador para un XTAL, inhabilitar el Watchdog y habilitar el Power-up Timer. El resto de los fuses (los no citados) tendrán sus valores por defecto. No te preocupes si el anterior parrafo se leyó extraño. A continuación se describen los 9 fuses de los PIC16F87xA. El PIC16F84A solo cuenta con los 4 primeros. También se muestran las máscaras correspondientes utilizadas en ensamblador. Fuses de configuración Selección del oscilador Este fuse se representa por los bits Fosc1 y Fosc0. Sirve para adaptar el circuito interno del oscilador según el componente externo que se usará como fuente del reloj del sistema.  

 

_LP_OSC = Oscilador LP. Se usa cuando el PIC va a trabajar con un cristal de baja potencia. _XT_OSC = Oscilador XT. Se usa cuando el PIC trabajará con un cristal o resonador de frecuencias iguales o menores que 4 MHz. Es la opción que usaremos a lo largo del curso. _HS_OSC = Oscilador HS. Se usa cuando el PIC operará con un cristal o resonador de alta frecuencia, iguales o mayores que 4 MHz. _RC_OSC = Oscilador RC. Se usa cuando el PIC va a operar con un circuito RC. Es útil para sistemas de bajo costo aunque con frecuencias bajas y de menor nivel de estabilidad. Es la opción por defecto.

El Watchdog El Watchdog o WDT es un temporizador que puede monitorizar el funcionamiento fluido del microcontrolador. El WDT lo estudiaremos al final porque no es imprescindible. De momento diremos que se trata de un temporizador que una vez habilitado debemos resetear periódicamente en el programa. Si no lo hacemos, él reseteará el PIC y el programa se volverá a ejecutar desde 0. En la mayoría de los programas no querremos estar preocupándonos del estado del WDT, así que la mejor decisión será inhabilitarlo poniendo la máscara _WDT_OFF. Esto es necesario porque el WDT está habilitado por defecto.  

_WDT_ON = WDT habilitado. Opción por defecto. _WDT_OFF = WDT inhabilitado.

Power Up Timer Se representa por el bit PWRTE. El Power-up es un circuito que estando habilitado temporizará cerca de 72 ms después de conectada la alimentación del PIC, manteniéndolo en estado de reset. Luego de este tiempo el PIC empezará recién a

CURSO_MICROS

P á g i n a | 15

ejecutar el programa. Es muy útil para esperar a que la tensión de alimentación se estabilice.  

_PWRTE_ON = El temporizador Power-up está habilitado. _PWRTE_OFF = El temporizador Power-up está inhabilitado. Opción por defecto.

Protección de Código Se representa por el bit CP. Este fuse pone protección a la memoria de programa. Como sabemos, es posible leer el programa contenido en el PICmicro mediante el dispositivo programador (JDM por ejemplo). Si activamos este fuse, dicha lectura será impedida. También implica renunciar a la característica de verificación del programa; así que si lo vas a activar, no olvides reconfigurar el software de programación.   

_CP_OFF = Protección de código inhabilitada. Es la opción por defecto. _CP_ON = Protección de código habilitada (PIC16F84A). _CP_ALL = Protección de código habilitada (PIC16F87xA).

Escritura en memoria de programa Se representa con los bits WRT1 y WRT0. Los PIC16F87xA ofrecen la posibilidad de escribir en su memoria de programa Flash en tiempo de ejecución. Sin embargo, esto algunas veces puede resultar riesgoso. Así que para dotarle se seguridad adicional al programa este fuse permite configurar qué área de memoria quedará protegida y qué área no. El efecto no es siempre el mismo en los PIC16F877A/876A que en los PIC16F874A/F873A: no es lo mismo la mitad de la memoria del PIC16F876A que la mitad de memoria del PIC16F873A.    

_WRT_OFF = No hay protección de la memoria de programa. Opción por defecto. _WRT_256 = Se protegen las primeras 256 palabras de la memoria de programa. _WRT_1FOURTH = Se protege el primer cuarto de la memoria de programa. _WRT_HALF = Se protege la primera mitad de la memoria de programa.

Modo ICD Se representa con el bit DEBUG. Con el módulo ICD (In Circuit Debugger) habilitado, los PIC16F87xA ponen en acción la circuitería interna que monitoriza el estado del CPU, de los periféricos internos y de los registros especiales del PIC. Los resultados serán almacenados en un área reservada de la memoria RAM y luego enviados a un ordenador a través de una interface conformada por los pines RB6 y RB7. Del lado del ordenador estará corriendo un programa como el MPLAB en modo ICD para recibir todos los datos e ir visualizándolos en la pantalla. También es posible enviar desde el ordenador comandos de ejecución del programa como Step into, Step over, etc. (todos estos conceptos serán abarcados a lo largo del curso). En otras palabras, es como correr el simulador MPLAB-SIM o el VSM Proteus pero esto será real y a veces en tiempo real. La habilitación del modo ICD implica renunciar a los pines RB6 y RB7 como puertos de E/S convencionales, a un nivel de pila y a algo de memoria RAM.  

_DEBUG_OFF = ICD inhabilitado. Opción por defecto. _DEBUG_ON = ICD habilitado, RB6 y RB7 se destinan al debugger.

CURSO_MICROS

P á g i n a | 16

Protección de la EEPROM interna Se representa con el bit CPD. Sirve para proteger la memoria EEPROM interna de los PIC16F87xA contra accesos mediante un dispositivo externo. Funciona similar a la protección de la memoria de programa, esto es, podrá ser accedida normalmente por el CPU en tiempo de ejecución, mas no, por ejemplo, por un programador de PICs.  

_CPD_OFF = EEPROM interna desprotegida. Opción por defecto. _CPD_ON = EEPROM interna protegida.

Programación en bajo voltaje Se representa con el bit LVP. Los PIC16F87xA también ofrecen la posibilidad de ser programados con una tensión igual a Vdd en el pin MCLR, en vez de los 12 V acostumbrados. Éste es el modo de programación ICSP (In Circuit Serial Programming) de bajo voltaje. Los pines RB6 y RB7 también deben ser sacrificados para uso exclusivo del programador y además se les suma la presencia del pin RB3 como señal del modo de programación. Dada esta interface, no debe sorprender que esta característica puede ir muy de la mano con el depurador ICD. Sin embargo, para la programación en bajo voltaje no se requiere de herramientas especializadas. Habilitado este fuse, los pines RB7, RB6 y RB3 no responderán como puertos de E/S típicos.  

_LVP_ON = Programación en bajo voltaje habilitado. Opción por defecto. _LVP_OFF = Programación en bajo voltaje inhabilitado.

Brown Out Reset Es un reset por baja tensión. Esta característica le permite al PIC16F87xA auto resetearse cada vez que detecte una caída de tensión en la alimentación, por debajo de 4 V (valor típico). El PIC tiene un filtro pasa-bajas interno que evade el ruido. A tensiones aceptablemente por debajo de este nivel de tensión el PIC todavía puede tener una operación correcta pero no garantizada. Si no se quiere correr el riesgo y se prefiere optar por que el PIC reinicie todo, se puede activar este fuse mediante su bit de configuración BOREN o mediante su máscara respectiva.  

_BODEN_ON = Brown out reset habilitado. Opción por defecto. _BODEN_OFF = Brown out reset inhabilitado.

Puertos Descripción de los Puertos Los puertos se conforman por las líneas del microcontrolador donde se pueden conectar los dispositivos de Entrada/Salida a controlar, por ejemplo LEDs, displays, transistores, otros ICs o, mediante relés u optoacopladores, cargas de 110V/220V como medianos motores. El PIC16F84A tiene 2 puertos, representados por los registros PORTA y PORTB. Los PIC16F87xA tienen hasta 5 puertos, accesibles mediante los registros PORTA, PORTB,

CURSO_MICROS

P á g i n a | 17

PORTC, PORTD y PORTE. No todos los puertos tienen los 8 pines completos. El puerto E, por ejemplo, solo tiene 3. Los pines pueden tener nombres simples, como RB1, o compuestos, como RC6/TX/CK. Los nombres compuestos implican que dichos pines tienen funciones multiplexadas. Por ejemplo el pin RC6, además de pin digital convencional puede funcionar como línea de transmisión TX del puerto serie cuando el USART trabaja en modo asíncrono o como línea de reloj CK cuando el USART trabaja en modo síncrono. En principio todos los pines son bidireccionales cuando actúan como líneas de E/S digital. La dirección es configurable por software. Algunos pines pierden esa función cuando su control es asumido por algún módulo relacionado. Cuando actúan como salidas, los pines pueden entregar tensiones de hasta Vdd. Cuando actúan como entradas pueden manejar niveles de hasta 0.3V por encima de Vdd. El diseño de los pines incluye diodos internos de sujeción que les permiten soportar tensiones mucho mayores que Vdd o inferiores que GND, siempre que la corriente no sobrepase del orden de los micro Ampers. Cada pin de puerto puede suministrar o recibir hasta 25 mA de corriente. Sin embargo, esta capacidad no puede estar presente en todos los pines al mismo tiempo. En seguida tenemos los límites de corriente total que soporta cada puerto: Para el puerto A del PIC16F84A:  

Máxima corriente suministrada = 50 mA Máxima corriente recibida = 80 mA

Para el puerto B del PIC16F84A:  

Máxima corriente suministrada = 100 mA Máxima corriente recibida = 150 mA

Para los puertos A, B y E (juntos) de los PIC16F87xA:  

Máxima corriente suministrada = 200 mA Máxima corriente recibida = 200 mA

Para los puertos C y D (juntos) de los PIC16F87xA:  

Máxima corriente suministrada = 200 mA Máxima corriente recibida = 200 mA

CURSO_MICROS

P á g i n a | 18

Diagrama de pines de los PIC16F84A y PIC16F87xA. El puerto B Empezamos con el puerto B porque es el más fácil. Los nombres sencillos de sus pines revelan que no tienen muchas funciones. Los 8 pines RB0...RB7 trabajan como E/S digitales bidireccionales por igual. Es adecuado para interfaces ordinarias como el manejo de LEDs, control de LCDs, teclados, lectura de switches, pulsadores, etc. La etiqueta INT en el pin RB0/INT significa que además se puede configurar para recibir interrupciones externas. Solo en ese estado se comporta como entrada Schmitt Trigger. De hecho, los pines RB4, RB5, RB6 y RB7 también pueden responder a interrupciones. Estas interrupciones le permiten al microcontrolador atender inmediatamente a los eventos de cambios de nivel lógico en los puertos sin necesidad de estar monitorizándolos constantemente. Las interrupciones se estudian con profundidad mucho más adelante. El puerto B es el único entre los PIC16F que incluye resistencias de pull up internas. Eso nos ahorrará el tener que ponerlas externamente cuando sean requeridas, aunque lo ideal sería que hubiera pull-ups en todos los puertos, así como que todos los pines fueran Schmitt Trigger.

CURSO_MICROS

P á g i n a | 19

Recordemos (del capítulo 2) que los pines RB6 y RB7 también sirven de interface para la programación del PICmicro. Solo en ese modo estos pines actúan como Schimitt Trigger, aunque tenga poca relevancia para nuestros propósitos. También recordemos (del capítulo 3) que los PIC16F87xA soportan la programación en bajo voltaje. En ese modo su pin RB3 tiene una función muy crucial. Eso explica la inscripción adicional PGM (Modo Programación). La programación en bajo voltaje se habilita/inhabilita vía los Bits de Configuración. El puerto A El PIC16F84A tiene un puerto A de 5 pines, desde RA0 hasta RA4. Los cuatro primeros funcionan normalmente como pines de E/S bidireccionales y también soportan niveles TTL. El pin RA4, no obstante, es un tanto especial. Como salida es de drenador abierto y requerirá de una resistencia de pull externa si se usa como tal. Es el único pin que en todo momento tiene buffer Schmitt Trigger, lo que como entrada le da una mejor performance, y el único pin que puede recibir voltajes hasta de 8.5 V. RA4 puede funcionar adicionalmente como entrada del Timer0 cuando opera en modo Contador. Por eso su etiqueta adicional T0CKI (Timer0 Clock Input). (Descuida, si de momento no entiendes mucho de estos conceptos, esto no se aprende de la noche a la mañana.) En los PIC16F87xA el puerto A tiene 6 pines. Los cinco primeros son compatibles con los del PIC16F84A. El pin RA5 también es E/S, TTL y bidireccional. Ahora, la gran diferencia en el puerto A de los PIC16F87xA es que está multiplexado para recibir 5 de los 8 canales posibles del conversor ADC (analógico-digital) de estos PICs. Eso es lo que indican las etiquetas ANx que poseen algunos pines. Nota que el pin RA4/T0CKI no está en este grupo. Ahora un punto clave: para confusión de los que migran a los PIC16F87xA el puerto A inicia con una configuración analógica. Si se quiere usarlo para interface digital será necesario reconfigurarlo en el registro ADCON1. Más adelante se muestra cómo. El puerto C Muchos (casi todos) los módulos o periféricos nuevos de los PIC16F87xA tienen salida al exterior mediante los pines de este puerto. Aquí están los pines de recepción RX y transmisión TX del puerto serie del USART; aquí están los pines de datos SDA y reloj SCL del módulo MSSP cuando funciona en modo I2C; aquí están las salidas de los dos canales de PWM CCP1 y CCP2 de los módulos del mismo nombre cuando generan ondas PWM; aquí están las entradas del Timer1 T1OSO/T1CKI y T1OSI cuando opera en modo Contador. Creo que no tiene caso seguir con la descripción porque sería casi interminable y porque nos familiarizaremos con muchos de estos pines cuando estudiemos los módulos a los que están relacionados. Por lo demás, los pines del puerto C no necesitan de configuración previa alguna para trabajar como E/S bidireccionales, compatibles con TTL.

CURSO_MICROS

P á g i n a | 20

El puerto D Está conformado por los 8 pines RD0...RD7. Junto con el puerto E solo están presentes en los PIC16F de 40 pines y tienen la característica destacable (y quizá superflua) de ser la interface del módulo PSP o Puerto paralelo esclavo. Pero como ese módulo casi ni se usa, el puerto D podría tranquilamente reemplazar o ayudar al puerto B en las interfaces con los dispositivos fotoelectrónicos, electromecánicos, etc., dado que es también es bidireccional, configurable pin por pin y maneja señales TTL. El puerto E Solo tiene 3 pines RE0...RE2, que se pueden usar como analógicos o digitales. Como pines digitales son bidireccionales y también pueden funcionar como señales de control RD, WR y CS del módulo PSP. Como pines analógicos, dan ingreso a 3 de los 8 canales posibles del conversor ADC. Al igual que el puerto A, el puerto E también inicia con sus pines como entradas analógicas y habrá que configurarlos del mismo modo para que trabajen como pines de E/S digital, si así se desea.

Configuración de los puertos Después de un reset todos los puertos inician con sus pines configurados como entradas, pero se pueden reconfigurar en cualquier punto del programa mediante los registros TRISx. Cada puerto tiene su correspondiente registro TRIS, así por ejemplo, TRISA para PORTA, TRISB para PORTB,... y TRISE para PORTE. Si se escribe un 1 en un bit de TRISx, entonces el pin correspondiente en el puerto x será de entrada y si se le escribe un 0, el pin será de salida. Para recordar este concepto suele ser útil notar la semejanza del 0 con la o (de output) y del 1 con la i (de input).  

0 → Output = salida 1 → Input = entrada

Por ejemplo, si escribimos el valor 00001111 en TRISB, entonces los cuatro pines de menor peso del puerto B serán entradas digitales y los cuatro pines superiores serán salidas. Si escribimos 00000001 en TRISA, únicamente el pin RA0 será entrada y los demás serán salidas. Como el puerto A no tiene los 8 pines completos, los bits de mayor peso de PORTA y TRISA no tienen significado. La codificación de lo expuesto sería así: banksel TRISB ; Cambiar al Banco de los registros TRIS movlw b'00001111' ; Mover literal 00001111 a W movwf TRISB ; Mover W a TRISB movlw b'00000001' ; Mover literal 00000001 a W movwf TRISA ; Mover W a TRISA

CURSO_MICROS

P á g i n a | 21

Otra forma de configurar los puertos es pin por pin, utilizando las instrucciones bsf (bit set file = setear bit en registro) y bcf (bit clear file = limpiar bit en registro). Por ejemplo. banksel TRISB bsf TRISB, 2 bcf TRISA, 5

; Cambiar al Banco de los registros TRIS ; Setear bit 2 de TRISB ; Limpiar bit 5 de TRISA

Así hemos configurado los pines RB2 para entrada y el pin RA5 para salida. El resto de los bits de los registros TRISA y TRISB conservarán sus valores anteriores. Finalmente, el siguiente fragmento configura los puertos del PIC empleando una forma de cofidicación alternativa y a veces más ventajosa. banksel TRISB ; Cambiar al Banco de los TRIS movlw b'00001111' ; Configurar nibble alto de PORTB como salida movwf PORTB ; y el nibble bajo como entrada bsf PORTA, 4 ; Configurar pin RA4 como entrada La pregunta es: ¿acaso los puertos no se configuraban en los registros TRISx? Bueno, sucede que los siete primeros bits de los registros PORTx y TRISx son iguales, de modo que una vez cambiado de banco se pueden llamar por igual. Esto es extensible a todos los registros de la RAM, aunque solo resulta práctico al trabajar con los puertos. Ahora observemos una piedra con la que todos en algún momento hemos tropezado sobre todo al portar nuestros códigos del PIC16F84A a los PIC16F87xA. Se trata de los puertos A y E. Estos puertos además de entradas inician configurados como pines analógicos (entradas del ADC). El código del programa parece tan lógico pero el PIC no funcionaba bien porque el puerto A no era digital. Es posible establecer varias combinaciones seleccionando los pines que serán digitales y los que serán analógicos. Por ejemplo, si se quiere que todos los pines sean digitales, hay que escribir el siguiente código en ensamblador. Banksel ADCON1 movlw 0x06 movwf ADCON1

; Cambiar al banco de ADCON1 ; Mover 0x06 a W ; Mover W a ADCON1

O en lenguaje C ADCON1 = 0x06;

// Poner 0x06 en ADCON1

Los códigos mostrados cargan el registro ADCON1 con el valor 0x06. ADCON1 es uno de los registros que controlan el conversor ADC. Este módulo lo estudiaremos tendidamente en su momento. Por ahora nos bastará con saber que si escribimos 6 ó 7 en él, todos los pines de los puertos A y E tendrán comportamiento digital de E/S. Las resistencias de Pull-up Una de las cualidades que distinguen a los microcontroladores de los microprocesadores es que encierran en un solo chip todos los elementos posibles de un sistema de control. Con este fin los PICmicros incorporan en su puerto B transistores a manera de fuente de corriente que en la práctica funcionan como resistencias de pull-up.

CURSO_MICROS

P á g i n a | 22

Estas pull-ups nos pueden ahorrar el uso resistencias de sujeción externas en los pines del puerto B configurados como entradas. Las pull-ups se podrían equiparar con resistencias de 20 K, a calcular por la corriente que dejan fluir. Las 8 pull ups se pueden habilitar al mismo tiempo limpiando el bit NOT_RBPU, del registro OPTION_REG. Las pull ups solo serán efectivas en los pines que actúan como entradas; en los pines RBx configurados como salidas las pull ups quedan automáticamente inhabilitadas. La siguiente figura muestra la conexión de un pulsador al PIC aprovechando la pull-up del pin RB7. Fíjate en que las pull-ups no se pueden usar como resistencias para excitar dispositivos como LEDs, relés, etc.

Ejemplo de uso de las resistencias de pull-up. La figura de ejemplo solo muestra la pull-up del pin RB7 pero están presentes en todos los pines del puerto B. Los siguientes códigos habilitan todas las pull-ups del puerto B, aunque solo se activarán en los pines configurados como entradas. banksel OPTION_REG ; Cambiar al banco de OPTION_REG bcf OPTION_REG, NOT_RBPU ; Habilitar pull-ups de PORTB O en lenguaje C OPTION_REG.NOT_RBPU = 0;

// Habilitar pull-ups de PORTB

Tutorial proteus ¿Qué es Proteus VSM? A lo largo de este curso no muestro interés personal para promocionar algún producto en particular. Pero ―al César lo que es del César‖ y no tengo mayor reparo en asegurar que Proteus VSM es el mejor software de su clase que existe para aficionados y profesionales dedicados al desarrollo de proyectos con microcontroladores. Proteus ha revolucionado el concepto de simulación de circuitos electrónicos al pasar de las típicas presentaciones gráficas y textuales de información preprocesada (al estilo PSPICE) a la simulación interactiva muchas veces en tiempo real.

CURSO_MICROS

P á g i n a | 23

Podría seguir listando las potentes características de Proteus, pero como tampoco pretendo desafiar sus archivos de ayuda y manuales oficiales, los cuales son muy buenos y de lectura recomendada (para quien tenga tiempo:), prefiero aconsejarte que le eches un vistazo a los excelentes ejemplos que trae incluido. Quedarás más que asombrado. El entorno de ISIS Proteus

ISIS es el entorno de trabajo de Proteus. Aquí se diseñan, dibujan y simulan los circuitos. Bueno, no voy a describir cada uno de los elementos de esta ventana. Tú mismo puedes ir conociéndolos con tan solo señalarlos con el puntero del mouse. Además de las clásicas sugerencias que suele ofrecer como cualquier otro buen programa de Windows, Proteus muestra una pequeña descripción del elemento apuntado cuando se pulsa la tecla F1. Por ejemplo, la siguente figura muestra la información contextual del botón Generator. Claro que está en ingles, pero igual se entiende aunque sea un poquito. Además, no me digas que no sabes lo que significan esas frasecitas como Copy to clipboard, Save current design, Zoom in, Zoom out, etc. ¡Por favor! En cuanto a los elementos y comandos que son más propios de Proteus, aprenderemos a usarlos de a poco.

CURSO_MICROS

P á g i n a | 24

Se llama por objeto a los diversos elementos que pueden estar presentes en la hoja de diseño. Según su categoría presente en las barras de herramientas, los podemos citar así: Components. Representan todos los componentes electrónicos presentes en un circuito, como los LEDs, condensadores, microcontroladores, etc. Virtual Instruments. Ofrece los instrumentos de medición como el Osciloscopio, voltímetro, frecuencímentro, etc. Generator, para producir ondas cuadradas, senoidales, de reloj, etc. Simulation Graphs, para visualizar los resultados de la simulación en gráficos, al estilo de los programas como Electronics Workbench o Cadence Orcad. Inter-sheet Terminal. Nos permitirá colocar los terminales de entrada, salida, así como las fuentes de alimentación. Etc. Etc. El panel de la zona izquierda del entorno ISIS, que en la Figura 1-1 se ve con el título de DEVICES y con los botoncitos de P y L al lado, se llama Object Selector. El Object Selector eventualmente cambiará de nombre y desplegará los elementos o formas de la categoría seleccionada actualmente (Components, Virtual Instruments, etc.). Dibujando el circuito Durante este capítulo vamos a trabajar con la práctica 4-2 del Módulo 1. Para añadir un objeto a la hoja de diseño primero se establece la categoria del objeto. Por ejemplo para empezar a colocar los componentes electrónicos del circuito debemos seleccionar el icono Components

de la barra de herramientas.

CURSO_MICROS

P á g i n a | 25

Con ello, la ventanita Object Selector se convierte en Device Selector. En la figura de arriba aparece vacío porque aún no hemos sacado ningún componente. Así que clicamos ese botoncito P o sencillamente presionamos la tecla ―P‖. En cualquier caso nos veremos con la ventana Pick Devices.

En la caja de texto Keywords se escribe el componente buscado. Nota que Proteus tiene un excelente motor de búsqueda y no es necesario escribir el nombre completo de una parte ni usar comodines como en otros programas. A medida que se va escribiendo, Proteus va mostrando todos los elementos coincidentes. En este circuito necesitaremos PIC16F84A, resistor, capacitor, button (pulsador), LED y crystal. Las fuentes de alimentación se sacan de otro lado. Una vez localizado el componente buscado, le damos doble click para enviarlo al Device Selector. Así podemos ir sacando los dispositivos restantes. Cuando hayamos terminado con esta parte cerramos esta ventana dándole al botón Cancel o, mejor aún, presionando Escape en el teclado. Ahora el panel Object Selector contiene los diversos dispositivos que formarán nuestro circuito. Selecciónalos uno a uno y luego colocalos en el esquemático con un click izquierdo.

CURSO_MICROS

P á g i n a | 26

Los símbolos de tierra y alimentación que figuran arriba no se encuentran en las librerías de los dispositivos electrónicos. Los puedes sacar del Object Selector luego de ubicarte en la categoría Inter-sheet Terminal, identificada con el icono de la barra de herramientas. De allí también podemos sacar los terminales de entrada INPUT y salida OUTPUT, muy útiles para conectar elementos sin necesidad de unirlos directamente con cables.

Como los objetos no siempre se presentarán en la posición deseada, conozcamos algunas formas de cambiarlas. Un objeto queda seleccionado por un click izquierdo del mouse. Con ello aparecerá resaltado en color rojo (por defecto). Se quita la selección de un objeto haciendo otro click sobre alguna parte vacía de la hoja de diseño. Para editar la posición de un elemento selecciónalo y abre su menú contextual (de click derecho). Allí encontrarás las diversas opciones disponibles, como mover, borrar, rotar

CURSO_MICROS

P á g i n a | 27

en un sentido u otro, o reflejar sobre el eje X o Y. Alternativamente, puedes usar otros atajos, por ejemplo:  

 

Para mover un objeto, selecciónalo y luego arrástralo con el botón izquierdo hasta el lugar deseado. Para rotar un objeto, selecciónalo y luego presiona la tecla ‗+‘ o ‗-‘ del teclado numérico tantas veces hasta conseguir la orientación deseada. Otra forma de hacerlo es aplicando los botones de rotación al objeto selecionado. La rotación solo es posible en ángulos rectos.

Para reflejar un objeto, ya sea sobre un eje horizontal o vertical, selecciónalo y utiliza los botones de reflexión de la figura de arriba. Para eliminar un objeto, dale doble click derecho, o selecciónalo y usa la tecla supr.

La selección de un grupo de objetos se logra encerrándolos en un rectángulo dibujado con el botón izquierdo. Una vez hecho esto el menú contextual del botón derecho desplegará las opciones de edición de grupo como copiar, mover o rotar/reflejar. Estas opciones también están presentes en la barra de herramientas. Entre todo, la forma más fácil de mover un grupo de objetos seleccionado es arrastrarlo con el botón izquierdo.

Con frecuencia tras la edición de los objetos aún quedarán restos o marcas de dibujo sobre el esquemático. Para refrescar de forma rápida todo el diagrama se puede presionar la tecla R (de Redibujar). Los cables para la interconexión de los elementos del circuito no están en una categoría en especial. Se colocan directamente, aprovechando la forma de lápiz del cursor y las marcas de snap (esos pequeños □) que aparecen al acercar el lápiz a algún terminal conectable.

CURSO_MICROS

P á g i n a | 28

En este punto vamos a detenernos a comentar los elementos de este diseño porque nos resultarán muy recurridos en el futuro y además aprovecharé para justificar su presencia. 







PIC16F84A. A lo mejor el PIC que ves en mi esquemático no se parece al que tienes en tu Proteus. Lo que importa es que sea o tenga el mismo modelo, el resto es solo cuestión de apariencia (un tema que quizás aprendamos a manejar más adelante). Tal vez te inquiete la ausencia de los pines GND y VDD, pero inclusive eso no cuenta para la simulación. De hecho, Proteus asume que, como la mayoría de los dispositivos digitales, el PIC trabajará con alimentación de 0 y 5 V. LED-BLUE, LED-GREEN... Hay varios tipos de diodos LED disponibles. En este caso buscaremos los LEDs animados (los que prenden). Como ésta es una simulación, los colores quedan en segundo plano. RESISTOR. Al escribir resistor en la casilla Keywords se listarán muchísimas partes, desde los modelos genéricos hasta los resistores comerciales. En principio, podríamos elegir cualquiera de ellas; de todos modos, la impedancia puede reajustarse fácilmente. También, se podría afinar la búsqueda añadiendo el valor de la resistencia. Como ves, yo escogí el genérico RESISTOR. CERAMIC22P. Al igual que las resistencias, hay varios modelos de condensadores disponibles y admisibles. Solo que esta vez quise tomar una parte más especifica y, para no tener que cambiar el valor del capacitor después, busqué ―capacitor 22p‖. Por cierto, éstos son los capacitores que estabilizan el circuito oscilador del XTAL. Sin embargo, debes saber que para los microcontroladores, este circuito no tiene directa intervención en la simulación. De hecho, la frecuencia de operación del

CURSO_MICROS

P á g i n a | 29

PIC se establece en el mismo PIC, con lo cual el circuito del XTAL quedaría de adorno. A veces se lo suele ignorar para aligerar la carga del diseño y mejorar en algo la velocidad de simulación. 





DISC100N16V. Hallé este capacitor de desacoplo de 100 nF al escribir ―capacitor 100n‖. A decir verdad, ya que en el entorno de ISIS no hay ruido ni interferencias de ese tipo, este capacitor también es decorativo. CRYSTAL. Como se dijo anteriormente, en Proteus la frecuencia de trabajo del PIC es establecida en el mismo PIC (leer la siguiente sección), quedando la presencia del cristal como innecesaria. BUTTON. Así se llaman los infaltables pulsadores.

Edición de las propiedades de los objetos Una de las grandes ventajas de las simulaciones es que se pueden cambiar los elementos del diseño o sus valores con suma facilidad. Para editar las propiedades de un objeto hay que darle doble click izquierdo. Así se accede a su ventana de propiedades, la cual, por supuesto, variará de acuerdo con el objeto tratado. Por ejemplo, si quisiéramos cambiar el valor de una resistencia, solo habría que modificar el parámetro Resistance en su ventana Edit Component.

La fuente de alimentación POWER tiene un valor de 5 V por defecto, aunque no se note así en el esquemático. Si quieres ver que al menos diga VDD o VCC, puedes abrir su ventana de propiedades y escoger una opción del combobox.

CURSO_MICROS

P á g i n a | 30

Claro que el susodicho combobox no ofrece tensiones ordinarias. Si las requiriéramos las tendríamos que escribir a mano. Por ejemplo, para una fuente de 12V se escribe +12V al lado de String. La V no hace falta, pero el signo al inicio es imprescindible. Además, no se deben dejar espacios en blanco. La edición de las propiedades del PIC puede pasar por cambiar muchísimos parámetros. En este momento solo veremos los dos que realmente interesan en la gran mayoría de diseños. El programa del PIC y su frecuencia de operación. 

 

Program File es el campo donde se carga el programa del microcontrolador. Éste puede ser el conocido archivo *.HEX (el mismo que utilizamos para grabar el microcontrolador) o un archivo de depuración (*.COF o similar), que para propósitos de simulación y depuración resulta más ilustrativo. Detallaremos este punto luego. Para cargar un archivo dale click al icono de carpeta que aparece al lado y en el diálogo Select File Name que surgirá busca y selecciona el archivo en cuestión. Program Clock Frequency. En el caso de los PIC16 es la frecuencia del XTAL usado por el PIC. Para los PIC18 no necesariamente es así.

CURSO_MICROS

P á g i n a | 31

Simulación del diseño Vamos a emplear los siguientes botones de control:

 

 

Play (F12). Iniciar la simulación. Step (Ctrl + F12). Iniciar/Reiniciar el debugging, si al menos hay un microcontrolador en el diseño. Para el debugging (la depuración) se necesita algo más que el archivo *.HEX. Pause (Pause). Pausar la simulación. Stop (Shift + Pause). Detener la simulación.

Bueno, sin más, con el circuito mínimamente armado y con el programa del PIC (*.COF, *.HEX u otro) cargado, corre la simulación presionando el botón Play. Debería verse así:

CURSO_MICROS

P á g i n a | 32

¡¡¡Simulación en tiempo real!!! Qué diferencia con otros simuladores, ¿verdad?

Simulación y Depuración del programa del microcontrolador Con este modo podremos ver la ejecución del programa paso a paso, ver en diversas ventanas el cambio de los registros y demás datos de la RAM del microcontrolador, el contenido de la memoria EEPROM interna, la evolución de la Pila, etc. En general, digamos que es parecido al MPLAB SIM de MPLAB pero muchísimo mejor, como lo comprobarás. Proteus no solo simula el PIC, sino que lo hace en interacción con el resto de circuito. Además, ya no tendrás que ir tras esas inquietas ventanas que se esconden por todas partes. Una simulación paso a paso requiere de un archivo de depuración creado por alguna herramienta particular. Para los programas en ensamblador Proteus incluye una utilidad que genera un archivo con extensión .SDI. El linkador del MPLAB también puede generar un archivo *.COF (Code Object File), que es algo mejor, aunque no tan potente como los generados por los compiladores de alto nivel. Antes de seguir, te advierto que las versiones algo viejitas de Proteus no admiten el archivo *.COF de MPLAB para programas en ensamblador. Si es tu caso, te aconsejo avanzar a la sección Depuración/simulación con un archivo *.sdi y regresar después. Con todo esto en mente, puedes cargar en el PIC el archivo *.COF en lugar del archivo *.HEX, si es que no lo tenías así antes. Luego presiona el botón Step o simplemente, las teclas ―Ctrl + F12‖ del teclado y ¡voilà!: tenemos la ventana PIC CPU Source Code.

CURSO_MICROS

P á g i n a | 33

En la parte superior derecha de la ventana PIC CPU Source Code están los siguentes botones, con nombres ya familiares para nosotros: Sobra decir que es preferible acostumbrarse a las teclas de atajo que los identifican (Las he puesto en azul). Play o Execute (F12). Ejecuta la simulación de corrido. Step over the current Function/Subroutine (F10). Como el Step over de cualquier otro simulador. Si la instrucción actual es una llamada a una función o subrutina, se ejecuta toda de golpe sin entrar en su interior. En el caso de los delays relativamente largos notaremos una breve desaparición de la ventana de código. Step into the current Function/Subroutine (F11). Tampoco nada nuevo. Si la actual instrucción es una llamada a subrutina o función, se entra en su interior. Step out of the current Function/Subroutine. Lo mismo de siempre. Si ya te cansaste de estar dentro de una subrutina o función, presiona aquí para salir de ella. Execute until the current cursor position is reached. Lo que dice su nombre: ejecutar el programa hasta alcanzar la posición actual del cursor. Este botón solo se activa si se apunta a una posición válida y diferente de la instrucción actual. Se suele usar para medir el tiempo empleado en ejecutarse el código entre dos puntos del programa. Toggle breakpoint at source line off->on->disabled (F9). Supongo que aún recuerdas qué son los breakpoints: puntos del programa donde se pausará la simulación. Con este botón los pones, quitas o inhabilitas. También se puede usar el doble click.

Ventanas de depuración Cuando se arranca la simulación, al final del menú Debug aparecen los ítems de varias ventanas de depuración (Simulation Log, Watch Window, etc.) que nos recuerdan al menú Debug del MPLAB cuando se inicia el MPLAB SIM. Obviamente Proteus soporta mucho más que un PIC y este menú podrá crecer según el diseño. Excepto PIC CPU Source Code, las demás ventanas siempre deberían estar disponibles, inclusive para una depuración que solo use el archivo *.hex.

CURSO_MICROS

P á g i n a | 34

En la siguiente imagen se aprecian algunas de las ventanas de depuración, básicamente relacionadas al PIC. Pierde cuidado si lucen algo diferentes a lo que ves en tu ISIS. Todo ello es fácilmente configurable mediante el menú contextual de cada ventana. Allí podrás cambiar colores, tipos de fuente, formatos numéricos de presentación, campos a visualizar (si es el caso), etc. Es una ―labor de clicks‖.

CURSO_MICROS











P á g i n a | 35

Simulation Log. Envía un reporte de los detalles de la simulación. En principio muestra las librerías de simulación cargadas, la versión del kernel de SPICE utilizada y el tamaño del archivo (*.hex, *.cof u otro) cargado. Pero, más importante, también desplegará los errores, mensajes y advertencias de los eventos ocurridos durante la simulación, normalmente referidos al microcontrolador; por ejemplo, cortocircuitos (contention on net), acceso a un registro no implementado del PIC, desbordamientos de la Pila PIC, etc. Así que cuando sientas que algo anda mal con la simulación no dudes en revisar en primer lugar esta ventana. PIC CPU Source Code. La estuvimos viendo desde el principio. Si hay varios PICs en el diseño, se presentará una ventana de código para cada uno. En realidad, eso pasará con todas las ventanas PIC CPU... PIC CPU Stack. Recordemos que la Pila o Stack es donde se guarda temporalmente el valor del PC (Contador de Programa) cada vez que se llame a una subrutina o se atienda una interrupción. En este panel podrás ver cómo evoluciona y prever peligros de desbordamiento. En la figura de arriba la Pila tiene la primera posición ocupada (en rojo). Fíjate en que la Pila se llena hacia abajo. Eso se debe a que las Pilas siempre trabajan de cabeza. PIC CPU Registers. Muestra todos los registros SFR del PIC, incluyendo el registro de trabajo W. También muestra la siguiente instrucción a ejecutarse y los valores del Contador de Programa PC y del Puntero de Pila SP (Stack Pointer). PIC CPU Program Memory. Visualiza el código del programa en hexadecimal que se entiende poco o nada. Por eso y por falta de espacio no la puse en la figura de arriba.

CURSO_MICROS 



P á g i n a | 36

PIC CPU Data Memory. Aquí apreciaremos los valores de todos los registros de la RAM del PIC, incluyendo los SFR. Lo malo es que no es nada fácil distinguirlos. Si de examinar los registros SFR se trata, es preferible ver la ventana PIC CPU Registers y para los GPR la mejor alternativa es la ventana Watch Window. Watch Window. Es como la ventanita homónima del MPLAB. Allí podemos poner solo los registros de la RAM del microcontrolador que queremos observar.

Uso de la ventana Watch Window Los archivos de depuración producidos por los compiladores de alto nivel despliegan en una ventana aparte todas las variables utilizadas en el programa. Por desgracia, nuestro archivo *.cof para ensamblador no ofrece esa bondad. Una forma, no muy agradable, de resolver este impase es sacarlas a mano a la ventana Watch Window. Éste es el menú contextual (del botón derecho) de la Watch Window.

Si elegimos la opción Add Items (By Name)..., veremos una ventana con todos los registros SFR, los cuales podemos enviar uno a uno a la Watch Window dándoles doble click.

CURSO_MICROS

P á g i n a | 37

En cambio, al tomar la opción Add Items (By Address)... estaremos frente a una ventana más completa donde también podemos encontrar los registros SFR al desplegar el combobox Address. Los registros marcados se envían a la Watch Window presionando el botón Add.

Supongo que habrás notado que las variables ordinarias del programa (registros GPR) no aparecen por ninguna parte, por ejemplo, cont1 y cont2 de nuestro SimpleSeq.asm. No habrá más remedio que ponerlas a mano. Sabiendo que cont1 y cont2 tienen las

CURSO_MICROS

P á g i n a | 38

direcciones 0x0C y 0x0D, respectivamente, tipeamos esos datos en los campos Name y Address, como se ve en la figura de arriba y luego clicamos Add. Ya que todos los registros los usamos en forma de bytes (8 bits), el marco Data Type queda con Byte. En otras ocasiones se suelen concatenar varios registros para formar variables de 2, 3, 4 u 8 bytes. El marco Display Format es más previsible y, por supuesto, dependerá del dato que representa la variable; por ejemplo, nuestros contadores se verán mejor en decimal sin signo (unsigned integer). De todos modos, estas presentaciones también se pueden modificar en la misma Watch Window mediante el menú contextual de cada elemento. Nota: En este caso fue fácil deducir las direcciones de las variables. En caso de haber muchas más o de encontrarse en posiciones de difícil localización, podemos abrir el archivo *.lst del proyecto y chequear la parte final. Allí está una tabla de símbolos que, entre otras cosas, muestra la identificación de una variable, es decir, su dirección. Uso de instrumentos virtuales El icono Virtual Instruments de la barra de herramientas despliega en el Object Selector la lista disponible, de la cual en este momento solo veremos un par de ellas. No tendría sentido que explicásemos los depuradores SPI DEBUGGER e I2C DEBUGGER porque, imagino, aún no tenemos idea de lo que significan. Por otro lado, supongo que tampoco te hace falta leer un tutorial para aprender a usar el voltímetro y el amperímetro. Sobre los demás instrumentos, o son muy poco usados o son igual de sencillos.

Uso del COUNTER TIMER Aunque la barra de estado de ISIS va mostrando el tiempo de simulación transcurrido, no es la mejor forma de medir los tiempos que toman en ejecutarse algunos segmentos de código. El Timer Counter se puede configurar como cronómetro (Time), frecuencímetro (Frequency) o contador de pulsos (Count) en su ventana de propiedades, pero también se puede hacer al vuelo en plena simulación. De sus tres terminales normalmente el único que se conecta es el CLK. CE puesto a 0 detiene su operación y RST reinicia el instrumento.

CURSO_MICROS

P á g i n a | 39

Cuando la simulación/depuración esté en ejecución dale click izquierdo para que aparezca con ventanita más grande, como la siguiente.

Observa los cuatro botones (también presentes en su ventana de propiedades):    

MODE establece la operación del Counter Timer como cronómetro (Time), contador de pulsos (Count), etc. MANUAL RESET. Es más cómodo hacer el RESET aquí que desde el pin RST. RESET POLARITY indica si el RESET será en el flanco de subida o de bajada del botón anterior. GATE POLARITY establece si en modo contador el incremento será con los pulsos positivos o negativos.

A modo de ejemplo veamos el tiempo exacto que toma la subrutina Pausa de nuestro programa SimpleSeq.asm. No pongo las capturas de pantalla porque creo que ya estoy abusando.

CURSO_MICROS     

P á g i n a | 40

Luego de colocar un Counter Timer sobre el esquemático es conveniente regresar a la categoría Component (son ―cosas de Proteus‖). Iniciamos la simulación/depuración y agrandamos el Counter Timer para verlo mejor. Nos ubicamos en cualquiera de las líneas call Pausa y reseteamos el Counter Timer. Ejecutamos toda la subrutina con Step Over. Esta subrutina demoró 250002 µs = 250.002 ms.

Ahora mediremos el tiempo que transcurre entre las instrucciones de las líneas 23 y 30 del código.      



Nos ubicamos en la línea 23 y reseteamos el Counter Timer. Resaltamos la línea 30 y empleamos la opción Execute until the current cursor position is reached. El tiempo medido es 750010µs = 750.01ms. Otra forma de resolver este tipo de ejercicios es mediante los breakpoints. Nos ubicamos en la línea 23 y reseteamos el Counter Timer. Ponemos un breakpoint en la línea 30. Aparte del botón , también se puede hacer con la tecla F9 o, al estilo de MPLAB IDE, con doble click en la línea en cuestión. Deja que corra el programa (F12). Se detendrá por sí solo en el breakpoint. Obviamente, el tiempo medido fue el mismo.

Uso del OSCILLOSCOPE Los primeros Osciloscopios de Proteus solo tenían dos canales y presentaban una interface bastante sencilla. Ahora son de cuatro canales, a colores y algo más completos. Con todo, la compatibilidad con las versiones anteriores se mantiene, y a veces inclusive prefiero las primeras.

CURSO_MICROS

P á g i n a | 41

Se puede notar una clara distinción de seis recuadros, cuatro de los cuales corresponden a los cuatro canales (Channel) A, B, C y D, con colores distintos.   

Los diales Position desplazan las gráficas de cada canal hacia arriba o hacia abajo, en el eje Y. Los diales de tensión fijan la amplitud de voltaje por división. Va desde 2mV/div hasta 20V/div. Con la barra deslizadora de cada canal se decide si las señales serán tratadas tales cuales son (DC), solo sus componentes alternas (AC), el nivel de tierra (GND) o si no aparecerá (OFF).

Las opciones del recuadro Trigger se pueden emplear para muestrear las señales de manera tal que se tengan gráficas más fluidas sin desfases. En realidad, se usa raramente porque este osciloscopio es más bien ideal y poca falta ese tipo de calibraciones. En el recuadro Horizontal el dial inferior establece el tiempo base para los canales, va desde 0.5µs/div hasta 200ms/div. A modo de ejemplo vamos a simular el circuito de un sencillo amplificador conformado por un opamp. Luego tomaremos las señales de tensión en la entrada y en la salida.

CURSO_MICROS

P á g i n a | 42

Luego de una adecuada calibración de los diales tendremos una imagen así:

Uso de gráficos de simulación Dada la potencia del osciloscopio de Proteus, el uso de gráficos para visualizar datos de la simulación podría parecer redundante. Bastará con revisar los ejemplos incluidos en Proteus para darse cuenta de que eso no es del todo cierto. Los gráficos de Proteus son muy parecidos a los obtenidos por programas como PSPICE o Electronics Workbench. De hecho, utilizan los mismos modelos de SPICE y el mecanismo para construirlos suele ser similar, sobre todo en los gráficos analógicos. Sucede que casi todos los modelos digitales de Proteus son nativos.

CURSO_MICROS

P á g i n a | 43

Vamos previendo por tanto que podemos optar por gráficos analógicos o digitales, aunque eso no significa que un gráfico analógico no pueda incluir una señal digital o viceversa. Continuando con el diseño anterior en este ejercicio vamos a capturar las gráficas de las tensiones de entrada y salida del amplificador. Primeramente selecciona la categoría Simulation Graph

de la barra de herramientas.

Del Object Selector escoge ANALOGUE y luego dibuja un rectángulo en el esquemático con el botón izquierdo del mouse. Quedará como el que aparece a la derecha de la siguiente figura. (Las flechitas azules Vi y Vo del circuito las pondremos después.)

Abramos la ventana de propiedades de este objeto para ver un par de detalles. Start time y Stop time determinan el margen temporal de la gráfica presentada. Así, con un Start time=0 y Stop time=10 tendremos la gráfica de los primeros 10 segundos. Cambiando Start time=100m y Stop time=200m establecemos una simulación entre los tiempos 100ms y 200ms. ¿Se entiende?

CURSO_MICROS

P á g i n a | 44

Selecciona la categoría Voltage Probe (sondas de voltaje) de la barra de herramientas y sin darle importancia al Object Selector haz click sobre los puntos del circuito cuyas tensiones tomaremos. Aparecerán esas pequeñas flechitas azules que se conocen como Probes (sondas). Yo solo he puesto dos probes: uno en la entrada y otro en la salida del circuito. Puedes editar las propiedades de los probes como cualquier otro objeto. Como ves en la Figura 1-27, yo les cambié de nombre: Vi para el primero y Vo para el segundo. Es solo para darles algo de identidad. Ahora selecciona un probe y con el botón izquierdo arrástralo y suéltalo sobre el rectángulo de la gráfica. Si el probe cayó bien, debió haber aparecido uno similar dentro del rectángulo. Al final verás que el probe original no se ha movido (si lo hizo, es que fallaste ;). Luego haz lo mismo con el otro probe. El rectángulo quedará como éste.

Ahora presiona la barra espaciadora del teclado. Momentáneamente la barra de estado de ISIS mostrará el progreso de la simulación y cuando haya finalizado, veremos la gráfica esperada.

Bueno, en realidad no tanto. Esperábamos ver ondas senoidales, ¿cierto? Debe ser que están tan juntas que no se notan. Así que dale click a la franjita verde superior, allí donde dice ANALOGUE ANALYSIS. La gráfica aparecerá en una ventana propia. (También se puede maximizar desde el menú contextual.)

CURSO_MICROS

P á g i n a | 45

Bueno, esto tampoco es lo que esperábamos, pero al menos ya tenemos disponibles los botones de ZOOM en la parte baja. Puedes utilizarlos para estirar la imagen. En todo caso, hubiéramos establecido la simulación de un tramo más corto, ¿verdad? Pues no tenemos que regresar al esquemático. Se puede reconfigurar el tiempo de simulación con la opción Edit Graph... del menú Graph. Se volverá a presentar la misma ventana de la Figura 1-28, donde se establece el tramo de simulación. En esta ocasión vamos a poner, Start time=100m y Stop time=110m. Luego presionamos el botón Run simulation for current graph (ése del hombrecito rojo corriendo) y...

CURSO_MICROS

P á g i n a | 46

Eso sí se ve mucho mejor. Nota que los márgenes de la gráfica dicen 100 ms y 110 ms, tal cual lo indicamos. Los demás detalles de la gráfica, como el uso del cursor, las coordenadas de tiempo y valores de señal en cada punto mostrados en zona inferior, cambio de colores, etc., los dejo a tu observación. Solo es cuestión de echarle ojo. Depuración/simulación con un archivo *.sdi El archivo *.COF producido por el MPLAB IDE para programas en ensamblador con fines de depuración sofware solo es soportado por las versiones más recientes de Proteus. Por estas limitaciones Proteus solía emplear el archivo *.HEX acompañado de un archivo *.SDI, el cual estructuralmente es muy parecido al archivo *.LST. A diferencia de un *.cof, que separa los archivos del programa en diferentes campos, un archivo *.sdi lo presenta todo junto en un solo cuerpo. Esto puede resultar algo incómodo, ya que si trabajamos con varios archivos es precisamente para ordenar las cosas. Así mismo, cada vez que se edite el archivo principal del código fuente, Proteus detectará la desactualización del archivo *.sdi y ensamblará todo el programa de nuevo. Esto también le quita algo de sentido al trabajo del proyecto con el MPLAB IDE. En este modo el único archivo a cargar en el PIC es el *.HEX; el archivo *sdi solo tiene que acompañarlo en su carpeta de destino. Para crear un archivo *.sdi sigue los siguientes pasos: (Retomaremos nuestro SimpleSeq.asm.) 

Ve al menú Source y selecciona la opción Add/Remove Source Files... Te aparecerá la siguiente ventana (pero con los campos vacíos).

CURSO_MICROS



 





P á g i n a | 47

Ahora dale al botón New y a continuación selecciona el archivo de código fuente del programa. En caso de tener un programa comprendido por varios archivos, solo se debe seleccionar el archivo principal. (El archivo principal suele tener la extensión .asm y los demás, .inc.) El nombre del archivo seleccionado irá al combobox Source Code Filename. Como ves arriba, yo he escogido el SimpleSeq.asm. Seguidamente, en el combobox Code Generator Tool, elige MPASMWIN. Es una copia del ensamblador que incluye el MPLAB. Con esto verás después que no hará falta construir el proyecto en el MPLAB IDE, dado que se volverá a ensamblar todo el programa otra vez. Luego clica OK y sigamos. Nota que en el menú Source ahora se ha agregado un ítem con el nombre de nuestro archivo *.asm. Seleccionando esa opción se abrirá un editor muy parecido al block de notas con el código del programa. Siendo un editor muy pobre, lo puedes cambiar por otro (Notepad++, por ejemplo) seleccionando la opción Setup External Text Editor... Pruébalo en otro momento, cuando tengas tiempo.

Bueno, terminemos con esto: clica Build All (Construir todo). Por un momento aparecerá la clásica ventanita del MPASMWIN y luego quedará una ventana más grande con el mensaje de ―Build completed OK‖ al final. Ciérrala y luego nos vemos. Nota: si la construcción falla, esta ventana nos dará los errores hallados, pero como no es una lista muy detallada, siempre convendrá revisar el archivo *.err.

CURSO_MICROS

P á g i n a | 48



Si te fijas en la carpeta del proyecto, verás que ha aparecido (junto a los esperados *.hex, *.lst...) un archivo con extensión .sdi. Solo déjalo allí. Tú sigue cargando el archivo *.HEX en la ventana de propiedades del PIC.



Ya puedes presionar Ctrl + F12.

CURSO_MICROS

P á g i n a | 49

Propiedades avanzadas del PIC Por lo general y como se ha podido comprobar, muchos de los componentes de Proteus no requieren nada de edición. De hecho, se pueden encontrar partes con modelos que ya tienen todos los parámetros correctamente calibrados. No obstante, hay casos en los que una parte enteramente modelada más que ayudar puede devenir en una mella para la performance de la simulación. En este apartado trataremos algunas de las propiedades del PIC cuya configuración sería más conveniente que la hiciera el usuario directamente si así lo demandase. La siguiente ventana es la misma que abrimos para cargar el programa del PIC y poner su frecuencia de trabajo. Ahora la tenemos para observar los campos más interesantes de los que sobran, casi todas pertenecientes al combobox Advanced Propierties.









Program Configuration Word: La palabra de configuración contiene los Bits de Configuración. Aunque no se reflejen directamente, sus valores se cargan desde el mismo archivo *.HEX, por lo que este campo no debería quitarnos la atención. Aun así, en Proteus hace falta algo más para que los bits de configuración entren en la simulación. Sigo hablando de esto en lo subsiguiente. Randomize Program Memory?: Raramente el programa del PIC alcanzará el límite de la memoria de programa. Las posiciones restantes normalmente quedan como datos 3FFF y así se cargarán para la simulación. Si por algún extraño motivo quisieras que esas posiciones se rellenaran con valores aleatorios, podrías establecer esta propiedad con un YES. Randomize Data Memory?: Igual que el caso anterior pero con la memoria de datos. Generalmente las variables utilizadas en un programa deberían estar inicializadas. Así que esta propiedad tampoco debería interesar. Dump Configuration Word? ¿?

CURSO_MICROS 













P á g i n a | 50

Model PIC Start-up Delays?: Se refiere al retardo inicial producido principalmente por el temporizador Power-up Timer. Es un tiempo que dura 72 ms tras conectarse la alimentación del PIC. Durante este lapso el PIC se mantiene en estado de RESET (para que la alimentación del circuito se estabilice) y luego recién ejecutará la primera instrucción del programa. Es el mismo tiempo que siempre habilitamos con el fuse _PWRTE_ON en la palabra de configuración. En conclusión, si queremos simular el tiempo del Power-up Timer en Proteus, además de activar el fuse en el código del programa, debemos poner un YES en este campo. Model PIC Wake-up Delays?: Se trata de un tiempo de 1024 ciclos de reloj (256 µs para un XTAL de 4MHz) generado por el temporizador interno Oscillator Startup Timer. También complementa al Power-up Timer pero sirve básicamente para esperar que el reloj del sistema se estabilice luego de salir del modo Sleep. En el chip real este temporizador no depende de nosotros ya que siempre estará activado. Es solo un tema de Proteus y la verdad es que, como 1024 ciclos son poco apreciables, se suele ignorar para las simulaciones. (Se estudia el modo Sleep en el Módulo 2.) Generate Q Clocks on CLKOUT Pin?: Cuando el PIC opera con un oscilador RC externo (de frecuencia Fosc) en vez de un XTAL, el pin OSC2/CLKOUT sacará una onda cuadrada de frecuencia Fosc/4. Y nosotros sabemos que a Proteus le interesa un bledo si se usa XTAL, circuito RC u otro oscilador externo. Por tanto, poniendo YES en este campo el pin OSC2/CLKOUT mostrará la onda de Fosc/4 (siendo este Fosc la frecuencia configurada en la ventana de propiedades del PIC), independientemente del oscilador externo usado. Como sea, una señal de este orden en Proteus sería demasiado pesada de simular, por lo que es preferible dejarla tal como está, inhabilitada. Watchdog Timer Period?: El Watchdog es un temporizador que tiene un tiempo base de 18ms, el cual varía ligeramente con la temperatura del chip. Al igual que todas las partes digitales de Proteus, el PIC no tiene un parámetro que interactúe directamente con la temperatura establecida para el diseño. Si se desea una simulación con un valor de Watchdog Timer Period un poquito diferente del típico, éste es el campo donde se cambia. (Se estudia el Watchdog en el Módulo 2.) Port Pin Low-High Delay y Port Pin High-Low Delay: En el mundo real los niveles de tensión en los pines del PIC no permutan instantáneamente. Estos tiempos de propagación son del orden de los nanosegundos y Proteus suele despreciarlos por defecto para la simulación. En caso de tener algún diseño donde ese parámetro realmente te importe debes indicar en este campo los tiempos pertinentes. (Los puedes hallar en el datasheet.) Data EEPROM Write Delay. Según su datasheet, los PIC16F tienen una EEPROM cuyos datos se graban en un tiempo típico de 4 ms, llegando a 10 ms como mucho. En este campo se puede establecer algún valor en particular. (Estudiaremos este recurso en el Módulo 2.) Initial contents of EEPROM. Es la misma EEPROM del punto anterior. Se supone que el contenido inicial de esta memoria también puede formar del archivo *.hex; así que este campo será raramente cargado.

CURSO_MICROS

Módulo 2 Contenido Índice Capítulo 1: El Lenguaje C para microcontroladores 









Introducción o

Compilador de alto nivel

o

¿Por qué C y no Basic?

o

¿Qué compilador usar?

o

¡Ánimo! No es tan difícil

Estructura de un programa o

Los comentarios

o

Las sentencias

o

Los bloques

o

Las directivas

o

Las funciones

Variables y Tipos de Datos o

Declaración de variables

o

Especificadores de tipo de datos

Sentencias selectivas o

La sentencia if

o

La sentencia if - else

o

La sentencia if - else - if escalonada

o

La sentencia switch

Sentencias iterativas o

La sentencia while

o

La sentencia do - while

o

La sentencia for



Bloques simples



Los operadores

P á g i n a | 51

CURSO_MICROS





o

Operadores aritméticos

o

Operadores de bits

o

Operadores relacionales

o

Operadores lógicos

o

Composición de operadores

o

Precedencia de operadores

Las funciones o

Funciones sin parámetros

o

Funciones con parámetros (por valor)

o

Parámetros por referencia

o

Prototipos de funciones

o

Variables locales y variables globales

o

Variables static

o

Variables volatile

Arrays y Punteros o

Los arrays o matrices

o

Declaración de arrays

o

Inicialización de arrays

o

Cadenas de texto

o

Los punteros

o

Declaración de punteros

o

Apuntando a variables

o

Asignaciones indirectas mediante punteros

o

Punteros y arrays

o

Paso de punteros y arrays a funciones

o

Arrays constantes

Capítulo 2 El Compilador BoostC 

El compilador BoostC/C++



Práctica 1 Creación de un proyecto en BoostC

P á g i n a | 52

CURSO_MICROS 

Práctica 2



Práctica 3



Práctica 4

Capítulo 3 El Display LCD 

Introducción



Pines del LCD



Memorias del LCD o

CGROM

o

DDRAM

o

CGRAM

o

El Puntero de RAM



Set instrucciones del LCD



Inicialización del LCD



Interface de un LCD



Control del Display LCD



Práctica 1 ―Hellow World‖



Práctica 2 Visualización de números



Práctica 3 Caracteres gráficos en LCD

Capítulo 4 El Teclado Matricial 

Operación del teclado



Control de un teclado



Práctica 1 Lectura de teclado mediante sondeo



o

El circuito

o

El código fuente

o

Descripción del código

Práctica 2 Control de teclado por interrupciones o

El código fuente

o

Descripción del código

P á g i n a | 53

CURSO_MICROS

Capítulo 5 Las Interrupciones 

Introducción



¿Qué es una Interrupción?



Fuentes de interrupción



Control de interrupciones o



El registro INTCON

La Interrupción RB0/INT o

El registro OPTION_REG



Práctica 1 Interrupción RB0/INT



El Modo Sleep



Práctica 2 Durmiendo



La Interrupción de Cambio de PORTB



Práctica 3 Interrupción de Cambio de PORTB



Práctica 4 Interrupciones múltiples



Anatomía de una Interrupción



o

Secuencia de ejecución de las interrupciones

o

Retorno de una interrupción

o

Guardar el Contexto de las Interrupciones

Práctica 5 Interrupciones en ensamblador

Capítulo 6 Los Timers 

Introducción



El Timer0 o

El registro OPTION_REG

o

El Prescaler del Timer0

o

El Timer0 en modo Temporizador

o

Cálculo de la temporización



Práctica 1 Temporización con sondeo del Timer0



Interrupción del Timer0



Práctica 2 Uso de la interrupción del Timer0

P á g i n a | 54

CURSO_MICROS 

Práctica 3 Estirando la temporización o

El Timer0 en modo Contador



Práctica 4 El Timer0 en modo Contador



El Timer2 o

Registros del Timer2

o

El Prescaler y el Postscaler del Timer2

o

Interrupción del Timer2

o

Cálculo de la temporización



Práctica 5 Uso del Timer2



El Timer1 o

Registros del Timer1

o

Modos de operación del Timer1

o

Interrupción del Timer1

o

Cálculo de la temporización

o

Acceso a los registros del Timer1



Práctica 6 El Timer1 en modo temporizador



Práctica 8 El Timer1 con XTAL externo

Capítulo 7 El USART 

Introducción



El Estándar RS-232





o

Voltajes de los niveles lógicos del RS-232

o

Formato de transferencia de datos

o

Velocidad de transmisión (Baud Rate)

o

Señales del puerto serie

o

Control del flujo de datos (Handshaking)

Interface serial microcontrolador-ordenador o

Requerimientos hardware

o

Requerimientos software

El USART de los PICs

P á g i n a | 55

CURSO_MICROS o

Los registros del USART

o

Inicialización del USART

o

Transmisión de datos del USART

o

Recepción de datos del USART

o

Cálculo del Baud Rate

o

Los registros TXSTA y RCSTA en detalle



Práctica 1: Comunicación PC - PIC - LCD



El programa Tera Term



Práctica 2: Tratamiendo de textos y números



Las Interrupciones del USART



Práctica 3: Interrupciones del USART



El buffer circular o buffer de anillo



Práctica 4: Buffer circular con Interrupciones



Práctica 5: Interface RS-232 entre dos PICs

Capítulo 8 El MSSP en modo I2C 



Protocolo del bus I2C o

Características bus I2C

o

Transferencias de datos

o

Condiciónes de Start, Stop y Start Repetido

o

El bit de Reconocimiento (ACK o NACK)

o

El Byte de Control

o

Velocidad de transferencia de datos

Módulo MSSP en modo I2C o

Registros del MSSP en I2C Master mode

o

Configuración del I2C Master mode

o

Velocidad de transferencias de datos

o

Condición Start

o

Condición Repeated Start

o

Condición Stop

P á g i n a | 56

CURSO_MICROS





o

Transmitir Dato y Recibir bit ACK/NACK

o

Recibir Dato y Transmitir bit ACK/NACK

o

Los registros SSPSTAT, SSPCON y SSPCON2

o

Interrupciones del módulo I2C

Memorias EEPROM 24xx128 o

Descripción de pines

o

Dirección del dispositivo

o

Lectura y escritura aleatorias de bytes

Práctica 1 Acceso aleatorio a la eeprom 24xx128 o



Lectura Secuencial y Escritura por Páginas

Práctica 2 Acceso secuencial a la 24xx128

Capítulo 9 El Conversor Analógico digital 

Introducción



Conceptos básicos





o

Resolución y tensiones de referencia del ADC

o

ADC de aproximaciones sucesivas

El módulo ADC de los PIC16F87xA o

Registros del módulo ADC

o

Configuración de los canales del ADC

o

Reloj del ADC y Tiempo de Conversión

o

Resultado de la conversión

o

Tiempo de adquisición

Práctica 1 Uso del conversor ADC o



Interrupción del ADC y conversiones en modo Sleep

Práctica 2 Conversiones en modo Sleep

Chapter 10 Los módulos CCPx en modo PWM 

Introducción



Registros de los módulos CCPx



Generación de ondas PWM de 8 bits

P á g i n a | 57

CURSO_MICROS

1-

o

Periodo y frecuencia y de la onda PWM

o

Duty cycle de la onda PWM



Práctica 1 PWM de 8 bits



Generación de ondas PWM de 10 bits



Práctica 2 PWM de 10 bits

P á g i n a | 58

El lenguaje C para microcontroladores > Los compiladores de alto nivel

Introducción Los compiladores de alto nivel Los compiladores de alto nivel son las herramientas de programación mas potentes que existen. En resumidas cuentas, el compilador traducirá el programa escrito en su lenguaje (C, Basic, Pascal u otro) en código ensamblador y luego generará los archivos de depuración (*.dbg, *.cof, .d31, etc.) necesarios y de ejecución (.hex). Al trabajar con un lenguaje de alto nivel el programador ya no tiene que preocuparse (o lo hace muy poco) por las características hardware ni por el ensamblador nativo de cada microcontrolador. Esto simplifica de manera asombrosa el desarrrollo de proyectos. Los compiladores se encargan de traducir el código fuente al código objeto de cada microcontrolador sin inportar mucho cuál sea. Por ejemplo, un código escrito para un PIC16F84 podría ser facilmente compilado para un PIC16F877A u otro, y viceversa. Inclusive es posible adaptar un código para un microcontrolador de otra marca, por ejemplo, de Freescale o Atmel. Eso se llama portabilidad. ¿Por qué C y no Basic? Ciertamente, el Basic es el lenguaje más fácil de aprender (no es exactamente la razón de su nombre). Y aunque los programadores en C de ordenadores miren con desdén a los que usan el Basic, en el mundo de los microcontroladores los compiladores Basic no tienen motivo para sentirse menos. De hecho, algunos pueden ser casi tan eficientes como los mejores compiladores C. Las características (muchas veces complejas) del C fueron ideadas para el trabajo con sofisticados proyectos, propios de los ordenadores. Muchas de esas características ya no resultan tan ventajosas en el limitado hardware de los microcontroladors y se convierten en prescindibles. Además, la simplicidad de los compiladores Basic para microcontroladores también permite que varios de ellos, como MBasic o PIC Basic Pro (por citar algunos) mantengan una compatibilidad entre sus códigos que no se encuentra entre los compiladores C. Ésas podrían ser razones más que convincentes para empezar por el Basic y, de hecho, es la opción que muchos han elegido. ¿Por qué nosotros no?

CURSO_MICROS

P á g i n a | 59

Porque es verdad comprobable que los mejores programadores trabajan en C (no siempre exclusivamente, pero lo manejan). Por consiguiente, los proyectos más fantásticos y alucinantes que se pueden encontrar están en C. Es más, la mayoría de, por no decir todos, los programadores de Basic tarde o temprano se ven obligados a aprender el C. No sé tú, pero yo opino que esa razón pesa más. Además, dada la robustez y la aceptación del lenguaje C, se lo ha tomado como referencia para lenguajes de otros propósitos como Java, JavaScript, php o de Matlab, entre otros. Así que, el C podrá servirte para trabajar en otros campos. El programador de C podría, inclusive, aprender luego el Basic sin el menor esfuerzo; lo contrario no es cierto. ¿Qué compilador C utilizar? No quiero burlarme de nadie, pero una vez leí en Internet el comentario de un novato: ―Quiero programar microcontroladores en C. Ya descargué el Visual C++. ¿Qué más necesito?‖ :). Aparte del lenguaje, nada tiene que ver un compilador para ordenadores con los compiladores para µCs. Poco tiene que ver un compilador para PICs que otro para otros µCs. Inclusive, poco tiene que ver un compilador de PICs de una compañía con otro de otra compañía. Veamos grosso modo algunos aspectos de los compiladores de PICs más conocidos. Hi-tech C. Es uno de los compiladores producidos por la empresa htsoft. Es quizá el más eficiente y el que mejor soporta el lenguaje C estándar. Su entorno IDE también incluye el mejor depurador ICD. Como contraparte, su apego al hardware del µC le resta algo de portabilidad. Tampoco luce librerías incorporadas como otros productos. Pero su principal desventaja es su elevado precio. Y, por si fuera poco, el compilador para la familia de partes PIC18 se vende por separado. IAR C. Los compiladores C de la compañía iar systems tienen básicamente las mismas características mencionadas de los compiladores de htsoft, incluyendo sus propios depuradores. Así mismo, las versiones para los PIC16 y PIC18 se distribuyen por separado. Actualmente, no sé por qué, ya no está disponible la primera versión. CCS C. La empresa ccsinfo decidió dotar a sus compiladores C una capa extra que aísla al programador de los recursos intrínsecos del µC. Esto puede afectar la portabilidad de sus códigos a otros compiladores, pero resulta inmejorable, si solo se trabaja en el lenguaje de CCS C, para transportar los códigos de un PIC a otro (de cualquier familia) con un esfuerzo sin comparación. Además, incluye en un solo paquete los compiladores para los PICs de las familias Baseline, Midrange (PIC16 básicamente) y High performance (PIC18). Al igual que los softwares anteriores, sus librerías estándar, como stdlib.h, stdio.h, string.h y math.h, son muy completas y potentes; pero CCS C supera a sus rivales al incorporar librerías para controlar todos los módulos internos del PIC y también muchísimos dispositivos externos. Mikro C. La compañía Mikroelektronika vende compiladores para PICs en los lenguajes C (MikroC), Basic (MikroBasic) y Pascal (MikroPascal). Yo diría que el estilo de Mikro C se parece al de Hi-tech C y sus facilidades tratan de acercarse a las de CCS C: aunque en muchos casos aún es necesario acceder a los

CURSO_MICROS

P á g i n a | 60

registros internos del PIC, cuenta con librerías para controlar sus módulos internos. También tiene una apreciable cantidad de librerías para interfacear dispositivos externos. Lo malo es que todas ellas están precompiladas y no se podrían modificar, en caso de ser necesario. Mikroelektronika y CCS también comercializan sus propias tarjetas de entrenamiento para el aprendizaje de sus productos. Para más información puedes visitar sus sitios web. MPLAB C18. Excelente compilador desarrollado por los ingenieros de Microchip. No es gratuito como el MPLAB, pero creo que es el que ofrece la versión demo más generosa: es 100 % funcional por 60 días. Lamentablemente, como sugiere su nombre, solo trabaja con las partes PIC18. Quizá lo probemos en otro momento. Otros. Aún hay otros compiladores C (como Bytecraft, BoostC y FedC) que algo menos reconocidos como los anteriores, lo que no significa que sean malos. También he visto algunos de código abierto, pero no son buenos: la gente del GNU trabaja más con el AVR GCC, un ―Señor Compilador‖. Es uno de los pocos casos donde el software libre supera a los comerciales. Como se puede entrever, está orientado a los microcontroladores AVR, de Atmel. Es, además, el compilador más difícil de todos; por eso lo estudiaremos en el Módulo 4. En cuanto a cuál compilador usar: la idea de este curso no es aprender a programar con un compilador en particular, y tampoco pretendo promocionar alguno. Después de todo, una victoria depende más de la habilidad guerrero que de su espada. He visto ―super programas‖ hechos con el compilador más modesto. En este Módulo 2 uso BoostC porque es muy fácil, porque nos permitirá ver más de cerca cómo funcionan las cosas dentro del PIC y, sobre todo, porque el salto de él a otros compiladores será mucho más fácil que hacerlo al revés. En el Módulo 3 migraremos al CCS C (que además del lenguaje C usa su propio ―argot‖) y en el Módulo 4 trabajaremos especialmente con AVR GCC. ¡Ánimo! No es tan difícil Pienso que, comparado con el Basic para microcontroladores, el C es infinitamente más difícil de aprender. Quienes lo usan, en gran parte, son personas que han tenido experiencia programando ordenadores, personas que han estudiado más de un libro para dominarlo. Es, literalmente, como aprender un nuevo idioma, y eso no es algo que se hace de la noche a la mañana. ¿Eso no suena muy alentador? Para simplificar las cosas, en este capítulo no voy a exponer todas las reglas del lenguaje C, aunque sí la mayoría; digamos el 95 % de lo necesario. El resto: o es solo aplicable a los PCs, o son temas raros o que difieren demasiado entre de compilador a otro y conviene más revisarlos en sus respectivos manuales. También, y para ahorrar los ejemplos prácticos, asumo que no eres un novato cualquiera, asumo que conoces algo de programación (aunque sea en ensamblador), que sabes cómo usar las subrutinas, que sabes cómo emplear los bucles, que sabes lo que significa redirigir el flujo de un programa, que sabes para qué sirven las variables, etc. Si no, estarás algo perdido.

CURSO_MICROS

P á g i n a | 61

Finalmente, no es necesario que te aprendas de golpe todo el capítulo; bastará con que lo leas fluidamente una primera vez y regresar luego a consultar algunos puntos de duda. La parte más complicada es Arrays y Punteros, sobre todo los punteros. Así que, ten paciencia con ellos. Estructura de un programa en C Tomaremos en cuenta este sencillísimo ejemplo, escrito para el compilador Hitech PICC. #include // Incluir este archivo /* La siguiente directiva establece la Palabra de Configuración */ __CONFIG ( PWRTEN & WDTDIS & XT & UNPROTECT ); void pausa(void) { // Llave de apertura del bloque de pausa unsigned int c; // Declarar variable c (de 16 bits) for(c=0; c b) { a = 0; } if(a == b) { a++; } else { b--; } while( a >= b) { a = a + b; } for(i=0; i b) a = 0; if(a == b) a++; else b--; while( a >= b) a = a + b; for(i=0; i

Desplazamiento a la derecha

Ejemplos: char m; int n;

// variable de 8 bits // variable de 16 bits

m = 0x48; m = m & 0x0F; m = m | 0x24; m = m & 0b11110000; n = 0xFF00; n = ~n; m = m | 0b10000001; m = m & 0xF0;

// m será 0x48 // Después de esto m será 0x08 // Después de esto m será 0x2F // Después de esto m será 0x20 // n será 0xFF00 // n será 0x00FF // Setear bits 0 y 7 de variable m // Limpiar nibble bajo de variable m

CURSO_MICROS

P á g i n a | 75

m = m ^ 0b00110000; // Invertir bits 4 y 5 de variable m m = 0b00011000; // Cargar m con 0b00011000 m = m >> 2; // Desplazar m 2 posiciones a la derecha // Ahora m será 0b00000110 n = 0xFF1F; n = n y

Mayor que


=

Mayor o igual que

. Nota: no debe haber ningún espacio entre el operador y el signo igual. Ejemplos: int a; a += 50; a += 20; a *= 2; a &= 0xF0; a Clock rate. 4000000 significa 4 Mhz.

Establecimiento de la frecuencia del cristal. Ahora sí, todo parece estar preparado para que empecemos a codificar y la barra de estado nos lo debería indicar así.

Barra de estado mostrando los parámetros del proyecto.

CURSO_MICROS

P á g i n a | 101

Sin más, abre el archivo principal del proyecto (LedFlasher.c en nuestro caso) en el editor de código clicando dos veces sobre su nombre en la ventanita Workspace.

SourceBoost IDE con el archivo principal del proyecto en el editor de código. Sobre este boceto podemos terminar de escribir el resto del código del programa o se puede aplicar el bendito copiar – pegar. Como sea, debería quedar como en la siguiente figura.

CURSO_MICROS

P á g i n a | 102

Editor de código con el programa completado. Con el código debidamente escrito, emprendemos la construcción del proyecto como ya sabemos hacerlo: seleccionando el menú Project > Build o, más fácil, presionando el icono de la B gótica. Espera a que termine la construcción. La ventanita Output deberá ir mostrándote los procesos llevados a cabo.

Ventana Output con el reporte de la construcción exitosa. Al final, si la construcción fue exitosa (success ... done), la ventanita Output también debería enviarnos un reporte del uso de la memoria (Memory Usage Report) como se muestra en la imagen de arriba. Allí la ventanita Output está desbocada de su lugar habitual solo para que los mensajes presentados se puedan apreciar mejor. Para comprobar la correcta construcción del proyecto puedes visualizar en el editor de código los archivos resultantes como *.asm, *.lst o el ansiado *.hex.

CURSO_MICROS

P á g i n a | 103

Editor de código mostrando el archivo *.hex. O puedes puedes abrir la misma carpeta del proyecto. Entre otros tantos también podrás hallar allí el archivo *.cof, para la simulación con Proteus VSM.

La carpeta del proyecto conteniendo todos los archivos del proyecto construido. En cambio, si no tuviste ―suerte‖, la ventanita Output te mostrará los errores encontrados. Por ejemplo, un error típico de los noveles suele ser el famoso ―... missing semicolon‖ (―... falta punto y coma‖). Al puro estilo de la ventanita Output del MPLAB IDE, haz doble click en la línea de error para resaltar la línea donde se encuentra ese error.

CURSO_MICROS

P á g i n a | 104

La siguiente imagen muestra la acción descrita, con la ventanita Output desencajada de su lugar habitual para una mejor apreciación del error indicado.

Corrección de los errores hallados. Así se deben ir corrigiendo los errores y volviendo a construir el proyecto hasta que todo salga bien. Cuando hayamos terminado con esta etapa podremos pasar a simular el programa o a grabar el PIC directamente. SourceBoost IDE incluye un nada desdeñable simulador, parecido al MPLAB SIM. De hecho, todos los simuladores son muy parecidos, así que no voy a entrar en detalle sobre ese tema porque ya me cansé de repetir esos conceptos de step over, step into, etc., porque en ese respecto basta con la ayuda del compilador, y porque si tienes Proteus VSM... Ya sabes, no hay simulador que se le compare. (A propósito, los proyectos de BoostC también se pueden construir en el MPLAB IDE y, por tanto, se pueden simular con el MPLAB SIM y depurar con el MPLAB ICD.) Quienes por alguna razón se interesen por el simulador de SourceBoost pueden arrancarlo o detenerlo presionando el botón plugins disponibles en el menú Plugins.

de la barra de herramientas. Hay varios

En la siguiente capura de pantalla la simulación muestra el código ejecutado en dos ventanas: una con el código en C y la otra con el correspondiente código en ensamblador. La vista de código ensamblador se puede alternar con el botón de la barra de herramientas o con la opción de menú View > Code Bar y seleccionando la ficha Assembly. Su contenido puede resultar particularmente interesante para quienes tengan la curiosidad de ver cómo realiza su trabajo el compilador BoostC, ya que muestra sentencia por sentencia de código C con sus correspondientes instrucciones assembler. En realidad, lo mostrado en esta ventana es el contenido del archivo *.casm del proyecto. Por eso también se puede examinar su contenido sin necesidad de estar en modo simulación mediante el botón ya indicado.

CURSO_MICROS

P á g i n a | 105

Simulación del programa en el entorno de SourceBoost. Por otro lado, si estás entre los afortunados que cuentan con Proteus, sabes que el archivo de depuración/simulación a cargar en el PIC es el que tiene extensión .cof (puede varíar en otros compiladores). La ventanita PIC CPU Variables nos muestra los registros y las variables utilizados en el programa. Eso es bueno porque no pasaba así con los archivos *.cof generados por el MPLAB. Sin embargo, aún no es suficiente (al menos hasta la versión que utilicé, la 6.87) por dos razones: Primero, en todo momento aparecen todas las variables utilizadas por el programa. Sería preferible que solo se apreciaran las que son modificadas actualmente para distinguir fácilmente las variables que tienen el mismo nombre (común en los programas en C). Y Segundo, también aparecen los nombres de todos los registros especiales del PIC. Lo ideal sería que solo se vieran los registros utilizados directamente por el código C (para otros casos podríamos sacar la ventana Watch). Por ejemplo, en la siguiente toma de imagen notamos la presencia de los registros tmr0, eedata, indf, etc., que nada tienen que ver con nuestro código C. (Si vamos a buscar defectos en cada compilador que usamos, te aseguro que los vamos a encontrar en todos.)

CURSO_MICROS

P á g i n a | 106

Simulación del programa en Proteus VSM. Con simulación o sin ella, todo proyecto (no me refiero a este ejemplo precisamente) debería terminar con el programa debidamente grabado en el microcontrolador. Claro que no vamos a repetir ahora las cosas que aprendimos en el Módulo 1; es solo que me llamó la atención la posibilidad de SourceBoost de poder invocar a los programadores genéricos como WinPic800. Para que el botón de la barra de herramientas te permita acceder al WinPic800 con el reciente archivo *.hex directamente cargado y listo para ser grabado, debes abrir la ventana del menú Settings > Option... y en el campo Programmer de la ficha Tools establecer la ruta del WinPic800 (o IC-PROG o el software que uses).

CURSO_MICROS

P á g i n a | 107

Configuración de WinPic800 como software de programación. Descripción del programa Los archivos de dispositivo suelen contener los nombres de los registros, de los bits de los registros y de los Bits de Configuración del microcontrolador. Recordemos que en assembler los teníamos que incluir explícitamente, por ejemplo poniendo #include < p16f84a.inc>. Al trabajar con los compiladores en cambio se incluye un archivo genérico, system.h en el caso de BoostC, el cual se encargará de invocar a todos los demás archivos necesarios para la construcción del proyecto, entre ellos el archivo del PIC que se había seleccionado anteriormente desde el IDE (menú Settings > Target...). #include El archivo de dispositivo para este proyecto será PIC16F84A.h. Para examinar éste o cualquier otro archivo que es llamado por system.h, puedes seguirles la pista abriéndolos en el editor mediante el menú contextual después de situar el cursor en el nombre del archivo. Practica eso cuando tengas tiempo. Lamentablemente, los archivos de dispositivo en BoostC usan los nombres de los registros en minúsculas y los nombres de los bits de registros en mayúsculas. Ése sera el primer escollo a superar. Pasemos a otros puntos: directiva #pragma hace lo que dice su comentario. Los nombres de las máscaras de los Fusess de configuración (_PWRTE_ON, etc.) son los mismos que usa el ensamblador. Así que no debería significar mayor novedad. Si no los recuerdas puedes chequear el archivo del dispositivo. La directiva #pragma CLOCK_FREQ 4000000 no es nada parecido a lo que conocemos. Indica la frecuencia del XTAL que utilizará nuestro PIC. El compilador necesita saberlo para poder generar adecuadamente las funciones delay_xx utilizadas en el programa. Obviamente, en nuestro caso 4000000 significa que usaremos un XTAL de 4 MHz. Habrás recordado que esta frecuencia también se puede establecer en el entorno de BoostC. De las dos formas, esta directiva tiene mayor prioridad. Ahora expliquemos el código ejecutable. En un programa puede haber varias funciones y con cualesquiera nombres, pero nunca debe faltar la función main (principal, en inglés). Como habrás podido apreciar en su simulación, ahí es donde empieza a ejecutarse el programa y, de hecho, el control de programa no debería salir de allí. void main(void) { // Cuerpo de la función main // ... } En un programa C para ordenador cuando termina la función main el control pasa al sistema operativo. En un programa para microcontrolador no hay S.O. Así que no debería terminar. Por eso se suele poner algún bucle infinito para que el programa se quede dando vueltas para siempre. Por ejemplo:

CURSO_MICROS

P á g i n a | 108

while(1) // Bucle infinito { // Bloque (o cuerpo) del bucle while // ... } Éste es un bucle while, que ejecutará un bloque de instrucciones mientras la expresión entre los paréntesis indicados sea verdadera. En este caso, dicha expresión es 1. Una expresión de este tipo es verdadera si es diferente de 0 y como 1 siempre será diferente de 0, el cuerpo del bucle se ejecutará una y otra vez, indefinidamente, forever, hasta el ―infinito‖... La sentencia de llamada a función delay_ms(200) genera un delay de 200 ms (¡qué descubrimiento!). Por desgracia, el valor máximo admisible es de 255. Eso lo puedes comprobar revisando su prototipo de función en el archivo boostc.h, abriéndolo de la forma indicada antes. delay_ms(200);

// Pausa de 200ms

Habrás notado que para acceder a un registro ya no es necesario cambiar a su banco de ubicación. Todas las labores de cambio de banco y de página las realizará el compilador. Tampoco hace falta enmarcar en una sección teorica aparte el significado de los prefijos 0x y 0b para descubrir que indican números en formato hexadecimal y binario, respectivamente. Los números sin prefijos son tratados por el compilador como decimales, como lo entenderíamos nosotros; por ejemplo, 1000, +200, 0, -35, etc. Práctica 2 En ensamblador solíamos redirigir el flujo de un programa utilizando instrucciones de salto como el goto. Aunque en C también existe una sentencia goto, que hace casi lo mismo, su uso está sensurado por las buenas prácticas de programación. Si algún programador respetable viese un goto injustificado en tu programa, se reiría de él. Las formas de hacer estas operaciones es mediante las sentencias de control de programa como if (y similares), while, for, etc. El programa enciende un LED más de los ocho conectados al puerto B cuando se presiona un botón, y apaga otro LED más cuando se pulsa otro botón.

CURSO_MICROS

El Circuito

El circuito. El código fuente

//**************************************************************************** // FileName: OnOffLEDs.c // Processor: PIC16F84A // Compiler: BoostC // Purpose: Operadores, sentencia if, bucle while. //**************************************************************************** #include #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _PWRTE_ON #pragma CLOCK_FREQ 4000000 void main() { char t = 0; // Declarar variable t e inicializarla a 0 trisa.4 = 1; // Pin RA4 entrada trisa.3 = 1; // Pin RA3 entrada trisb = 0x00; // PORTB como salida portb = 0x00; // Limpiar PORTB while(1) // Bucle infinito { if (porta.4==0) // Si RA4 vale 0, ejecutar sig, bloque { t = 1; // Desplazar t a la derecha t &= 0x7F; // Limpiar bit 7 de t portb = t; // Colocar en PORTB delay_ms(40); // Delay antirrebote while(porta.3==0) // Mientras RA3 valga 0, esperar continue; } } } Descripción del programa El cuerpo de la sentencia while(1) tiene dos sentencias if. Cada sentencia if a su vez tiene varias sentencias más. Así son los programas en C, sentencias conteniendo sentencias y más sentencias. Las sentencias if del programa comparan los bits RA4 y RA3 de PORTA con 0. Valdrán 0 cuando los botones en dichos pines estén pulsados. Claro que sabemos cómo funciona todo eso. Mi punto era este: podemos leer una expresión con el operador == diciendo ‗igual‘; por ejemplo: if (porta.4==0)

// Si RA4 vale 0, ejecutar sig, bloque

se leería ―si el bit 4 de PORTA es igual a 0, entonces...‖. Sin embargo, no debemos confundirlo con el operador =, que transfiere el valor de un dato, variable o una expresión a otra variable. Suele ser un error frecuente en los diseñadores noveles no detectable fácilmente porque el compilador no dará errores. Por ejemplo, esta expresión también es totalmente válida: if (porta.4 = 0)

// Si RA4 igualado a 0 es diferente de 0...

Significa que primero se asigna el valor 0 al bit 4 de PORTA y después se comprueba si ese valor es verdadero. Por supuesto que nunca lo será. Sigamos con más operadores. t 0,...

Pero a los programadores de C nos da pereza tipear más código de lo necesario. Quizá este estilo te disguste en un inicio pero pronto estarás de acuerdo con nosotros. No lo olvides: una expresión no relacional simple es verdadera si vale diferente de 0 y es falsa cuando vale 0. El tercer tema era el array Code7seg. Esta forma de declarar los Arrays constantes, con la palabra reservada rom y el asterisco, es propia del compilador BoostC; así que no le busquemos mayor lógica porque va a variar en otro compilador. rom char * Code7seg = // Array constante almacenado en rom (FLASH) { 0b00111111, // 7-segment code of 0. Format: 0bxgfedcba , x=don‘t care // ... 0b01110001, // 7-segment code of F }; Nota que los elementos deben ir separados por comas; de modo que no es necesario que vaya uno por cada línea. Lo escribí así solo para que se distingan mejor. Lo que no debería variar en ningún compilador C es el acceso a los elementos del array, mediante corchetes e índices. Así la sentencia portb = Code7seg[Count]; envía al puerto B el elemento número Count del array Code7seg. En C el primer elemento siempre es el 0.

CURSO_MICROS

P á g i n a | 115

Finalmente, pasemos al cuarto punto: el tipo de dato ideado para trabajar con números enteros en el C estándar es int (entero de 16 bits con signo, suficiente para alojar la gran mayoría de los datos procesados en un programa). Sin embargo, en el mundo de los µCs la RAM no es un recurso que se caracterice por abundar. Es por eso que se muchas veces se suele usar el tipo char, que fue inicialmente concebido para almacenar caracteres (characters) ascii (de 8 bits), como ‗a‘, ‗5‘, ‗#‘, etc. A este tipo se le han añadido los especificadores signed (con signo) y unsigned (sin signo) para formar los tipos: 

signed char establece variables enteras de 8 bits con signo (desde –128 hasta +127).



unsigned char establece variables enteras de 8 bits sin signo (desde 0 hasta 255).

char también se puede usar para almacenar números, pero funcionará ambiguamente, a veces como signed char y otras como unsigned char, según el compilador entre otras cosas. Si los datos usados en el programa no requieren formato, se podrán usar los tres tipos indistintamente sin que funcione mal y sin que el compilador ―se dé cuenta‖. Sin embargo, si las variables van a trabajar como números en operaciones aritméticas o relacionales de comparación, será necesario aplicarles el signed o unsigned respectivo. PRÁCTICA 4 Descripción del programa Este programa tiene dos funciones: main (infaltable) y Flash, para la que no fue necesario escribir su prototipo de función porque la puse encima de main. Tratemos esta extraña construcción: for(;;) // Bucle for sin condiciones (infinito) { // Bloque o cuerpo del bucle for // ... } El bucle for ejecuta un bloque de sentencias según ciertas condiciones que contiene entre los paréntesis. En este programa esas condiciones no existen, lo que para el compilador significa que es un bucle infinito, justamente igual que nuestros anteriores while (1). Se suele usar una u otra forma indistintamente. Ahora veamos los bucles for que sí tienen límites, pero antes quiero que sepas porque uso for y no los bucles while o do-while, que en un inicio pueden ser los más simples. Cuando uno tiene un enunciado que describe alguna forma de conteo, de inmediato debe pensar en el bucle for. Así, cuando yo entendí que para que el LED se desplace de uno a otro lado debe recorrer 8 posiciones, de inmediato imaginé un bucle de la forma for(i=0; i 1200 ns lcd_E = 1; // Habilitar LCD delay_us(2); // Data Delay Time > 1320 ns low = lcd_DBUS; // Leer nibble bajo lcd_E = 0; return (high&0xF0)|(low>>4); // Juntar nibbles leídos } //**************************************************************************** // Envían cadenas ROM/RAM terminadas en nulo al LCD. //**************************************************************************** void lcd_puts(rom char * s) { unsigned char c, i=0; while(c = s[i++]) lcd_write(c, 1); // Instrucción ‗Write Data to DDRAM/CGRAM‘ } void lcd_puts(char * s) { unsigned char c, i=0; while(c = s[i++]) lcd_write(c, 1); // Instrucción ‗Write Data to DDRAM/CGRAM‘ } //**************************************************************************** // Ubica el cursor del LCD en la columna c de la línea r. //**************************************************************************** void lcd_gotorc(char r, char c) { if(r==1) r = LCD_LINE1; else r = LCD_LINE2; lcd_write(r+c-1, 0); // Instrucción ‗Set DDRAM Address‘

CURSO_MICROS

} //**************************************************************************** // Limpia la pantalla del LCD y regresa el cursor a la primera posición // de la línea 1. //**************************************************************************** void lcd_clear(void) { lcd_write(LCD_CLEAR, 0); // Instrucción ‗Clear Display‘ } //**************************************************************************** // Envían instrucciones de comando y de datos al LCD. //**************************************************************************** void lcd_cmd(char com) { lcd_write(com, 0); // Cualquier instrucción de comando } void lcd_data(char dat) { lcd_write(dat, 1); // Instrucción ‗Write Data to DDRAM/CGRAM‘ } /////////////////////////////////////////////////////////////////////////////// // File Name: lcd.h // Processor: Todos los PICmicros // Compiler: BoostC // Author: Shawn Johnson /////////////////////////////////////////////////////////////////////////////// #include //**************************************************************************** // Configuración de los pines de interface //**************************************************************************** #define lcd_DBUS portb // Data Bus (RB4-DB4,...,RB7-DB7) #define lcd_DBUStris trisb // #define lcd_E #define lcd_Etris

portb.3 // Pin Enable trisb.3 //

#define lcd_RW portb.2 // Pin Read/Write #define lcd_RWtris trisb.2 // #define lcd_RS portb.1 // Pin Register Select #define lcd_RStris trisb.1 // //**************************************************************************** // Códigos de comando usuales //**************************************************************************** #define LCD_CLEAR 0x01 // Limpiar Display #define LCD_RETHOM 0x02 // Cursor a inicio de línea 1 #define LCD_LINE1 0x80 // Línea 1 posición 0 #define LCD_LINE2 0xC0 // Línea 2 posición 0 #define LCD_DDRAM 0x80 // Dirección 0x00 de DDRAM

P á g i n a | 128

CURSO_MICROS

#define #define #define #define #define

P á g i n a | 129

LCD_CGRAM 0x40 // Dirección 0x00 de CGRAM LCD_CURSOR 0x0E // Mostrar solo Cursor LCD_BLINK 0x0D // Mostrar solo Blink LCD_CURBLK 0x0F // Mostrar Cursor + Blink LCD_NOCURBLK 0x0C // No mostrar ni Cursor ni Blink

//**************************************************************************** // Prototipos de funciones //**************************************************************************** void lcd_init(void); // Inicializa el LCD void lcd_puts(rom char * s); // Envía una cadena rom al LCD void lcd_puts(char * s); // Envía una cadena ram al LCD void lcd_gotorc(char r, char c); // Cursor a fila r, columna c void lcd_clear(void); // Limpia el LCD y regresa el cursor al inicio void lcd_data(char dat); // Envía una instrucción de dato al LCD void lcd_cmd(char com); // Envía una instrucción de comando al LCD char lcd_read(char RS); // Lee un dato del LCD void lcd_write(char inst, char RS); // Escribe una instrucción en el LCD void lcd_nibble(char nibble); Práctica 1 “Hellow World” Mostrar un mensaje de ―Hellow World‖ en el LCD es un programa casi tan trillado como hacer parpadear un LED. El circuito

La inteface entre el LCD y el PIC depende en gran medida de la librería usada. En nuestro caso, en lcd.h se configura por defecto una conexión como la mostrada en este esquema. Luego veremos cómo modificar parte de esta interface.

CURSO_MICROS

P á g i n a | 130

El pin Vss (o Vo) del LCD establece el contraste de la pantalla. Muchas veces se prefiere quitar el potenciómetro y conectar Vss a tierra para fijar el máximo contraste. En los siguientes circuitos haremos algo parecido. El código fuente El programa se compone de tres archivos: el principal, cuyo listado se muestra en seguida, y lcd.c junto con lcd.h. Nota que la directiva solo señala el segundo. //**************************************************************************** // FileName: HelloWorld.c // Processor: PIC16F84A // Compiler: BoostC // Purpose: LCD - Visualización de texto //**************************************************************************** #include #include ―lcd.h‖ // Incluir librería de LCD #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _PWRTE_ON #pragma CLOCK_FREQ 4000000 void main(void) { lcd_init(); // Inicializar LCD while(1) { lcd_gotorc(1,7); // Cursor a fila 1 posición 7 lcd_puts(―Hello‖); // Escribir Hello lcd_gotorc(2,7); // Cursor a fila 2 posición 7 lcd_puts(―World‖); // ... delay_s(1); // Pausa de 1 segundo lcd_clear(); // Limpiar pantalla delay_s(1); // ... } } Descripción del programa Obviamente, la primera función a llamar debería ser lcd_init. Tras ejecutarse el LCD debe quedar inicializado, con la pantalla limpia y con el cursor en el primer casillero. El LCD tiene un cursor que, si bien puede mostrarse en pantalla, suele configurarse para que permanezca oculto. Bien, visible o no, el cursor avanza automáticamente tras cada letra que se escribe. Por ejemplo, luego de escribir ―Hello‖ el cursor queda apuntando al casillero 13 de la primera fila. La función lcd_gotorc sirve para mover el cursor a la posición deseada. A las tres funciones vistas en este ejemplo solo bastaría sumarle lcd_data, que escribe una sola letra en el LCD, para realizar la gran mayoría de las aplicaciones. Aun así, ocasionalmente también usaremos lcd_cmd, para escribir comandos alternativamente. Por ejemplo:

CURSO_MICROS

P á g i n a | 131

lcd_cmd(LCD_LINE2); // Mover cursor al inicio de línea 2 lcd_cmd(LCD_CLEAR); // Limpiar pantalla lcd_cmd(LCD_CURBLK); // Mostrar Cursor + Blink lcd_cmd(LCD_CURSOR); // Mostrar solo Cursor lcd_cmd(LCD_CGRAM+16); // Mover Puntero de RAM a dirección 16 de la CGRAM Las constantes LCD_CLEAR y otras más se hallan definidas en el archivo lcd.h. Por cierto, no deberías tocar lcd.c para nada, salvo que por alguna razón bien pensada quieras modificar el código. El cambio más frencuente a realizar puede ser la configuración de los pines de interface entre el LCD y el PICmicro. Eso se hace en el archivo lcd.h, en la sección indicada. //**************************************************************************** // Configuración de los pines de interface //**************************************************************************** #define lcd_DBUS portb // Data Bus (RB4-DB4,...,RB7-DB7) #define lcd_DBUStris trisb // #define lcd_E #define lcd_Etris

portb.3 // Pin Enable trisb.3 //

#define lcd_RW portb.2 // Pin Read/Write #define lcd_RWtris trisb.2 // #define lcd_RS portb.1 // Pin Register Select #define lcd_RStris trisb.1 // Aquí tenemos cuatro pares de directivas. El primero establece el puerto del PICmicro que dará con el bus de datos del LCD. Como solo se toma el nibble alto, en el PIC16F84A no hay otra alternativa que el puerto B. El puerto A no tiene nibble alto completo, tendríamos que editar el archivo lcd.c. Los tres pares restantes definen la conexión de las líneas E, RS y RW del LCD. Esto es pin a pin, así que se pueden tomar cualesquiera pines libres del PIC. (RA4 necesitaría de una resistencia de pull-up.) Práctica 2 Visualización de números Los LCDs solo entienden de caracteres alfanuméricos y algunos otros, pero no saben reconocer números. En esta práctica veremos cómo hacerlo. El circuito De ahora en adelante, en vez del potenciómetro, colocaremos un diodo 1N4148 en el pin Vee para fijar la tensión (Vdd-Vee) a cerca de 4.3 V. En la mayoría de los LCDs este valor brinda un muy aceptable nivel de contraste de la pantalla.

CURSO_MICROS

El código fuente //**************************************************************************** // File Name: lcdNum.c // Processor: PIC16F84A // Compiler: BoostC // Purpose: LCD - Visualización de números //**************************************************************************** #include #include // Contiene la función itoa,... #include ―lcd.h‖ #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _PWRTE_ON #pragma CLOCK_FREQ 4000000 void main(void) { char buff[10]; // Array de 10 elementos tipo char int i = 0; // Variable i inicializada a 0 lcd_init(); // Inicializar LCD lcd_puts(―cursomicros.com‖); for(;;) { lcd_gotorc(2,4); // Cursor a fila 2 posición 2 itoa(i, buff, 10); // Convertir i en cadena texto lcd_puts(buff); // Enviar buffer a LCD lcd_gotorc(2,10); // Cursor a fila 2 posición 10 itoa(i, buff, 16); // Convertir i en texto, base 16 lcd_puts(buff); // Enviar buffer a LCD

P á g i n a | 132

CURSO_MICROS

i++; delay_ms(250); delay_ms(250); } }

P á g i n a | 133

// Incrementar i // Pausa

Descripción del programa La función lcd_puts recibe como parámetro un array de tipo char, que en su forma más usada sería una cadena texto. Puede que te hayas fijado en la existencia de dos funciones lcd_puts en la librería del LCD. Ésa es una característica conocida como sobrecarga de funciones o polimorfismo. El compilador sabe a cuál de las dos llamar basándose en el tipo de parámetro que se les envíe. Por ejemplo, en el primer caso, lcd_puts(“cursomicros.com”), llamará a la lcd_puts que recibe como parámetro una cadena constante, porque así he diseñado la librería. Por otro lado, no siendo buff un array constante, en el caso de lcd_puts(buff) se llama a la lcd_puts que recibe arrays en ram. Como sea, esas decisiones las tomará el compilador y nosotros nos dejamos de preocupar. Para visualizar números en el LCD primero debemos convertirlos en cadenas de texto. La función itoa (acrónimo de Integer TO Ascii) puede hacerlo. Es una función incorporada en el C estándar y que también la implementan muchos compiladores para microcontroladores, aunque con variaciones en los parámetros que recibe. Podemos hallar itoa y otras funciones análogas en la librería estándar sdtlib.h. En muchos casos solo se mostrarán los encabezados de las funciones (porque suelen estar precompiladas o implementadas a nivel ensamblador). El siguiente es el encabezado de itoa en BoostC: char* itoa( int val, char* buffer, unsigned char radix ); Es fácil deducir que el primer parámetro es el número a convertir; el segundo es el buffer donde nos devolverá la cadena de texto y el tercero es la base del número. En el programa hemos puesto 10 y 16 en el tercer parámetro porque queremos visualizar el número en formato decimal y luego en hexadecimal. (También podría ser, binario u otro) sdtlib.h de BoostC también contiene funciones como atoi (que realiza la tarea inversa a itoa), entre otras, pero, sigue siendo bastante limitada comparada con las sdtlib.h de algunos otros compiladores. Práctica 3 Caracteres gráficos en LCD La creación de caracteres gráficos puede ser un tema superfluo. Aun así, suponiendo que no faltarán algunas personas obsesivas como yo, que siempre quieren saberlo todo, he preparado esta práctica para cerrar el capítulo. Hagamos un poco de memoria. Cuando enviamos el código de un carácter alfanumérico a la DDRAM del LCD, su chip interno buscará en la CGROM el patrón correspondiente y luego lo visualizará en la pantalla. Así se escriben todos textos (y así hemos trabajado hasta ahora).

CURSO_MICROS

P á g i n a | 134

Ahora bien, si el código enviado vale entre 0x00 y 0x07 (o 0x08 y 0x0F), el chip interno buscará su patrón de visualización en la CGRAM. Siendo ésta una RAM de lectura/escritura, podemos programar en ella los diseños que se nos ocurran.

Mapa de memoria para la creación de nuevos caracteres. La CGRAM (Character Generator RAM) consta de 64 bytes en los que se pueden escribir los patrones de 8 nuevos caracteres de 5×7 puntos ó 4 caracteres de 5×10 puntos. Aquí veremos el primer caso. Cuando los caracteres son de 5×7 puntos los 64 bytes se dividen en 8 bloques de 8 bytes cada uno, y cada bloque almacena el patrón de un nuevo carácter. El esquema mostrado arriba indica que: 

El primer bloque de CGRAM, con direcciones desde 0b00000000 hasta 0b00000111, corresponde al código 0x00 (ó 0x80) de la DDRAM.



El segundo bloque CGRAM, con direcciones desde 0b00001000 hasta 0b00001111, corresponde al código 0x01 (ó 0x88) de la DDRAM; y así sucesivamente.

CURSO_MICROS

P á g i n a | 135

Por ejemplo, la figura de arriba indica que se han rellenado los dos primeros bloques con los patrones de dos pacmans. Hasta ahí solo se han creado dos nuevos caracteres. Para mostrarlos en el LCD habría que escribir un código así: lcd_data(0x00); lcd_data(0x01);

// Visualizar primer pacman // Visualizar segundo pacman

Pasando a la práctica en sí: como parte de su funcionalidad el LCD tiene instrucciones para desplazar lo mostrado en la pantalla hacia un lado u otro. Puede parecer interesante, pero sus limitaciones llevan a muchos a realizar esos efectos mediante rutinas software. Pues es lo que haremos en esta práctica, mostrar por el LCD un mensaje que pasa como una marquesina, y como nuevo carácter pondremos a un pacman glotón que en la esquina inferior izquierda. El circuito

El código fuente //**************************************************************************** // FileName: Pacman.c // Processor: PIC16F84A // Compiler: BoostC // Purpose: LCD - Creación de caracteres gráficos personalizados //**************************************************************************** #include #include ―lcd.h‖ #pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _PWRTE_ON

CURSO_MICROS

P á g i n a | 136

#pragma CLOCK_FREQ 4000000 /* Definiciones */ #define LCD_LEN 16 // Para LCD de 2×16 #define PacOpen 0x00 // Indentificador de carácter nuevo #define PacShut 0x01 // Indentificador de carácter nuevo void main(void) { unsigned char j; // Índice relativo unsigned char i; // Índice base char c; rom char * PattOpen = {0x0F,0x1C,0x18,0x10,0x18,0x1C,0x0F,0x00}; // Pattern rom char * PattShut = {0x00,0x0E,0x1F,0x10,0x1F,0x0E,0x00,0x00}; // Pattern rom char * Taine = ― \‖EL HAMBRE PRODUCE POEMAS INMORTALES. \ LA ABUNDANCIA, SOLAMENTE INDIGESTIONES Y TORPEZAS\‖ ―; lcd_init(); /* Crear dos nuevos caracteres (los pacman‘s) en la CGRAM */ lcd_cmd(LCD_CGRAM); // Instrucción Set CGRAM Address for (i=0; i