Está en la página 1de 22

I ♥AVR ´s

Microcontroladores AVR`s

Protocolo de Comunicación I2C

Elaborado:
Ing. Xavier Flores C
I ♥AVR ´s

BUS I2C
TWI AVR es el módulo para la comunicación serial I2C del microcontrolador AVR,
la comunicación serial I2C se le llama TWI que viene de las siglas en inglés de
interfaz serial a 2 hilos, en la comunicación I2C o TWI se utilizan 2 hilos a lo que
se conoce como bus I2C o en el caso del AVR se le llama bus TWI, a estos hilos se
conectan los dispositivos que se puedan comunicar mediante el protocolo I2C, por
uno de los hilos se enviará una señal de reloj para la sincronización y por el
otro hilo se enviarán o recibirán datos, se pueden conectar varios dispositivos de
los que uno de ellos será el maestro, es el que generará la señal de reloj además
de decidir cuándo se inicia o finaliza la comunicación y si la comunicación
será de recepción o transmisión de datos, los demás dispositivos conectados al
bus I2C se conocen como esclavos, el protocolo I2C es efectiva para distancias
cortas y ampliamente usada para la comunicación entre sensores, rtc, eeprom
y lcds.
Cada uno de los dispositivos tiene una dirección, cuando el maestro necesita
comunicarse con alguno de los esclavos lo hará enviando la dirección del
esclavo a través del bus I2C, cuando el esclavo reciba su dirección podrá
comunicarse con el maestro, el maestro además tiene que enviar un bit mediante el
cual le indica al esclavo si quiere enviarle un dato o quiere recibir un dato del
esclavo, el microcontrolador AVR puede ser utilizado como maestro o como
esclavo en la comunicación serial I2C AVR.
Los pines que se utilizan en la comunicación serial I2C son los nombrados como
SDA serial data y SCL serial clock, el pin SDA es para enviar o recibir los datos,
y el pin SCL es para la señal de reloj, a estos pines se les debe conectar mediante
unas resistencias que pueden ser de 4K7 a la tensión de alimentación del
microcontrolador AVR, o también se puede habilitar las resistencias internas pull up
de estos pines, con lo que ya no se necesita utilizar las resistencias externas para
la comunicación I2C AVR; los pines de los demás dispositivos conectados al bus
I2C también están nombrados como SDA y SCL.

A/D
LCD MCU D/A RTC

SCL
SDA
I ♥AVR ´s

La velocidad de comunicación puede ser desde 100Kbps en el modo estándar


o normal, aunque puede llegar en el modo rápido hasta los 400Kbps y en la más
alta hasta más de 3Mbps, esto dependerá de los dispositivos utilizados, para ello
es recomendable revisar sus hojas de datos.
El bus I2C consiste de 2 líneas bidireccionales de “drenaje abierto” que deben
ir en una configuración pull-up con las resistencias, tal como se muestra en
la figura de abajo:

vcc

R R DISPOSITIVO DISPOSITIVO DISPOSITIVO DISPOSITIVO


1 2 3 4

SDA
SCL
Interfaz del BUS I2C

Dado que las líneas son de “drenaje abierto” o colector abierto, es necesario
proveer un voltaje alto al gate del transistor. Si el voltaje del gate está en bajo,
el transistor no se activará y la correspondiente línea conducirá en alto.
I ♥AVR ´s

Características electrónicas del Bus I2C

Como podemos observar en la figura, pese a que recomendamos usar resistencias


de 4k7 cuando conectamos los dispositivos I2C hay que tomar en cuenta otros
factores, entre ellos la capacitancia de 400pF (Cb - Capacitance of bus), es decir
que mi número de dispositivos máximos conectados al bus I2C se ve limitado por
este valor, esta capacitancia es la que se encuentra entre las líneas SDA y SCL, y
que a medida que vayamos agregando más elemento la capacitancia ira
cambiando, una vez encontrada ese capacitancia podemos hallar nuestra
resistencia de PULL-UP (Rp) tal como se muestra en la tabla superior.
Contemplando estos pequeños pero valiosos detalles obtendremos excelentes
resultados durante la comunicación.

FRAMES DE DATOS
Para que los paquetes de datos sean válidos en la línea SDA debe mantenerse en
alto el estado de la línea de SCL, el dato en la línea SDA solo cambiara cuando
pase de alto a bajo el pulso de la línea del SCL.
I ♥AVR ´s

Secuencia de START y STOP


Para que el maestro pueda comunicarse con los esclavos, él primero debe notificar
al esclavo a través de una secuencia especial llamada Start y esta se produce
cuando SCL está en alto y la línea SDA cambia de alto a bajo, marcando el inicio
de la comunicación entre los dispositivos.

Secuencia START
SDA

SCL

Para finalizar la transmisión la línea SDA cambia de estado bajo a alto mientras la
línea SCL mantiene su estado.
I ♥AVR ´s

Secuencia STOP
SDA

SCL

PINES DEL AVR

En la imagen se tiene la distribución de pines del ATMEGA, se han resaltado las


ubicaciones de los pines SCL y SDA.
I ♥AVR ´s

La comunicación I2C se realiza de la siguiente manera:


La señal del pin SDA del maestro pasa de un alto a un bajo mientras la señal del
pin SCL esté a un alto, esto es el inicio de la comunicación I2C, al iniciar la
comunicación se genera una señal de reloj por el pin SCL del maestro y se empieza
a enviar los datos por el pin SDA.
El maestro enviará primero la dirección de identificación del esclavo con el que se
quiera comunicar junto con el bit de escritura o lectura, si el maestro quiere enviar
o escribir un dato este bit será 0, si el maestro quiere leer o recibir un dato este bit
será 1, la dirección del esclavo normalmente será de 7 bits.
Cada vez que el esclavo reciba un byte el esclavo responderá enviando un bit en 0
al maestro para indicar que se ha establecido la comunicación, este es un bit de
confirmación de que hay comunicación y se le llama ACK, si la comunicación no se
establece el valor del bit ACK será un 1.
Luego de haber enviado la dirección del esclavo y haber recibido el maestro el bit
de confirmación ACK el maestro enviará la dirección del registro del esclavo que se
quiera leer o escribir, el esclavo responderá enviando al maestro el bit de
confirmación ACK.
Luego el maestro enviará el dato si lo que se quiere es enviar o escribir un dato en
el registro del esclavo, el esclavo responderá enviando al maestro el bit de
confirmación ACK; pero si lo que se quiere es que el maestro reciba o lea algún dato
desde algún registro del esclavo, ocurrirá que si la recepción es correcta es maestro
enviará al esclavo el bit de confirmación ACK.
Por último y para finalizar la comunicación la señal del pin SDA pasará de un bajo
a un alto mientras la señal de reloj en el pin SCL este en un alto, en ese momento
se deja de generar la señal de reloj y la comunicación habrá terminado.

SDA D7 D6 D5 D4 D3 D2 D1 D0 ACK

SCL 1 2 3 4 5 6 7 8 9

Dato enviado desde el maestro hacia el esclavo


ESCENARIO ACKNOWLEDGE
Dato enviado desde el esclavo hacia el maestro
I ♥AVR ´s

CLOCK STRETCHING
Unas de las características del protocolo I2C es el ensanchamiento del pulso del
reloj, es un tipo de flujo de control. Si la dirección de un dispositivo esclavo no está
lista para procesar más información, éste sufrirá un ensanchamiento en el pulso del
reloj, hasta que esa pueda seguir recibiendo información, por lo tanto se esperara a
que el esclavo libere la línea SCL para poder transferir el siguiente bit.

Diagrama de Tiempo

Analicemos en primer lugar. Antes de empezar, todos sabemos lo que significan


estas líneas inclinadas, ¿verdad? Las líneas inclinadas son una representación de
la velocidad de respuesta del bus/ sistema/ dispositivo.
Lo ideal es que cada vez que una señal cambia su estado (de mayor a menor o
viceversa), se supone que debe hacerlo inmediatamente. Pero en el escenario real,
es casi imposible para que esto ocurra sin un lapso de tiempo. Las líneas inclinadas
se refieren a estos retardos de tiempo, también conocido como slew.
Muy bien, de vuelta a donde estábamos.
I ♥AVR ´s

• La operación comienza con una secuencia de START.


• Después de la secuencia de START, el maestro tiene que enviar a la dirección del
esclavo que quiere hablar. Esa es la dirección de 7 bits (MSB primero) seguido por
bit R / W 'determinar si desea leer desde el dispositivo o escribir en él.
• El esclavo responde mediante el ACK de la dirección. Si no se envía el ACK,
sabemos lo que hace el maestro, ¿verdad?
• Una vez que el esclavo reconoce la dirección, significa que ahora está listo para
enviar / recibir datos desde / hacia el Maestro. Así comienza la transferencia de
datos. La técnica ha sido siempre de 8 bits (MSB primero), y el receptor tiene que
enviar la señal ACK después de cada byte de datos recibidos.
• Cuando la operación ha terminado, el Maestro termina por generar una secuencia
de START. Como alternativa, el Maestro también podría comenzar con un START
repetida.
Hay tres casos posibles de datos transferibles
• Caso 1: Master-Slave transmisor-receptor
• Caso 2: Esclavo-transmisor para Master-receptor
• Caso 3: Bi-direccional (R / W) en la misma transferencia de datos

Caso 1: Maestro (transmisor) a Esclavo (receptor) transferencia de datos


Vamos a echar un vistazo a toda la transacción y luego analizarla.

• El maestro envía la secuencia de arranque para iniciar la transacción.


• Es seguido por el Maestro envío de Dirección del esclavo 7 bits y el R / W 'bit igual
a cero. Lo ponemos a cero porque el Maestro está escribiendo en el esclavo.
• El esclavo reconoce tirando el bit ACK baja.
• Una vez que el esclavo reconoce la dirección, el maestro puede ahora enviar datos
al esclavo byte a byte. El esclavo tiene que enviar el bit ACK después de cada byte
que recibe.
I ♥AVR ´s

• Esto continúa hasta esclavo ya no puede recibir datos y no envía el bit ACK.
• Esto es cuando el maestro se da cuenta de que el esclavo se ha vuelto loco (no
aceptar más), y se detiene la transacción (o reiniciar).
Vemos que la transferencia de datos nunca cambia su dirección. Los datos siempre
fluyen de maestro a esclavo, lo que hace que la configuración bastante fácil.
Un ejemplo de este caso sería como realizar operaciones de escritura de página en
un chip de memoria EEPROM.
Caso 2: Esclavo (transmisor) a Maestro (receptor) transferencia de datos.

• El maestro envía la secuencia de START, seguido por el 7-bits Slave address y el


R/W' bit igual a 1.
• Hemos establecido bit R / W 'a 1 porque el Maestro está leyendo del Esclavo.
• El esclavo reconoce la dirección, por lo tanto, está preparado para enviar datos
ahora.
• Esclavo mantiene en el envío de datos al maestro, y el maestro mantiene en el
envío de ACK al esclavo después de cada byte hasta que ya no puede aceptar más
datos.
• Cuando el maestro se siente como que termina la transacción, no se envía el ACK,
terminando así con la secuencia de parada.
Un ejemplo de este caso podría ser un convertidor de analógico a digital (ADC) el
envío de datos al microcontrolador continuamente. El microcontrolador acepta datos
siempre que quiere, después de lo cual se detiene/finaliza la ejecución.
I ♥AVR ´s

Caso 3: Bi-direccional de lectura y escritura en la misma transferencia de


datos

• El maestro envía la secuencia de START seguido por el 7-bits y la Slave address


R/W' bit.
• El esclavo reconoce la dirección.
• Dependiendo del valor del bit R/ W', lectura / escritura se realizan las operaciones
(como los dos casos anteriores).
• Cualquiera que sea el caso, puede ser, siempre termina con el receptor no
enviando el ACK.
• Hasta ahora, en los dos casos anteriores, hemos visto que el Maestro iba a cerrar
la conexión. Pero en este caso, el maestro intenta un START repetida.
• Y todo el proceso se repite otra vez, hasta que el Maestro decide parar.
Como podemos ver, un cambio de dirección de la transferencia de datos que podría
ocurrir dependiendo de bits de la R / W 'en toda la transacción.
Un ejemplo de este caso podría ser la realización de lectura secuencial de un chip
EEPROM. Es bidireccional porque la CPU escribe primero la dirección desde donde
le gustaría comenzar a leer, seguido por la lectura desde el dispositivo. Es como, a
menos que usted le dice al dispositivo desde el que desea iniciar la lectura, ¿cómo
podría empezar a enviarle los datos?

Ejemplo:
Mostrar como el master escribe el valor 11110000 a un esclavo con dirección
1001101.
Sol.
Las siguientes acciones son desempeñadas por el master:
I ♥AVR ´s

(1) El master pone de alto a bajo el pulso en SDA mientras, SCL está en alto
genera una condición de START para la transmisión.
(2) El master transmite 10011010 dentro del bus. Los primeros sietes bits
(1001101) indican la dirección del esclavo, y el octavo bit indica la operación
de escritura que empezara cuando el maestro escriba el siguiente byte dentro
del esclavo.
(3) El esclavo pone la línea del SDA en bajo para la señal del ACK, y decir que
esta lista para recibir el byte del dato.
(4) Después de recibir el ACK, el master transmite el byte de dato (11110000)
en la línea del SDA (MSB primero)
(5) Cuando el dispositivo esclavo recibe el dato, deja la línea SDA en alto para
la señal NACK. Esto informa al maestro que el esclavo recibió el ultimo byte
del dato y no necesita más.
(6) Después de recibir el NACK, el maestro sabe que no necesita enviar más
información. El master cambia la línea del SDA cuando la línea del SCL en
alto para transmitir la condición de parada y liberar el bus para otra función.
I ♥AVR ´s

I2C AVR PROGRAMACIÓN

Para programar la comunicación serial I2C AVR se recomienda mucho leer la hoja
de datos del AVR utilizado, es lo mejor que se puede hacer, como referencia se verá
para el ATMEGA328p, para lo que se utilizan los siguientes registros: el registro
TWBR, el registro TWCR, el registro TWSR, el registro TWDR, el registro TWAR, y
el registro TWAMR.

El registro TWBR se hace referencia cuando el microcontrolador AVR es utilizado


como maestro, en este registro se cargará el valor con el que se elige la velocidad
de transmisión de los datos, esto es la cantidad de bits por segundo que se enviarán
en la comunicación I2C AVR.
El valor a cargar en el registro TWBR se calcula con la siguiente fórmula que se
encuentra en la hoja de datos, que dependerán de la velocidad elegida, de la
frecuencia del oscilador utilizado y de un prescaler para la frecuencia del oscilador,
el prescaler puede ser 1, 4, 16 o 64, se elige mediante las combinaciones de los bits
1 y 0 del registro TWSR.
Velocidad=Fosc/(16+2*(TWBR)*prescaler)
Esta formula se puede expresar de la siguiente manera:
TWBR=((Fosc/Velocidad)-16)/(2*prescaler)
Si se quiere por ejemplo una velocidad de 400Khz, y el oscilador es de 8Mhz, con
un prescaler de 1, si en la fórmula anterior se reemplaza y se despeja, se tendrá:
I ♥AVR ´s

TWBR=((8000000/400000)-16)/(2*1)
de donde:
TWBR=2
Por lo que para obtener una velocidad de 400Khz se tendrá que cargar el registro
TWBR con 2.

El registro TWCR este es el registro de control del módulo TWI para la comunicación
I2C AVR

El bit7 TWINT este es el bit de reconocimiento de que ha ocurrido una interrupción


en caso de que esta esté habilitada la interrupción del módulo TWI al poner a uno
el bit0 TWIE, en el caso de no habilitar las interrupciones este será el bit más
utilizado ya que mediante la verificación del estado de este bit se podrá conocer si
se ha iniciado correctamente la comunicación I2C AVR, o también si se ha detenido
la comunicación, o también si se han enviado o recibido los datos correctamente.
El bit6 TWEA al poner este bit a 1 se habilita el uso del bit de reconocimiento ACK
El bit5 TWSTA Al poner este bit a 1 se da inicio a la comunicación I2C AVR
El bit4 TWSTO Al poner este bit a 1 se para o termina la comunicación I2C AVR.
El bit3 TWWC este bit se pone a 1 automáticamente indicando un error cuando se
quiere enviar o recibir un dato mientras no se dan las condiciones apropiadas.
El bit2 TWEN Al poner este bit a 1 se habilita el uso del módulo TWI para la
comunicación serial, mientras este bit esté a 0 no se podrá utilizar la comunicación
I2C AVR.
El bit1 este bit se pone a 0 ya que no se utiliza.
El bit0 TWIE Habilita el uso de la interrupción del módulo TWI.
El registro TWSR este registro se utiliza para averiguar en que estado se encuentra
el módulo TWI cuando se realiza la comunicación serial I2C AVR, en este registro
I ♥AVR ´s

también se encuentran los bits mediante los cuales se elige el prescaler para
obtener la velocidad de la comunicación I2C AVR.

Bit7 a bit3 estos 5 bits trabajan en forma automática generando diferentes


combinaciones, dependiendo de las combinaciones permite conocer en que estado
se encuentra la comunicación I2C AVR, para ello en la hoja de datos del AVR
utilizado se tienen unas tablas con lo que indican esta combinaciones, la siguiente
es por ejemplo para el caso cuando el ATMEGA328p se comporta como maestro y
está enviando un dato al esclavo:

Si las combinaciones de estos bits es por ejemplo 0x08 quiere decir que se ha dado
el inicio de la comunicación I2C AVR, las combinaciones de estos bits son utilizadas
dentro del programa para verificar que la comunicación transcurre con normalidad.
El bit2 no se utiliza se pone a 0.
I ♥AVR ´s

Los bits 1 y 0 con las combinaciones de estos bits se elige el prescaler a utilizar
para obtener la frecuencia de transmisión, de donde se obtiene el valor a cargar en
el registro TWBR, las combinaciones son las siguientes:

El registro TWDR en la comunicación I2C AVR en este registro se pondrá el dato


que se quiera transmitir hacia el esclavo, y también donde se encontrará el dato
recibido desde el esclavo, tiene esta doble función.
El registro TWAR en los bits del 7 al 1 de este registro se colocará la dirección del
microcontrolador AVR cuando este es utilizado como esclavo, el bit0 es para una
llamada general, al poner el bit0 a 0 el microcontrolador responderá solo si el
maestro envía su dirección, al poner este bit a 1 el AVR esclavo responde cuando
el maestro envíe la dirección 0x00.

INTERFAZ DE UNA APLICACIÓN EN UN TRANSMISION TIPICA DEL


PROTOCLO I2C
I ♥AVR ´s

El primer paso en una transmisión TWI es transmitir una condición START. Esto se
realiza escribiendo un valor específico en TWCR, instruyendo al hardware TWI para
transmitir una condición de START. El valor que debe escribir se describe más
adelante. Sin embargo, es importante que el bit TWINT se establezca en el valor
escrito. Escribir un uno a cero la bandera TWINT. El TWI no se iniciará ninguna
operación, siempre que el bit TWINT en TWCR se establece.
Inmediatamente después de la aplicación se ha aclarado TWINT, el TWI iniciar la
transmisión de la condición de START.
2. Cuando la condición de START ha sido transmitido, la Bandera TWINT en TWCR
se fija, y TWSR se actualiza con un código de estado que indica que la condición
de arranque se ha enviado correctamente.
3. El software de aplicación debe ahora examinar el valor de TWSR, para
asegurarse de que la condición de START se transmitió con éxito. Si TWSR indica
lo contrario, el software de aplicación pudiera tomar ciertas medidas especiales,
como llamar a una rutina de error. Suponiendo que el código de estado es como se
esperaba, la aplicación debe cargar SLA + W en TWDR. Recuerde que TWDR se
utiliza tanto para la dirección y los datos. Después TWDR ha cargado con la
deseada SLA + W, un valor específico se debe escribir en TWCR, instruyendo el
hardware TWI para transmitir el SLA + W presente en TWDR. El valor que debe
escribir se describe más adelante. Sin embargo, es importante que el bit TWINT se
establece en el valor escrito. Escribir un uno a cero la bandera TWINT. El TWI no
iniciará ninguna operación tanto como el bit TWINT en TWCR es cambiado
inmediatamente después de la aplicación se ha aclarado TWINT, el TWI inicia la
transmisión del paquete de direcciones.
4. Cuando el paquete de dirección se ha transmitido, la Bandera TWINT en TWCR
se fija, y TWSR se actualiza con un código de estado que indica la dirección de
paquetes que se ha enviado satisfactoriamente. El código de estado también
reflejará si un esclavo reconoce el paquete o no.
5. El software de aplicación debe ahora examinar el valor de TWSR, para
asegurarse de que el paquete de dirección se ha transmitido correctamente, y que
I ♥AVR ´s

el valor del ACK fue como se esperaba. Si TWSR indica lo contrario, el software de
aplicación pudiera tomar ciertas medidas especiales, como llamar a una rutina de
error. Suponiendo que el código de estado es como se esperaba, la aplicación debe
cargar un paquete de datos en TWDR. Posteriormente, un valor específico se debe
escribir en TWCR, instruyendo el hardware TWI para transmitir el paquete de datos
presente en TWDR. El valor que debe escribir se describe más adelante. Sin
embargo, es importante que el bit TWINT se establece en el valor escrito. Escribir
un uno a cero la bandera TWINT. El TWI no se iniciará ninguna operación, siempre
que el bit TWINT en TWCR se establece. Inmediatamente después de la aplicación
ha despejado TWINT, el TWI iniciará la transmisión del paquete de datos.
6. Cuando el paquete de datos ha sido transmitido, la Bandera TWINT en TWCR se
fija, y TWSR se actualiza con un código de estado que indica que el paquete de
datos se ha enviado correctamente. El código de estado también reflejará si un
esclavo reconoce el paquete o no.
7. El software de aplicación debe ahora examinar el valor de TWSR, para
asegurarse de que los paquetes de datos se han transmitido correctamente, y que
el valor del bit ACK fue como se esperaba. Si TWSR indica lo contrario, el software
de aplicación pudiera tomar ciertas medidas especiales, como llamar a una rutina
de error. Suponiendo que el código de estado es como se esperaba, la aplicación
debe escribir un valor determinado a TWCR, instruyendo el hardware TWI para
transmitir un estado de STOP. El valor que debe escribir se describe más adelante.
Sin embargo, es importante que el bit TWINT se establece en el valor escrito.
Escribir un uno a cero la bandera TWINT. El TWI no se iniciará ninguna operación,
siempre que el bit TWINT en TWCR esté cambiado. Inmediatamente después de la
aplicación se ha aclarado TWINT, el TWI iniciará la transmisión de la condición de
STOP. Tenga en cuenta que TWINT no se establece después de una condición de
parada se ha enviado.
A pesar de que este ejemplo es simple, que muestra los principios implicados en
todas las transmisiones de inmersión recíproca. Estos se pueden resumir como
sigue:
I ♥AVR ´s

Cuando el TWI ha terminado una operación y espera respuesta de las


aplicaciones, la Bandera TWINT se establece. La línea SCL se tira bajo hasta
TWINT se borra.
Cuando se establece el indicador TWINT, el usuario debe actualizar todos los
registros de inmersión recíproca con el valor correspondiente para el próximo ciclo
de bus TWI. Como un ejemplo, TWDR debe ser cargado con el valor a transmitir en
el siguiente ciclo de bus.
Después de haber completado todas las actualizaciones TWI Registro y otras
tareas de software de aplicación pendientes, TWCR está escrito. Al escribir TWCR,
el bit TWINT debe establecerse. Escribir un uno a cero la bandera TWINT. El TWI
Después comenzará la ejecución de cualquier operación se especifica en la
configuración TWCR.

LIBRERÍA SENCILLA I2C PARA LA COMUNICACIÓN CON OTROS DISPOSITIVOS


Elaborada y testeada en Atmel Studio 7.0

EJEMPLO .- IMPLEMENTACION DE UNA LIBRERÍA PARA EL USO DEL BUS I2C

#ifndef I2C_H_
#define I2C_H_

void i2c_iniciar(); //función para iniciar el módulo TWI I2C


AVR
void i2c_espera(); //función de espera
void i2c_inicia_com(); //función que inicia la comunicación I2C
AVR
void i2c_detener(); //función que detiene la comunicación I2C
AVR
void i2c_envia_dato(unsigned char ); //función para enviar o
escribir
//datos en el esclavo
unsigned char i2c_recibe_dato_ack(); //función para recibir o
leer datos del esclavo
//enviando el bit ACK si se quiere leer mas datos
//después del último leído
I ♥AVR ´s

unsigned char i2c_recibe_dato_nack(); //función para recibir o


leer datos del esclavo
//sin enviar el bit ACK si no se quiere leer mas datos
//después del último leido
uint8_t i2c_estado_com(); //función para averiguar el estado de
la comunicación I2C AVR
//útil para detectar errores

//////////////////////////////////////////////////////////////////
//inicialización del módulo TWI I2C AVR en el ATMEL STUDIO en una
función////
//para el ATMEGA88 como maestro
//a 400KHz con un oscilador de 8Mhz

void i2c_iniciar(){
PORTC|=((1<<4)|(1<<5)); //activa resistencias pull upp para
SCL y SDA
TWBR=2; //velocidad 400Khz, Fosc 8Mhz,
prescaler de 1
TWCR|=(1<<TWEN); //módulo TWI iniciado
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Función de espera: mientras el bit7 o bit TWINT del registro
// TWCR sea 0, el IC2 AVR se esperará
// antes de realizar algún trabajo

void i2c_espera(){
while ((TWCR & (1<<TWINT)) == 0);//espera mientras el bit de
interrupcion sea 0
}

////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
Función de inicio de la comunicación I2C AVR

void i2c_inicia_com() {
I ♥AVR ´s

TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);//bandera de
interrupción a 1, start, habilita I2C AVR
i2c_espera(); //espera mientras el bit TWINT sea 0
}

////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Función de parada de la comunicación I2C I2C

void i2c_detener() {
TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN);//bandera de
interrupción a 1, detener, habilita I2C AVR
}

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//Función de transmisión de datos del maestro al esclavo

void i2c_envia_dato(unsigned char dato) {


TWDR = dato;
TWCR = (1<<TWINT)|(1<<TWEN);//para empezar a enviar el dato
i2c_espera();//cuando TWINT se ponga a 1 se habrá terminado
de enviar el dato
}

/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//Función de recepción de datos enviados por el esclavo al maestro
//esta función es para leer los datos que están en el esclavo
//en forma continua, esto es tras leer uno se volverá a leer otro

unsigned char i2c_recibe_dato_ack(){//maestro envia ack para


seguir recibiendo
//mas datos
TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWEA);
i2c_espera();
return TWDR;
}
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
//Función de recepción de datos enviados por el esclavo al maestro
I ♥AVR ´s

//esta función es para leer solo un dato desde el esclavo


//esto es tras leer uno ya no se volverá a leer otro

unsigned char i2c_recibe_dato_nack(){//maestro no envia ack para


no seguir recibiendo
//mas datos
TWCR = (1<<TWINT)|(1<<TWEN);
i2c_espera();
return TWDR;
}

/////////////////////////////////////////////////////////////////
//función para averiguar el estado de la comunicación I2C AVR
//útil para detectar errores, el valor que retorna esta función
//se compara con el estado que deberían indicar los bits del 7 al
3
//del registro TWSR según tabla, durante la comunicación I2C AVR,

uint8_t i2c_estado_com(){
uint8_t estado; //variable donde se almacena el estado
de la comunicación
//I2C AVR
estado = TWSR & 0xf8; //en la variable estado se guarda el
valor de los 5 bits de
//mas peso del registro TWSR seguidos de 3 ceros,
//el número obtenido indica
//el estado en que se encuentra la comunicación I2C AVR

return estado; //la función retorna el estado de la


comunicación
}

#endif /* I2C_H_ */

Referencias:

 microcontroladores-mrelberni.com/i2c-avr-comunicacion-serial-twi/
 maxembedded.com/2014/02/inter-integrated-circuits-i2c-basics/
 www.embedds.com/programming-avr-i2c-interface/
 AVR PROGRAMMING IN C, editorial 2014
 DATASHEET AVR ATMEGA328P

También podría gustarte