Descargar

Construcción de robots a bajo costo. Programación de microcontroladores


  1. Objetivo
  2. Includes
  3. Configuración de algunos PIC
  4. USART
  5. Conexiones
  6. Envío: MASTER
  7. Recepción: SLAVE
  8. Envío: SLAVE
  9. Recepción: MASTER
  10. Interrupciones
  11. Detalles de Assembler
  12. Bibliografía y referencias

El presente documento procura mostrar como utilizar algunas características importantes de los microcontroladores PIC de la empresa Microchip, en un lenguaje accesible y basado en ejemplos de modo de complementar en parte las hojas de datos. Conjuga códigos de ejemplo y comentarios sobre distintas funcionalidades haciendo referencia al proyecto de grado: Construcción de Robots a Bajo Costo.

Objetivo

El objetivo del documento es reunir características importantes de la programación de PICs en el lenguaje C o en Assembler.

Se describirá el uso del USART (Universal Synchronous Asynchronous Receiver Transmitter), el i2C, las interrupciones, los timers y otras funcionalidades. Si bien la forma de usar estas facilidades de los PIC se explica en las hojas de datos, se ha encontrado algo de dificultad en entenderlos, se intentará facilitar las cosas en el documento dando ejemplos de código y seudo código, mostrando algunos detalles importantes que hay que tener en cuenta a la hora de utilizar los microcontroladores.

Todo lo que sigue tiene como fuente principal las hojas de datos de los PIC que se usaron, y las pruebas realizadas. En ninguna prueba se tuvo éxito en el primer intento, aún siguiendo al pie de la letra lo que indican las hojas de datos. Algunas veces no se entendió bien, otras las indicaciones de las hojas de datos no fueron lo especificas o completas que se esperaría, así que para hacer funcionar cada situación fueron necesarias muchas horas de pruebas, los resultados se documentan en las secciones siguientes. Esto no significa que no existen otras formas de hacer funcionar cada característica, muestra como se hicieron funcionar para el proyecto.

El documento se basa en las experiencias con el compilador HI-TECH PICC Compiler en su versión PICC Lite, versión estudiantil y el MPASM assembler de Microchip. Cabe aclarar que no es un documento introductorio porque asume que el lector tienen algún conocimiento de microcontroladores y programación (se recomienda leer el documento [LM2004A] Funcionamiento de microcontroladores) por otro lado tampoco es profundo, dado que no agota ninguno de los temas que considera. En general se hacen referencia a funcionalidades que se encuentran en PICs de la gama media de Microchip, en particular el 16F628, 16F876A y 16F877A.

El documento esta enmarcado en el conjunto de documentos relacionados con el proyecto de grado "Construcción de robots a bajo costo" por lo que se hará referencia a dicho proyecto en los casos en que se pueda, con el fin de tener una referencia concreta a implementaciones de las funcionalidades descritas, de esta forma el lector tendrá donde ver códigos y arquitectura que ejemplifiquen la utilización de las funcionalidades mas allá de los ejemplos del documento.

Includes

#include

Cuando se programa utilizando el MPLab, al elegir el modelo de PIC para el que se va a compilar, el IDE genera la línea de compilación incluyendo este modelo. Con esta bandera seteada y la inclusión de la biblioteca es suficiente para que a su vez se incluya la biblioteca picXX.h (siendo XX el modelo del PIC).

Código ejemplo:

#include

Colocar este include permite manejar el conjunto de nombres de registros y bits, haciendo mucho más intuitiva la programación, y sobre todo más entendible la posterior lectura de código (en las secciones siguientes se mencionaran registros según sus nombres en estas bibliotecas), por ejemplo: a partir de la inclusión de estas bibliotecas se puede usar el nombre PORTA en lugar de la dirección de memoria 05h, y el TRISA en lugar de 85h (esta biblioteca es en realidad un gran conjunto de defines).

#include

Utilizando el MPASM Assembler también es posible incluir bibliotecas que permiten nombrar registros, aunque no existe la facilidad de incluir una sola, por lo que es necesario incluir la que corresponde al microcontrolador en cuestión.

Código ejemplo:

#include

Existen muchas bibliotecas disponibles para incluir, aunque hay que considerar que tanto el lenguaje C como el assembler son exclusivos para estos microcontroladores, por lo tanto no se puede incluir cualquier biblioteca. Por otro lado el C sigue el estándar de ANSI casi completamente, a menos de algunas macros y el tipo de dato bit (en PICC existe el tipo de dato bit), así como el tratamiento de la rutina de interrupción (en PICC existe una sola rutina de interrupción).

Algunas bibliotecas disponibles para ser incluidas se encuentran en los directorios c: PICCLITEinclude y en c:PICCLITEsamples en una instalación estándar del compilador PICC Lite, y en el directorio C:Program FilesMPLAB IDEMCHIP_Tools en una instalación estándar del MPLab (este incluye el ensamblador y el linkeditor).

Configuración de algunos PIC

La configuración de un microcontrolador refiere a como se setean algunas de sus características al momento en que el microcontrolador inicia su ejecución, por ejemplo: el tipo de reloj y frecuencia con que va a trabajar, la habilitación del watchdog (timer que resetea el microcontrolador) y la protección del código entre otras.

Esta configuración no tiene que ver con el lenguaje en el que se programe aunque si con el modelo de microcontrolador (por ejemplo: la palabra en memoria de configuración del PIC 16F628 tiene poco en común con la del PIC 16F877).

Configurar un PIC significa establecer la palabra de configuración en tiempo de carga del programa, único momento en que se puede acceder a la dirección 2007h (dirección donde se guarda la configuración). Esta palabra determina el funcionamiento del PIC.

Ejemplos de configuración para el PIC 16F877A

Configuración de un microcontrolador PIC 16F877A programado con el lenguaje PICC versión Lite que incluye la librería pic.h.

Código ejemplo :

__CONFIG( HS & WDTDIS & PWRTEN & BORDIS & LVPDIS & DUNPROT & UNPROTECT );

Ejemplos de configuración para el PIC 16F628

Configuración de un microcontrolador PIC 16F628 programado en Assembler que incluye la librería p16F628.inc

Código ejemplo :

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF & _PWRTE_ON

USART

Universal Synchronous Asynchronous Receiver Transmitter. También se conoce como SCI (Serial Communications Interface).

El módulo USART de los microcontroladores PIC permite la comunicación con otros microcontroladores, memorias eeproms, PC, etc, utilizando tanto un modo asincrónico (pudiendo ser full duplex) o sincrónico ( master o slave, half duplex).

Permite enviar 8 o 9 bits por transmisión y tiene posibilidad de alcanzar varias velocidades de transmisión, siendo lo mas importante, que por ser una funcionalidad integrada al PIC, el programador logra desentenderse de toda la complejidad del protocolo a nivel de capa 1 y es suficiente con poner un dato en un registro del microcontrolador para enviar y leer otro registro para recibir.

Si bien existen varios protocolos relacionados con la sincronización de la comunicación USART como el RTS/CTS o el XON/XOFF, los microcontroladores PIC de gama media no los implementan, para utilizarlos hay que programarlos utilizando algún par de pines disponibles.

En un PIC 16F87XA los pines que son utilizados por la funcionalidad integrada USART son el RC6/TX y el RC7/RX. En un PIC 16F62X los pines que son utilizados por la funcionalidad integrada USART son el RB1/RX y el RB2/TX.

Estos pines tienen que estar configurados como entrada (puestos en 1 en los registros TRIS correspondientes).

En las siguientes secciones se describirá como se utiliza el USART en modo asincrónico con transmisiones de 8 bits.

Cuando se utiliza el lenguaje PICC en su versión Lite, existen rutinas para el uso y gestión del USART que se encuentran en el archivo sci.h, ubicado en el directorio C:PICCLITE samplesusart en una instalación estándar. Para utilizar el módulo en Assembler se deben utilizar los registros de la misma forma en que se usan en C a bajo nivel. A pesar de que se cuenta con la biblioteca sci.h, se describirá el funcionamiento y uso del módulo USART a mas bajo nivel, dado que puede ser necesario cambiar esta biblioteca. En particular para el proyecto se hicieron cambios para integrar controles de tiempos (se agregaron timers para controlar que si pasado cierto tiempo no llega un dato se devuelva error), es decir se hicieron rutinas bloqueantes con timeout.

Registros que intervienen

Registro TXSTA

Transmit Status and Control Register (Registro de estado y control de transmisión) .

Incluye:

CSRC selecciona la fuente de reloj (interna, externa).

TX9 habilita transmisiones de 8 o 9 bits.

TXEN habilita transmisión.

SYNC selección de modo (sincrónico, asincrónico).

BRGH complementa el control en la generación de baudios.

TRMT bit de estado del Transmit Shift Register

TX9D noveno bit de transmisión de datos.

Registro RCSTA

Receive Status and Control Register (Registro de estado y control de recepción) .

Incluye:

SPEN bit de habilitación del puerto serial.

RX9 setea recepción de 8 o 9 bits.

SREN bit de habilitación de recepción simple.

CREN bit de habilitación de recepción continua.

ADDEN bit de habilitación de detección de dirección.

FERR bit bandera de error de framing.

OERR bit de error por sobreescritura.

RX9D noveno bit de recepción de datos.

Registro SPBRG

Genera los pulsos, el reloj de la transmisión. Existe un timer independiente de 8 bits que decrementa hasta 0 a partir del valor de este registro. Dependiendo de la velocidad de transmisión que se quiera conviene setear en 0 o 1 el BRGH, y dependiendo de este es el valor que se setea en el SPBRG (ver figura 10-3 y 10-4 de la hoja de datos del pic16F87X).

Registro PIE1

Incluye:

TXIE habilita interrupciones por transmisión de USART

RCIE habilita interrupciones por recepción de USART

Registro PIR1

Incluye:

TXIF bandera que indica que se enviado por USART

RCIF bandera que indica que se ha recibido por USART

Registro TXREG

Registro que se debe escribir con el dato a enviar por USART.

Registro RCREG

Registro que se debe leer al recibir un dato por USART.

Modo de uso

Inicialización

Inicialmente es necesario hacer una serie de seteos para que pueda usarse el modo USART, esto incluye definir a que velocidad se va a transmitir, el modo (sincrónico / asincrónico), con interrupciones, etc.

Código ejemplo:

// Inicialización

SPBRG = 129; // setea la velocidad de transmisión en 2.4 Kbps.

BRGH = 1; // complemento del seteo del baud rate.

SPEN = 1; // habilito el uso del puerto serial.

SYNC = 0; // seleccino el modo asincrónico.

CREN = 1; // recepción continua habilitada.

TXIE = 0; // deshabilito interrupciones por transmisión completada.

RCIE = 0; // deshabilito interrupciones por recepción.

TX9 = 0; // setea transmisión de 8 bits.

RX9 = 0; // setea recepción de 8 bits.

TXEN = 1; // transmisión habilitada.

Envío de datos

Para enviar por USART se carga el registro TXREG, esto es suficiente para que el módulo se ponga a trabajar, cuando se termine de enviar se levanta la bandera TXIF.

Código ejemplo:

//Envío

while(!TXIF) // el TXIF se pone en 1 cuando se termino de enviar.

continue;

TXREG = byte;

// TXIF es puesto en 0 por hardware cuando se carga el TXREG.

Recepción de datos

Para recibir por USART se controla la bandera RCIF que se pondrá en 1 cuando llegue un dato. Luego se puede leer el dato en el RCREG.

Código ejemplo:

//Recibir

while (!RCIF)

continue;

data_1 = RCREG;

// RCIF es puesto a 0 por el hardware luego de la lectura de RCREG.

Detección de errores

El OERR es el bit de overrun y se pone en 1 cuando se intentan mandar 3 palabras y el receptor no ha leído ninguna de las 2 primeras, la tercer palabra se pierde.

Debe ser reseteado en software borrando y seteando el CREN.

Código ejemplo:

if(OERR){

CREN = 0;

CREN = 1;

// hacer lo que corresponde

}

El FERR es el bit de framing error y se pone en 1 cuando hay un error en la forma del frame que llega. El valor del FERR debe ser leído antes de leer el RCREG, esta lectura lo sobrescribe.

Conexiones

Para comunicar 2 PIC utilizando el USART, es suficiente con conectar los pines RX y TX cruzadods, es decir el pin TX del pic1 conectada con el pin RX del pic2 y el pin RX del pic1 con el pin TX del pic2. Dado que los 2 PIC utilizan los mismos voltajes (la norma TTL) no hay que hacer mas cambios.

Por otro lado si se quiere comunicar un PIC con un PC utilizando el puerto serie con la norma RS232, hay que tener en cuenta que esta norma utiliza voltajes distintos para representar el 1 y el 0 que los microcontroladores. Por lo tanto será necesario pasar tanto el TX como el RX por un módulo convertidor de voltajes del tipo Maxim max232A o el utilizado en el proyecto un ICL232.

Excepto por el ICL232 no hay mas diferencias entre comunicar 2 PIC o un PIC y un PC, sin embargo es necesario considerar que un PIC tiene un buffer de 1 posición y el PC tiene un buffer mucho mayor (depende de la configuración, usualmente 1024 bytes), para una transmisión de varios bytes del PC al PIC puede ser necesario establecer algún tipo de protocolo de sincronización.

I2C

El I2C es uno de los dos modos que tiene el MSSP (Master Synchronous Serial Port), módulo que tienen integrados algunos microcontroladores PIC de la gama media de Microchip como el 16F877A que se utiliza en el proyecto. El otro modo es el SPI (Serial Peripheral Interface).

I2C es un bus de comunicaciones, un canal al que se pueden conectar entidades que hablen el protocolo. Esta sola característica hace que los sistemas que lo utilizan sean inherentemente extensibles. Su implementación electrónica es tan simple como tener 2 cables conectados a resistencias pull-up y todos las entidades que pretendan utilizar el bus deberán estar conectadas a dichos cables.

Existen un ambiente multimaster con detección de colisiones (modo de funcionamiento en el que pueden haber varios master) y otro ambiente en que existe un solo microcontrolador con el rol de MASTER (modo utilizado en el proyecto). Siempre existe la relación maestro esclavo entre las entidades conectadas y siempre un master controla el bus.

Se permite un direccionamiento de entidades en el bus de 7 o 10 bits. Para el proyecto se utiliza el de 7 bits y se transmiten palabras de 8 bits en todos los casos.

En general el funcionamiento es el siguiente, todos los dispositivos conectados al bus tienen una dirección, el master pone una dirección (y el modo: transmisión o recepción) en el bus, si alguien tiene esa dirección le contesta, si el modo es de transmisión el master comenzara a enviar datos, si es de recepción el esclavo envía datos, cuando el envío de datos se termina el master pone en el bus un fin de transmisión.

Muchos y variados tipos de dispositivos pueden integrar el bus I2C tales como microcontroladores, memorias, procesadores de señal en televisores, codificadores de video en reproductores de dvd, displays, convertidores A/D, etc.

Para conectarse al bus una entidad tiene que conectar sus pines SDA y SCL a los hilos correspondientes en el bus; todos conectan directamente. En un PIC 16F877A los pines que se utilizan para el I2C son el RC3/SCL y el RC4/SDA. En el PIC 16F876A son los mismos aunque cambian la posición en la distribución de pines del PIC (recordar que el modelo 16F877A tiene 40 pines y el modelo 16F876A tiene 28 pines).

Los ejemplos del PICC Lite incluyen una biblioteca de nombre i2c.h que provee rutinas para utilizar el protocolo pero lo implementan a nivel de capa 1, esta forma debería funcionar inclusive en PICs que no tengan la funcionalidad integrada, sin embargo la forma de uso propuesta en las siguientes secciones utilizan las funcionalidades integradas del microcontrolador. Cuando se estudiaron estas bibliotecas y se determinó que dependen de la biblioteca delay.h se evitó su uso, sobre todo porque delay.h tiene como objetivo esperar ciertos tiempos y esta espera varía según la forma de compilación; si se compila con la bandera del compilador Global Optimization Level en alto genera menos instrucciones que si el nivel es bajo, esto concibe cierta desconfianza en la biblioteca que controla los tiempos (fundamentales para la implementación a nivel capa 1 de una forma de comunicación), más cuando se ve que la espera depende de que pasen cierto número de instrucciones C cuando el tiempo conocido de demora es de las instrucciones Assembler (no de las instrucciones C). Para esperas generales la biblioteca funciona bien pero cuando los tiempos son cruciales como en el establecimiento de las señales de START y STOP del bus I2C o el envío de datos a nivel electrónico se prefirió no utilizarla. Demás está decir que la utilización de la biblioteca se consideró cuando estaba en tela de juicio mantener los PIC 16F628. Al pasar a los PIC 16F877 no hubo ninguna consideración, directamente se utilizó la funcionalidad integrada del PIC.

Seguramente estas rutinas funcionan bien en las condiciones adecuadas (condiciones que no se tuvo necesidad de buscar) por lo que las bibliotecas no se descartan, solo se dejaron de lado para el proyecto.

Registros que intervienen

Registro SSPCON

WCOL bit de detección de colisiones en escritura.

SSPOV bit indicador de overflow en recepción.

SSPEN puerto serial sincrónico habilitado.

CKP controla la contención del reloj (0 contenido, 1 suelta el reloj).

SSPM3:SSPM0 bits de selección del modo de funcionamiento.

Registro SSPCON2

El SSPCON2 es un registro de control que contiene los siguientes bits:

GCEN permite escuchar mensajes generales.

ACKSTAT bit indicador de recepción de ACK (solo master en transmisión).

ACKDT bit de reconocimiento de dato (NoACK, ACK, master recibe).

ACKEN bit para iniciar un ACK (solo en recepción de master).

RCEN bit de habilitación de la recepción (solo master).

PEN bit para iniciar una condición de Stop (solo master).

RSEN bit para iniciar una condición de Start repetida (solo master).

SEN bit para iniciar una condición de Start (solo master).

Registro SSPSTAT

El SSPSTAT mantiene el status de la transmisión, contiene los siguientes bits:

SMP bit de habilitación de control para velocidades bajas.

CKE bit de habilitación del SMBus.

D/A bit indicador de que el último byte recibido fue dato o dirección.

P el bit indica que lo último detectado fue una condición de Stop.

S el bit indica que lo último detectado fue una condición de Start.

R/W el byte recibido es una dirección o un dato (recepción esclavo).

UA bit indicador de que la dirección debe ser actualizada (10 bits).

BF bit indicador de que el buffer está lleno.

Registro SSPBUF

Este registro mantiene la información que se enviará a través del bus, tanto para direcciones como datos. Leer o escribir en este buffer significa enviar o recibir por el bus.

Registro SSPADD

Este registro mantiene la dirección del esclavo en los 7 bits más significativos. En el caso del master en los 7 bits menos significativos se mantiene el valor del generador de baudios del bus (de este valor depende la frecuencia de funcionamiento del bus).

Modo de uso

Los pines SDA y SCL deben estar configurados como entrada en los registros TRIS correspondientes.

Se describe a continuación el rol de MASTER (en adelante master) para enviar y recibir y el rol de SLAVE (en adelante slave) para recibir y enviar.

Tanto master como slaves tienen características distintas desde el punto de vista del uso y la configuración, por ejemplo cada slave debe setear su dirección donde el master setea el baud rate, un slave manda los ACK automáticamente, pero el master debe hacerlo explícitamente por software y otras…

Las siguientes secciones muestran código ejemplo de cómo hacer funcionar el bus I2C, de ninguna manera estos ejemplos agotan el tema, son una introducción y no pueden siquiera intentar suplir las hojas de datos, su único fin es mostrar una forma en que ésto funciona, porque si bien no es un ejemplo completo fue sacado del fuente de un programa master y un programa slave que están funcionando.

Inicialización: MASTER

Código ejemplo:

SSPCON = 0x8 // seteo como MASTER

SSPEN = 1; // módulo SSP habilitado.

SSPADD = 0x28; // Baud Rate Generator: 125 kHz

Inicialización: SLAVE

Código ejemplo:

TRISC = 0B00001100; // seteo las SDA y SCL como entrada, el resto de las patas del // TRISC pueden tener otros valores.

SSPCON = 0B00000110; // seteo como SLAVE

SSPADD = 30; // Dirección del I2C, el valor es de ejemplo

SSPEN = 1; // módulo SSP habilitado.

CKP = 1; // Libera el clock

SEN = 1;

SSPIE = 1; // Para habilitar interrupciones, esta en 0 por defecto.

Envío: MASTER

Se genera una START CONDITION, se envía una DIRECCIÓN con modo transmisión, se envían DATOS, se genera una STOP CONDITION.

Código ejemplo :

// start condition MASTER

SEN = 1; // Start Condition Enabled

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío de la start condition no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

Cuando se envía la dirección, el bit menos significativo es el indicador del modo: transmisión (el master enviará datos al esclavo) o recepción (el esclavo enviará datos al master).

En el ejemplo la dirección del slave es 30 (0B00011110), así que si se quiere enviar datos (modo transmisión) se pondrá en el canal el número 30, si se quiere recibir de él se pondría el 31 (0B00011111). Porque el bit menos significativo indica el modo, las direcciones usadas de esta forma solo pueden tener 7 bits.

Código ejemplo:

// envío la dirección del esclavo con el que quiero comunicarme.

SSPBUF = 30; // envío al canal la dirección 30 modo transmisión.

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío de la dirección no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

// luego del envío chequeo el error viendo el ACKSTAT

if (ACKSTAT != 0)

// ocurrió un error…

// envío un dato al esclavo que ahora está escuchando datos.

SSPBUF = DATO_1; // pongo en el canal el dato a enviar.

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío del dato no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

// luego del envío chequeo el error viendo el ACKSTAT

if (ACKSTAT != 0)

// ocurrió un error…

// repito el envío de datos… (esto se menciona porque la recepción en el esclavo la haremos // 2 veces en este ejemplo ).

// stop condition MASTER

PEN = 1; // Stop Condition Enabled

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío de la stop condition no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

Recepción: SLAVE

El slave está escuchando todo el tiempo el canal, cuando llega una dirección y es para él (compara los 7 bits más significativos (y 0 en el menos significativo) de lo que llega con su dirección (guardada en SSPADD), si hay coincidencia levanta la bandera SSPIF, entonces recibe la dirección y la guarda en SSPBUF. Luego mira el bit menos significativo de lo que llegó y lo guarda en STAT_RW. Si el modo es Master Transmit, el slave empieza a leer datos del canal.

Código ejemplo:

while (SSPIF==0) // mientras no se levante la bandera que indica la

continue; // recepción de un dato o dirección no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

DIR = SSPBUF; // Se debe leer lo que llegó sino no se limpia SSPBUF

if ( STAT_DA==0 ) && ( STAT_RW == 0 )

// llegó una dirección en modo transmisión.

else {

if ( STAT_RW == 0 )

// llegó un dato

else

// el modo es recepción

}

CKP = 1; // suelto el clock, que fue detenido por la llegada del

// dato o dirección.

while (SSPIF==0) // mientras no se levante la bandera que indica la

continue; // recepción de un dato o dirección no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

DATO_1 = SSPBUF; // Se lee el dato que llegó

if ( STAT_DA==0 ) && ( STAT_RW == 0 )

// llegó una dirección en modo transmisión.

else {

if ( STAT_RW == 0 )

// llegó un dato

else

// el modo es recepción

}

CKP = 1; // suelto el clock, que fue detenido por la llegada del

// dato o dirección.

Envío: SLAVE

El slave está escuchando todo el tiempo el canal, cuando llega una dirección y es para él ( compara los 7 bits más significativos (y 0 en el menos significativo) de lo que llega con su dirección (guardada en SSPADD), si hay coincidencia levanta la bandera SSPIF, entonces recibe la dirección y la guarda en SSPBUF. Luego mira el bit menos significativo de lo que llegó y lo guarda en STAT_RW. Si el modo es Master Receive entonces el slave comienza a enviar datos, hasta que el master envíe un ACK final.

while (SSPIF==0) // mientras no se levante la bandera que indica la

continue; // recepción de un dato o dirección no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

DIR = SSPBUF; // Se lee el dato que llegó

if ( STAT_DA==0 ) && ( STAT_RW == 1 ){

// llegó una dirección en modo recepcion.

// Envío el primer dato

SSPBUF = DATO_1;

// Suelto el reloj.

CKP = 1;

while (SSPIF==0) // mientras no se levante la bandera que indica el

continue; // envío del dato no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

// Envío el segundo dato

SSPBUF = DATO_2;

// Suelto el reloj.

CKP = 1;

}

Recepción: MASTER

Se genera una START CONDITION, se envía una DIRECCIÓN con modo recepción, se reciben DATOS, se envía ACK por recepción y un ACK FINAL luego del último byte recibido, por último se genera una STOP CONDITION.

Código ejemplo:

// start condition MASTER

SEN = 1; // Start Condition Enabled

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío de la start condition no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

// envío la dirección del esclavo con el que quiero comunicarme.

SSPBUF = 31; // envío al canal la dirección 31 modo recepción.

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío de la dirección no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

// luego del envío chequeo el error viendo el ACKSTAT

if (ACKSTAT != 0)

// ocurrió un error…

RCEN = 1; // Recepción habilitada.

// Recepción de un dato.

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // recepción de un dato no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

DATO_1 = SSPBUF; // el dato recibido esta en el SSPBUF.

// Envío del ACK

ACKDT = 0;

ACKEN = 1;

while (SSPIF==0) // mientras no se levante la bandera que indica el fin del

continue; // envío de un ACK no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

RCEN = 1; // Recepción habilitada, para recibir cada dato.

// Recepción de un dato.

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // recepción de un dato no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

DATO_2 = SSPBUF; // el dato recibido esta en el SSPBUF.

// Envío el ACK FINAL.

ACKDT = 1;

ACKEN = 1;

while (SSPIF==0) // mientras no se levante la bandera que indica el fin de

continue; // envío del ACK FINAL no hago nada.

SSPIF=0; // la bandera se debe bajar por software.

Control de errores

Para controlar errores se cuenta con los bit"s:

BF que indica buffer full (en la recepción)

tansmisión en progreso (en la transmisión)

SSPOV indicador de overflow (en la recepción).

En los ejemplos no se han explicitado controles de error pero es recomendable, así como el control de la llegada de los ACK.

Si cuando llega un byte el BF esta seteado o el SSPOV, entonces no se enviará el ACK desde el slave.

Interrupciones del I2C

Para que cada vez que sube la bandera SSPIF se produzca una interrupción es necesario habilitar las interrupciones generales y las periféricas

GIE = 1;

PEIE = 1;

y habilitar las interrupciones del módulo SSP

SSPIE = 1;

El resto del funcionamiento es el mismo pero se puede aprovechar esta situación para poner el código en la rutina de interrupción (en vez de hacer polling como en el ejemplo anterior) y hacer una máquina de estados (por ejemplo) para seguir la recepción ordenada de mensajes y respuestas.

Timers

Los timers de un PIC son contadores que corren independientes del programa que está ejecutando el microprocesador. En un PIC de la gama media de Microchip hay 3 distintos, llamados timer0, timer1 y timer2.

Los timers se utilizan para contar tiempos con una fuente de reloj interna o externa, se pueden utilizar para contar instrucciones y en base a que un PIC demora un tiempo fijo en procesar una instrucción se pueden controlar tiempos con buena precisión.

Un timer se controla directamente leyendo su valor todo el tiempo, (pollenado sobre él), o se mirá su bandera de interrupción asociada, que se pondrá en 1 cuando desborde. Además se pueden setear interrupciones por timer, para que cuando desborde se produzca una interrupción.

Timer0

El timer0 es un contador de 8 bits, se puede leer y escribir, cuenta con un preescaler y gracias a él puede llegar a contar hasta 2562, puede utilizar el reloj interno (si lo hay) o externo, genera una interrupción cuando se produce un overflow, tiene 2 modos de funcionamiento, timer mode, suma 1 por cada instrucción y counter mode suma 1 por cada bajada del reloj, está disponible en todos los PIC de la gama media de microchip.

Timer1

El timer1 es un contador de 16 bits, también tiene 2 modos de funcionamiento, counter mode y timer mode (para algunos PIC además hay un modo que se llama contador asincrónico), este timer puede encenderse y apagarse seteando un registro, tiene un preescales de hasta 8.

Código ejemplo :

La funcion prenderTmr1() prende el timer1, seteandolo para que interrumpa en el overflow.

La funcion apagarTmr() apaga el timer1.

void prenderTmr1(){

/*Habilito interrupcion de overflow del timer1*/

TMR1IE = 1;

/*Bajo la bandera que indica interrupcion por timer1*/

TMR1IF = 0;

/*Prendo el timer1.*/

TMR1ON = 1;

TMR1L = 1; // setea los valores iniciales del timer

TMR1H = 0; // en sus MSB y LSB.

}

void apagarTmr1(){

/*Deshabilito interrupcion de overflow del timer1*/

TMR1IE = 0;

/*Apago el timer1.*/

TMR1ON = 0;

/*Bajo la bandera que indica interrupcion por timer1*/

TMR1IF = 0;

}

Cuando el timer de overflow se producirá una interrupción, otra forma de uso es desactivar interrupciones y mirar todo el tiempo la bandera TMR1IF, o bien inspeccionar los valores de TMR1L y TMR1H.

Cabe aclarar que si se prevee usar interrupciones de timers, el GIE debe estar en 1.

Timer2

El timer2 es un contador de 8 bits que tiene preescaler y postescalers, gracias a los que puede llegar a comportarse como un timer de 16 bits. Permite setear un registro de modo que el timer cuente hasta el valor de ese registro y luego pase a 0. Se inicia y se detiene seteando el registro TMR2ON.

Interrupciones

La interrupciones en un PIC funcionan casi como en un PC, excepto porque en un PIC existe solo una rutina de atención a todas las interrupciones (no existe el concepto de vector de interrupciones).

Existen varias fuentes de interrupciones, el USART, el SSP, escritura completa de EEPROM, cambio en el puertoB, timers, etc.

Para habilitar las interrupciones existen bit"s particulares para cada una, estos se encuentran en los registros PIE, y los PIR contienen las banderas de interrupción.

El bit que enmascara las interrupciones globales es el GIE. Si este bit no está en 1 no se detectan interrupciones, es decir no se ejecuta la rutina de interrupción; de todas formas las banderas de interrupción se setean en 1 cuando estas ocurren.

La rutina de interrupción se aloja en la dirección 0004h, lo que significa que si se está programando con interrupciones en Assembler es necesario saltar esta dirección. En C no es necesario preocuparse dado que el compilador ubicará la función interrupt en el lugar adecuado.

Cuando se ejecuta la rutina de interrupción, la bandera GIE se baja por hardware durante la ejecución de la rutina y se sube por hardware al terminar la misma, es importante bajar en software la bandera de la fuente de interrupción provocada. Si no se baja esta bandera en cuanto se suba la GIE, y termine la ejecución de la rutina de interrupción esta se volverá a ejecutar provocando un ciclo de ejecución infinito de la rutina de interrupción.

En las hojas de datos de cada controlador se muestran las distintas interrupciones y las formas de enmascararlas. Es sano tener presentes estas consideraciones a la hora de programar.

Gracias a la posibilidad de enmascarar todas las interrupciones pueden establecerse zonas críticas en el código, tan solo poniendo el GIE=0 para iniciar la zona crítica y volviéndolo a 1, al salir de la misma. Dada la arquitectura de funcionamiento de los PICs si ocurrió una interrupción cuando la GIE estaba baja, al subir esta se ejecutará inmediatamente la rutina de interrupción.

En un programa C compilado con Hi Tech PICC la rutina de interrupción puede tener llamadas a otras rutinas si estas no son utilizadas en el principal, es decir, una rutina no puede ser llamada desde el programa principal y desde la rutina de interrupción a la vez.

Detalles de Assembler

Donde dice variable léase contenido de una dirección de memoria.

Para comparar por igualdad dos variables

Se restan y se mira si el bit ZERO del registro STATUS se puso en 1, si lo hizo las variables son iguales.

Para ver si una variable es mayor que otra

Si a <= b

Movf a, w ; pongo a en el acumulador

Subwf b, w ; a b le resto el acumulador guardo en él.

Btfsc status, carry ; miro si hubo carry

Goto etiq_a_<=_b ; salto a la etiqueta con a menor igual b.

Goto etiq_a_>_b ; sino salto a la de a mayor b.

Para saber si es menor estricto se debe determina si son distintos. Donde w = 0, y carry = 0;

Complemento a 2

Los PIC usan aritmética de complemento a 2. Para encontrar el complemento a 2 de un número binario se pasa a complemento a uno y se le suma 1. Para encontrar el complemento a 1 de un número binario se intercambian los 1"s y 0"s del número original.

Una resta en esta aritmética es la suma del primer término más el complemento a 2 del segundo.

Bibliografía y referencias

[GEO2004] Analizador de bus i2C.

http://www.geocities.com/consultacecat/proyectos.html

Confirmada la existencia de la página al 30/05/2004

[AUT2004] Descripción del bus i2C.

http://autric.com/Microbotica%20y%20Mecatronica/pagina_nueva_1.htm

Confirmada la existencia de la página al 30/05/2004

[COM2004] Características eléctricas del bus i2C.

http://www.comunidadelectronicos.com/articulos/i2c.htm

Confirmada la existencia de la página al 30/05/2004

[ES.2004] como programar el puerto serie en linux.

http://es.tldp.org/COMO-INSFLUG/COMOs/Programacion-Serie-Como/Programacion-Serie-Como.html#toc3

Confirmada la existencia de la página al 30/05/2004

[UWS2004] rs232- connectors and cabling.

http://www.uwsg.iu.edu/usail/peripherals/serial/rs232/

Confirmada la existencia de la página al 30/05/2004

[IPN2004] Puertos y conectores. El puerto serie.

http://www.ipn.mx/sitios_interes/sanlovdra/serie.htm

Confirmada la existencia de la página al 30/05/2004

[CPC2004] Serial I-O Rs232

http://www.cpcug.org/user/clemenzi/technical/Languages/SerialI-O(RS232).htm

Confirmada la existencia de la página al 30/05/2004

[VOT2004] Información general de introducción a PICs…

http://www.voti.nl/swp/index.html

Confirmada la existencia de la página al 30/05/2004

[IMP1998] Implementación de un sistema de desarrollo utilizando lo microcontroladores PIC, Universidad de Guadalajara,1998 .

Manuel Fernando Campos Cerda

Ramiro Castañeda Pérez

Arturo César Contreras Torres

[MMP2003] Manual de MicroContoladores PIC. Diseñado para los amigos de Picislatina. Documento facilitado por el instructor del curso : MicroControladores PIC 2003.

[MIC2004] http://www.microchip.com página oficial de MicroChip.

Confirmada la existencia de la página al 30/05/2004

[HOJ2004A] Hoja de datos del microcontrolador 16F628.

[HOJ2004B] Hoja de datos del microcontrolador 16F877A y 16F876A.

[MAN2004] Manual de PICC Lite.

[FIN2004] http://www.fing.edu.uy/~pgconrob pagina del proyecto de grado Construcción de robots a bajo costo.

[LM2004A] Funcionamiento de microcontroladores. Documentación asociada al proyecto, descripción de funcionamiento de microcontroladores PIC. Germán López – Santiago Margni (2004)

Enviado por: Ing.+Lic. Yunior Andrés Castillo S.

"NO A LA CULTURA DEL SECRETO, SI A LA LIBERTAD DE INFORMACION"®

Santiago de los Caballeros, República Dominicana, 2016.

"DIOS, JUAN PABLO DUARTE, JUAN BOSCH Y ANDRÉS CASTILLO DE LEÓN – POR SIEMPRE"®

CONSTRUCCIÓN DE ROBOTS A BAJO COSTO.

Programación de Microcontroladores.

Rutinas, detalles y sintaxis.

 

 

 

Autor:

Germán López y Santiago Margni.