En esta
nota se mostrara la utilización simple del protocolo I2C de un microcontrolador
que posee un puerto especial para dicho protocolo.
Las
funciones Básicas del protocolo dentro del compilador CCS son:
i2c_start();
//Inicialización de la trama
i2c_stop();
//Finalización de la trama
i2c_read();
//Lectura de los datos
i2c_write();
//Escritura de los datos
i2c_poll();
//Espera a que exista un byte y cuando lo encuentra se activa como verdadero
La configuración
del protocolo puede ser Rápida o Lenta, Maestra o Esclava,
En el
caso de que sea una configuración Maestra (Master) será de la siguiente forma:
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)
En esta configuración
podemos notar que se encuentra en modo Maestro, modo Rápido, y que asigna los
pines SDA y SCL a los pines físicos del microcontrolador, que de todas formas
son los que poseen el puerto internamente.
En el
caso de que sea una configuración Esclava (Slave) será de la siguiente forma:
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0x10)
En esta configuración
podemos notar que se encuentra en modo Esclavo, modo Rápido, y que asigna los
pines SDA y SCL a los pines físicos del microcontrolador, que de todas formas
son los que poseen el puerto internamente. Pero también notamos un nuevo
comando que es “Address” donde en este caso y a modo ejemplo posee el valor
hexadecimal 0x10, el cual puede ser modificado a gusto por el programador. Este
valor de dirección será el “nombre” del esclavo.
Como
este protocolo es un bus, podemos montar sobre el mismo bus varios esclavos, pero
cada uno con un address diferente, de esta forma el maestro puede acceder a
cada uno utilizando la dirección, es decir, envió la dirección de quien quiero
acceder y luego el dato.
Estas
configuraciones son por Hardware, CCS también posee una librería para utilizar
el protocolo I2C por Software.
A continuación
les mostrare dos programas de ejemplo, el primero es un programa Maestro y el segundo
es un programa Esclavo.
Lo que
hace el maestro es leer el puerto analógico del microcontrolador y enviar el
valor leído por medio del protocolo I2C, Luego el Esclavo toma este valor y lo
muestra en un LCD, es muy simple pero funciona muy bien a modo ejemplo.
MAESTRO
#include <16F883.h>
#FUSES NOWDT
#FUSES RC_IO
#FUSES NOMCLR
#device adc=8
#use delay(clock=4000000)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)
#define IDslave 0x10
void main()
{
setup_adc_ports(sAN0|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
int8 varAdc;
while(true){
set_adc_channel(0);
varAdc = read_adc(); //Lee puerto ADC
i2c_start(); //Inicializa
i2c_write(IDslave); //Envia el Address del Esclavo
i2c_write(varAdc); //Envia valor leido ADC
i2c_stop(); //Finaliza
delay_ms(100);
}
}
Podemos
ver que en el programa Maestro tenemos configurado el pin AN0 como entrada análoga
de 8bit la cual se guardara en la variable varAdc, luego de esto aparecen las
funciones básicas del i2c de CCS, primero iniciamos la trama con i2c_start();
luego enviamos los datos mediante i2c_write(); ,la dirección 0x10 que la he definido
como IDslave por prolijidad pero pueden poner directamente el valor 0x10 y no
definir nada arriba, luego de este valor viene el segundo dato que es el valor
de lectura del ADC y luego el i2c_stop(); que finaliza la trama.
ESCLAVO
#include <16F883.h>
#device adc=8
#FUSES NOWDT
#FUSES RC_IO
#FUSES NOMCLR
#use delay(int=4000000)
#use i2c(Slave,Fast,sda=PIN_C4,scl=PIN_C3,address=0x10)
#include <LCD.C>
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
lcd_init();
while(TRUE){
if(i2c_poll()) //Pregunta si hay un byte presente
printf(lcd_putc,"VALOR I2C: %d \a",i2c_read());
//Muestra el valor enviado por el maestro
}
}
En el
programa Esclavo podemos ver que es mas sencillo aun, el mismo consulta
mediante un if si la función i2c_poll(); es verdadera o falsa, si es verdadera
es porque hay un dato en la entrada del puerto I2C, de esta forma procedemos a
mostrar el valor del dato enviado por el maestro en nuestro LCD.
NOTA:
observe que en la impresión del LCD se ha finalizado el sistema con \a, esto es
para que en el LCD solo se muestre el ultimo valor de la memoria pisando el
anterior, ya que si no utilizamos esto nos mostrara el primer valor que seria
16, ya que como el Maestro envía dos datos (el IDslave o Address , y el dato
que proviene del ADC) mostraría el 16 que es 0x10 convertido en decimal.
Podemos
ver el circuito que es muy simple, solamente hay que tener en cuenta que la
salida del protocolo I2C es a Emisor Común, por lo que debe utilizarse siempre
las resistencias de Pull-Up, como se ve en el circuito son de 4k7, es un valor
recomendado por Microchip pero puede ser otro valor, claramente si es menor
aumentara la corriente del puerto lo que disminuirá la vida útil del
microcontrolador, y si es mayor la resistencia aumentara el nivel de ruido eléctrico
en el bus.
En el
circuito se ha puesto un debugger del bus I2C el cual muestra con el color Verde los bits de Start y de Parada, Con el color Azul se puede ver el dato 0x10 que es el Address que se envia al esclavo y con el color Rojo el valor que esta
siendo enviado por el bus, en este caso el ADC esta enviando el valor 0x30 el
cual al pasar por el printf en el Esclavo se convierte a decimal como el valor
48.
Hola Sebastián,
ResponderBorrarHe leido tu artículo y visto tu video.
Me queda una duda con respecto con respecto al envío de la dirección Address por parte del Maestro:
En el caso del LCD, el mismo es direccionado por la dirección IDslave, en este caso, el Esclavo como se agencia que su dirección es la mencionada por IDslave?
Te lo pregunto por que no me doy cuenta como es que se envía la dirección Addres primero e inmediatamente el dato.
Se me ocurre que internamente el LCD tiene alguna manera de determinar si aceptará el dato o no.
Disculpa si la pregunta parece sencilla pero estoy tratando de entender el i2c para una aplicación y necesito saber como implementarla adecuadamente.
Desde ya muchas gracias,
Un saludo cordial,
Pablo Silvoni
Hola, buen día!, el LCD no tiene nada que ver con el I2C en este caso, el Master es uno de los microcontroladores y el Slave es el otro de los microcontroladores, fíjate que en la configuración del i2c en el microcontrolador Slave tiene aparte de la definición de pines y velocidad, la dirección del Slave (0x10).
BorrarDespués el Master tiene que enviar primero la dirección y luego el dato para que el dato enviado por el Master sea recogido solo por el Slave que tiene esa dirección, porque podrías tener varios dispositivos en el mismo bus y tendría que responder solo al que el Master seleccione y no los demás. Pero el LCD es independiente del proyecto, podría haber usado LEDs o algún otro dispositivo de salida.
Saludos!
Hola Sebastian
ResponderBorrarMuy bueno tu artículo.
Quisiera ayuda pero para utilizar un Micro controlador como Maestro y un Arduino Como esclavo.
Muchas gracias, Saludos.
Hola, si, no hay problema, siempre que tengas la misma velocidad en el bus y el mismo ID, no deberías tener problemas
BorrarSaludos.
hola sebas
ResponderBorraruna consulta como seria si el esclavo sensa el adc y el maestro lo muestra en el lcd y solo es de 8 bits por lo que noto si uso el adc10 como aria en ese caso gracias de ante mano
Hola como estas?, podes mandar mas de 8 bit si queres, tenes que enviar mas paquetes de datos, por ejemplo podrías mandar dos paquetes de 8bit donde en uno mandas la parte alta del ADC y en el otro la parte baja. Después en el receptor lo reconstruis y lo mostras.
BorrarSaludos.
en tu ejemplo usas el esclavo para mostrar pero como seria si el maestro es el que usa el lcd y el esclavo sensa el adc de ante mano gracias. no entiendo mucho eso del lo de los paquetes en programar si entiendo la idea. de enviar dos paquetes y luego sumarlas al llegar
ResponderBorrarHola el display es independiente, podes ponerlo en el master o el esclavo, da igual, lo importante es el dato que mandas. En realidad en i2c se denomina que el master "consulta" al esclavo y el esclavo le "responde", de ahi viene la idea.
BorrarDespues el display puede estar en el master y mostrar los datos "respondidos" del esclavo.
Saludos
HOLA QUE TAL UNA CONSULTA COMO SERIA SI PONGO TRES MAESTROS Y UN SOLO ESCLAVO NO EXISTIRA COLICIONES O ALGO ASI Y SI PODRIAS HACER UN TUTO SOBRE ESO EN YOUTUBE ESTARIA GENIAL GRACIAS DE ANTEMANO TUS INFORMACIONES SON GENIALES...
ResponderBorrarHola, si de echo no deberías hacer eso, deberías tener siempre un master y después los esclavos que quieras. lo que se suele hacer es dar jerarquía a la red, por ejemplo tener alguno que este entre el máster y el esclavo, pero la toplogia de i2c es de master a muchos a esclavos. Podes hacer la prueba, vas a tener problemas con los ACK y demas... pero bueno romper no vas a romper nada porque son salidas opendrain/opencolector, entonces siempre estan en 1 mediante un pullup y solo controlas cuando bajas la linea.. lo peor que puede pasar es que no se comunique bien. Saludos.
Borrarmuy buen trabajo me resolviste muchas dudas gracias
ResponderBorrarHola disculpa como puedo descargar la librería.
ResponderBorrar