Microcontroladores (Pic) .3

Descargar como docx, pdf o txt
Descargar como docx, pdf o txt
Está en la página 1de 17

Comunicación I2C

En esta entrada vas a aprender todo sobre el protocolo de


comunicación I2C, que es, como funciona y adicionalmente veremos
como implementarlo en cualquier microcontrolador PIC usando el
compilador CCS C. Al final veremos un TUTORIAL I2C con un ejemplo
paso a paso de su implementación.

Tabla de Contenido
 1 Comunicacion I2C Microcontroladores PIC
o 1.1 ¿Que es el I2C?
o 1.2 ¿Como trabaja la comunicación I2C?
 2 Funcionamiento de la Comunicación I2C PIC
o 2.1 Sensor de Presión MPX con PIC
o 2.2 LCD I2C PIC
o 2.3 I2C Arduino
o 2.4 Protocolo de Comunicación I2C con CCS C
 3 Protocolo I2C PIC – Ejemplo
o 3.1 Circuito Electronico Comunicación I2C Microcontroladores PIC:
o 3.2 XBEE modo AT
o 3.3 Predictor de Smith con PIC
o 3.4 Adquisición de Datos e Identificación de un Horno con PIC
o 3.5 Código de Implementación de Comunicación I2C PIC:
 3.5.1 EEPROM
 3.5.2 RELOJ DE TIEMPO REAL DS1307
 3.5.3 TERMOMETRO
 3.5.4 PRINCIPAL
 4 Bibliografia

Comunicacion I2C Microcontroladores PIC


Vamos a comenzar a entender inicialmente a ver la explicación del protocolo I2C el
cual puede ser implementado en cualquier microcontrolador, tanto en el PIC como
también se puede implementar una comunicación I2C con Arduino.

¿Que es el I2C?
El bus de comunicaciones I2C (nombrado a veces como I cuadrado C, I^2) es un
protocolo que se efectúa por medio de DOS hilos. A través de estos dos hilos
pueden conectarse diferentes dispositivos donde algunos de ellos
serán MAESTROS en cuanto muchos otros dispositivos serán ESCLAVOS.
¿Como trabaja la comunicación I2C?
Para poder reconocer cada uno de los dispositivos conectados a los DOS hilos del
bus I2C, a cada dispositivo se le asigna una dirección.
Así en este tipo de comunicaciones el MAESTRO es el que tiene la iniciativa en la
transferencia y este es quien decide con quien se quiere conectar para enviar y
recibir datos y también decide cuando finalizar la comunicación.
Los DOS hilos del BUS interfaz de comunicación I2C PIC son lineas de colector
abierto donde una de las lineas lleva la señal de reloj y es conocida como (SCL), y la
otra linea lleva los datos y es conocida como (SDA).
Los Pines SDA y SDL I2C se encuentran especificados en todos los componentes
que usan este tipo de protocolo de comunicación.
Para que la comunicación funcione se deben utilizar unas resistencias PULL
UP (resistencias conectadas a positivo) para asegurar un nivel alto cuando NO hay
dispositivos conectados al BUS I2C.

La conexión I2C entre un maestro y vários esclavos se muestra a continuación:

El número de dispositivos que pueden conectarse de esta forma y además


la longitud del BUS es limitada por la capacidad de direccionamiento (de
7 a 10 bits) y por la máxima carga del BUS (400pF). La velocidad máxima
estándar es de 100Kbps.

Funcionamiento de la Comunicación I2C PIC


La transmisión de datos se inicia con un bit de inicio (START) y termina con un
bit de finalización (STOP). El bit de START se reconoce porque la linea SDA pasa de
un estado lógico alto para un estado lógico de bajo cuando la linea SCL esta en
nivel alto. El STOP se establece cuando hay una transición de bajo a alto en la
linea SDA, cuando SCL está en un nivel alto.

Cuando comienza la transmisión de datos, el MAESTRO envía la dirección del


ESCLAVO con el cual se quiere comunicar, esta dirección puede ser de 7 o 10 bits
con formato de byte (uno o dos bits respectivamente) Después de la dirección se
adiciona 1 bit, que indica si se desea ESCRIBIR o LEER (R/W).
Cuando el Maestro envía estos DATOS para el esclavo. El ESCLAVO debe
responderle al maestro con un bit de confirmación para informarle que escucho
la solicitud del maestro y que esta a disposición de lo que él necesite. Este bit de
confirmación se conoce como  (ACK).
Si el maestro NO recibe este bit, la comunicación se interrumpe. Por otro
lado, se puede dar el caso que un ESCLAVO está mandando alguna
información al maestro, entonces el maestro también generará este bit de
confirmación hacia el esclavo.

Puede darse el caso también de que una vez el MAESTRO se comunica con el
ESCLAVO, el MAESTRO no abandone el BUS y continúe comunicándose con el
ESCLAVO, para eso el MAESTRO debe generar una nueva condición de START que
se conoce en la literatura como START REPETIDA (Sr), idéntica al START anterior
solo que con un pulso de reconocimiento.
Para trabajar con el modulo de comunicación I2C PIC, se deben configurar los
siguientes registros: SSPCON, SSPCON2, SSPADD, SSPBUF, SSPSTAT y SSPSR.

Protocolo de Comunicación I2C con CCS C


En CCS C PIC C, existen funciones que nos facilitan la implementación de este tipo
de comunicación. Comencemos primero viendo el tipo de configuraciones que
podemos llevar a cabo:

Para las configuraciones genéricas del i2c declaramos lo siguiente en el


encabezado de nuestro programa:

#use i2c (opciones)

Estas opciones pueden ir separadas por comas y pueden ser cualquiera de las
siguientes opciones
La directiva (#use i2c) tiene efecto en las funciones: I2C_START, I2C_STOP,
I2C_READ. I2C_WRITE y I2C_POLL. Se utilizan funciones de Software a menos que se
especifique FORCE_HW.

Como por ejemplo:

#USE I2C(master, sda=PIN_B0, scl=PIN_B1)

#USE I2C(slave, sda=PIN_C4, scl=PIN_C3, address=0XA0, force_hw)

#USE I2C(master, sda=PIN_B0, scl=PIN_B1, fast=450000)

Las funciones asociadas al i2c son:

i2c_start();

Para el modo maestro, esta función inicia la trasmisión. Después de la condición de


arranque o START, el reloj es colocado en nivel lógico bajo hasta el momento en
que se escriba con la función I2C_WRITE(); Si se llama otra función I2C_START antes
que un I2C_STOP quiere decir que se está utilizando un START Repetido (Sr). Esta
función depende de la respuesta del esclavo.

i2c_stop();

Finaliza la transmisión.

i2c_write(DATO);

En esta función “DATO” es un entero de 8 bits que se envía por el bus. Cuando un
dispositivo que es MAESTRO aplica esta instrucción , se genera una señal de reloj
que marca la velocidad de transmisión del dato; Cuando un ESCLAVO aplica esta
instrucción se queda esperando la señal de reloj que genere el MAESTRO.

Esta función devuelve el bit de reconocimiento ACK que le envía el receptor


cuando la transmisión ha terminado: 0 indica ACK; 1 indica NOACK y 2 indica una
colisión en el modo MULTIMASTER.

Para saber la dirección de la transmisión, se observa el bit de menor peso (LSB) del
primer dato transmitido tras un START (Si el bit es “0” quiere decir que la
información se está transmitiendo de MAESTRO a ESCLAVO)

Dato=i2c_read();
Dato2=i2c_read([ack]);
Dato es un entero de 8 bits leído del BUS. Cuando un dispositivo que es MAESTRO
aplica esta instrucción , se genera una señal de reloj que marca la velocidad de
transmisión del dato; Cuando un ESCLAVO aplica esta instrucción se queda
esperando la señal de reloj que genere el MAESTRO. No hay timeout  por lo que
esta instrucción se utiliza junto con i2c_poll() para prevenir bloqueos.

Opcionalmente se puede incluir un ACK donde  1 indica ACK; 0 indica NOACK

valor=i2c_poll();

Se utiliza solo si el PIC tiene modulo SSP. Devuelve un TRUE(1) si se ha recibido el


dato en el buffer y un FALSE(0) si no se ha recibido. Cuando devuelve el TRUE(1) la
función i2c_read() guarda el dato recibido.

estado=i2c_isr_state();

Se utiliza solo si el PIC tiene modulo SSP. Devuelve el estado del bus en modo
ESCLAVO después de una interrupción.

Estado es un entero de 8 bits.


i2c_slaveaddr(int8 adr);

Se especifica la dirección del dispositivo en modo esclavo.

Protocolo I2C PIC – Ejemplo


Un proceso de temperatura tiene incorporado una tarjeta electrónica encargada de
realizar el monitoramiento de la variable temperatura en el interior del proceso.

Dicha tarjeta electrónica cuenta con PIC16F887, un LCD, un puerto de


comunicación serial, un sensor I2C de temperatura (DS1621), cuenta con un reloj
calendario de tiempo real I2C (DS1307) y cuenta además con una memoria
EEPROM serie I2C (M24512).

Se solicita al ingeniero de control realizar un programa en el PIC16F887, para que


por medio de un menu en el computador, el usuario pueda tener la opción de leer
la temperatura y la hora de lectura de la misma almacenando estos datos en la
memoria EEPROM y que estos datos también se visualicen en el LCD.

El Menú debe tener una segunda opción que le permita al usuario ver por el puerto
serial los últimos datos almacenados en la EEPROM.
Circuito Electronico Comunicación I2C Microcontroladores PIC:

En el proteus vamos a necesitar los siguientes componentes: PIC16F887, RES, CAP,


CRYSTAL, M24512, DS1621, DS1307 y LM016L.

Código de Implementación de Comunicación I2C PIC:


A continuación se muestra el procedimiento y todo el código de implementación
del ejemplo. Recuerda que para poder ver el código es necesario
que COMPARTAS el contenido de este post o te SUSCRIBAS con cualquiera de los
tres botones que están abajo y automáticamente el Código de implementación
queda desbloqueado para que lo pegues y lo copies en tu compilador.
En este ejemplo vamos a hacer la libreria I2C para PIC nosotros mismos,
entonces es una práctica muy interesante donde vas a aprender mucho.

[sociallocker id=948]

Para solucionar este ejemplo vamos a crear tres librerías para manejar cada uno
de los 3 esclavos del ejemplo.
EEPROM
En entradas pasadas habíamos utilizado la libreria de la EEPROM del PIC para
guardar datos en ella, en este ejemplo vamos a crear nuestra propia  libreria I2C
para PIC para entender como programarla por i2c:
La EEPROM M24512 (click para ver datasheet)  tiene tres pines E2, E1, E0 que
permiten establecer la dirección de este dispositivo, de esta manera el PIC se
comunicara con la Memoria cuando el envíe por el i2c dicha dirección.
Esta dirección es almacenada dentro de la EEPROM en un byte de control
donde la parte alta de este byte siempre es fija (1010) y la parte
baja corresponde a los estados lógicos de E2, E1, E0, por ultimo viene el
bit de escritura/lectura, como puede ser visto en la siguiente figura:

Lo que quiere decir que si el PIC envia 0xA0 el PIC estará escribiendo en la


memoria, por otro lado si manda 0xA1h el PIC estará leyendo la memoria.
El formato de escritura de la EEPROM es mostrada en la hoja de datos en la pagina
15, donde después de la señal de START, se escribe la palabra de control para
seleccionar el dispositivo y el modo de trabajo, dos bytes para la dirección de
escritura y el dato a escribir.

A continuación se muestra la función de escritura de nuestra  libreria I2C para PIC


que guardaremos en un archivo llamado EEPROM_24512.c

void write_ext_eeprom(long int address, BYTE data)

short int status;

i2c_start(); //Inicializa la Transmisión

i2c_write(0xa0); //Escribe la palabra de control(direccion


//0h + 0 para escritura)

i2c_write(address>>8); //Parte alta de la dirección a escribir en la eeprom

i2c_write(address); //Parte baja de la dirección a escribir en la eeprom

i2c_write(data); //Dato a escribir

i2c_stop(); //Finalización de la transmisión

i2c_start(); //Reinicio

status=i2c_write(0xa0); //Lectura del bit ACK, para evitar escrituras

//incorrectas

while(status==1) //Si es "1" se espera para responder al esclavo

i2c_start();

status=i2c_write(0xa0);

El proceso de escritura puede hacerse de 4 formas como mostrada en la pagina 19


del datasheet, nosotros utilizaremos la segunda forma “leer una dirección
cualquiera (Random Address Read)” que es la más común y dicho proceso de
lectura es muy similar con el de escritura solo que en este caso al final el MAESTRO
debe enviar un NO ACK.

A continuación se muestra la segunda función de nuestra  librería I2C para PIC que
colocaremos en nuestra librería de EEPROM_24512.c

BYTE read_ext_eeprom(long int address) {

BYTE data;

i2c_start(); //Inicializa la Transmisión

i2c_write(0xa0); //Escribe la palabra de control(direccion


//0h + 0 para escritura)

i2c_write(address>>8); //Parte alta de la dirección a escribir en la eeprom

i2c_write(address); //Parte baja de la dirección a escribir en la eeprom

i2c_start(); //Reinicio

i2c_write(0xa1); //Escribe la palabra de control(direccion

//0h + 1 para escritura)

data=i2c_read(0); //Lectura del Dato

i2c_stop(); //Finalización de la transmisión

return(data);

RELOJ DE TIEMPO REAL DS1307


Datasheet click aca. Este dispositivo es capaz de suministrar los segundos, minutos,
horas, dia, mes y año en tiempo real (por medio de un cristal de cuarzo de
32.768Khz).

Este dispositivo posee una serie de registros donde aparecen los datos necesarios
(tabla 2 de la pagina 8 del datasheet). Estos datos son suministrados en BCD.

El ciclo de escritura de este dispositivo se inicia con la palabra 0xD0 y la lectura


con 0xD1 (pagina 12).

En la escritura el segundo byte es un puntero que indica la dirección del dato que
queremos escribir (ver la tabla 2).

En el ciclo de lectura es igual que el de escritura solo que el ultimo byte debe
indicar un NACK al Maestro. Con esto tan solo queda convertir los bytes leídos de
bcd a binario.

Para el manejo del reloj de tiempo real vamos a crear una libreria I2C para PIC
llamada DS1307.c con las siguientes funciones:

int BCDaBIN(BYTE bcd)


{

int varia;

varia=bcd;

varia>>=1;

varia &= 0x78;

return (varia + (varia>>2) + (bcd & 0x0f));

void rtc_get_time(BYTE& hr, BYTE& min, BYTE& sec) {

i2c_start(); //Escritura

i2c_write(0xD0); //Codigo de escritura

i2c_write(0x00); //Puntero de la primera dirección

i2c_start(); //Lectura

i2c_write(0xD1); //Codigo de lectura

sec = BCDaBIN(i2c_read()&0x7f); //Lectura de los 7 bit de los segundos

min = BCDaBIN(i2c_read()&0x7f); //Lectura de los 7 bit de los minutos

hr = BCDaBIN(i2c_read(0)&0x3f); //Lectura de los 6 bit de las horas

i2c_stop(); //Finaliza comunicación

TERMOMETRO
El termometro digital i2c DS1621 (Clic aca Datasheet)  permite medir una
temperatura entre -55°C y 125°C como mostrado en la tabla 2 de la pagina 4 del
datasheet.
Este valor de temperatura es suministrado en dos Bytes. El byte alto es el valor
entero con una resolución de 1°C y el segundo byte es el valor decimal con una
resolución de 0.5°C.
El termómetro tiene tres pines los cuales sirven para darle la dirección al
dispositivo (A2, A1, A0). En nuestro ejemplo tenemos la dirección (0x03).
Al igual que la memoria EEPROM el termómetro tiene un byte de control donde se
almacena la dirección y si se desea escribir o leer. Este byte de control posee en su
parte alta un numero fijo (1001) y la parte baja viene dado por los pines de
dirección (A2, A1, A0) y el ultimo bit (R/W) es de escritura o lectura.
En la pagina 10 del datasheet se muestran todos los comandos que se pueden
usar con este dispositivo y la pagina 9 muestra ejemplos de como debe realizarse
el envío de tramas por el i2c.

Los comandos pueden ser 0xAA para lectura de la temperatura, 0xEE para el inicio
de conversión.

A continuación se muestran las funciones que vamos a colocar en nuestra librería


llamada TEMP_DS1621.c

void init_temp(int address) {

i2c_start();

i2c_write(0x90|(address<<1)); //Genera primer byte (1001A2A1A0W)

i2c_write(0xee); //Inicia conversion

i2c_stop();

float read_full_temp(int address) {

float tura;

BYTE datah;

BYTE datal;

int data;

i2c_start();

i2c_write(0x90|(address<<1)); //Genera primer byte (1001A2A1A0-W)

i2c_write(0xaa); //Lee temperatura


i2c_start();

i2c_write(0x91|(address<<1)); //Genera primer byte (1001A2A1A0-R)

datah=i2c_read(); //Lectura parte alta

datal=i2c_read(0); //Lectura parte alta y NACK

i2c_stop();

data=datah;

if (datal==128)

tura=data+0.5;

else

tura=data;

return(tura);

}
PRINCIPAL
Dado que la temperatura es un dato tipo FLOAT, no se puede guardar este dato
directamente en la EEPROM, por lo tanto vamos a utilizar una librería suministrada
por CCS C llamada FLOATEE.c que nos permitirá guardar y leer datos tipo FLOAT
en una EEPROM.

A continuación se muestra el programa principal el cual despliega un menú, donde


si se digita “1” el pic lee la temperatura y la hora y las almacena en la memoria
EEPROM mostrando estos datos en el LCD. Si el usuario presiona “2” el PIC lee la
memoria y muestra los últimos 7 datos en el terminal serie.

Descargar Códigos + Esquema en Proteus v8.7

#INCLUDE <16F887.h>

#DEVICE ADC=10

#USE DELAY(CLOCK=4000000)
#FUSES XT,NOPROTECT,NOWDT,NOBROWNOUT,PUT,NOLVP

//Configura direccion de memoria de los puertos A,B,C,D

#BYTE PORTA= 5

#BYTE PORTB= 6

#BYTE PORTC= 7

#BYTE PORTD= 8

#define EEPROM_SDA PIN_C4

#define EEPROM_SCL PIN_C3

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, bits=8, parity=N)

#use i2c(MASTER,Fast=100000, sda=EEPROM_SDA, scl=EEPROM_SCL,force_sw)

#include <lcd.c>

#include <EEPROM_24512.c>

#include <DS1307.c>

#include <TEMP_DS1621.c>

#include <floatee.c>

int dat_in=0, cnt, hr, min, sec;

int16 address=0;

int dat_serie[7];

float dato=0;

//Interrupción por el puerto serial

#int_rda

void rda_isr(void)

{
dat_in=getc(); //Lee el puerto Serial

printf("%c\r",dat_in);

if (dat_in=='2') //Pregunta si es "2" para visualizar parametros de la EEPROM

for(cnt=address-7;cnt<=address;cnt++) //Lee los primeros 7 bytes de la EEPROM

dat_serie[cnt]=read_ext_eeprom(cnt);

printf("Byte %u=%3u \r", cnt, dat_serie[cnt]);

void main()

lcd_init();

set_tris_c(255);

enable_interrupts(int_rda);

enable_interrupts(global);

address=0;

init_temp(0x03); //Inicializa el DS1621

//Crea un Menu para mostrar por el Serial

printf("Pulse 1 para leer los datos\r");

printf("Pulse 2 para visualizar los datos\r");

while(1)
{

if(dat_in=='1') //Si es "1" inicie la lectura y grabado de la EEPROM

init_temp(0x03); //Inicializa el DS1621

rtc_get_time(hr,min,sec); //Lee el tiempo del DS1307

dato=read_full_temp(0x03); //Lee temperatura del DS1621

write_float_ext_eeprom(address,dato); //Guarda 4 bytes del float

address=address+4;

write_ext_eeprom(address++,hr); //Guarda byte de Hora

write_ext_eeprom(address++,min); //Guarda byte de Minuto

write_ext_eeprom(address++,sec); //Guarda byte de Segundo

lcd_gotoxy(1,1);

printf(lcd_putc,"Temp=%4.1f C \n",dato);//Visualiza la temperatura

printf(lcd_putc,"%2u:%2u:%2u",hr,min,sec);//Visualiza la hora

if (address==0xffff)

address=0; //Cuando se termina la EEPROM vuelve al principio

dat_in=0;

[/sociallocker]
Bibliografia
1. Compilador C CCS y Simulador Proteus para Microcontroladores PIC, Eduardo
Garcia Breijo,

También podría gustarte