Como usar I2C / TWI (interface de dois fios) no AVR ATmega32- (Parte 36/46)

Cómo utilizar I2C/TWI (interfaz de dos cables) en el AVR ATmega32- (Parte 36/46)

Este artículo explora la interfaz TWI entre dos controladores ATmega32. Se recomienda a los lectores que consulten la comunicación TWI y los registros TWI del ATmega32 antes de continuar.
TWI funciona en cuatro modos:
1. MASTER como transmisor.
dos. MAESTRO como receptor.
3. ESCLAVO como receptor.
4. SLAVE como transmisor.
Generalmente los modos 1 y 3 y los modos 2 y 4 se utilizan juntos. Este artículo explica el uso de estos cuatro modos en un experimento.
Objetivo: Establecer comunicación entre dos ATmega32 utilizando la interfaz TWI. Primero, el maestro comienza a enviar datos y luego el esclavo transmite el complemento de datos recibidos al maestro. Cuando el Maestro recibe los datos suplementados, desplaza los datos originales hacia la izquierda. Este proceso de transmisión y recepción continúa. Cuando el valor de los datos alcanza 0x80, se repite todo el proceso. Al principio, el valor de los datos originales es 0x01. El valor recibido se muestra en PORTB en ambos extremos.
Descripción del circuito:
Realice las conexiones como se muestra en el diagrama del circuito.
Explicación del código del controlador MASTER:
Paso 1: inicialización maestra.
La inicialización MASTER significa configurar la frecuencia del reloj TWI (SCL). Esto se hace configurando la tasa de bits en TWBR y los bits del preescalador en TWSR.

Equação da frequência do clock TWI para inicializar o mestre no AVR

Fig. 2: Ecuación de frecuencia de reloj TWI para inicializar el maestro en el AVR

 void TWI_init_master(void) // Función para inicializar el maestro
 {
   TWBR=0x01;   // tasa de bits
   TWSR=(0<<TWPS1) (0<<TWPS0);   // Configurando bits preescalar
   // frecuencia SCL= F_CPU/(16+2(TWBR).4^TWPS)
 }

Paso 2: Enviar condición inicial
La condición inicial en TWI fue explicada anteriormente. El microcontrolador AVR tiene registros incorporados que facilitan mucho este trabajo.
1. Borre la bandera TWINT escribiéndole una lógica.
dos. Establezca el bit TWSTA para enviar la condición de inicio.
3. Establezca el bit TWEN para inicializar TWI.
4. Supervise el estado de la bandera TWINT.
5. Verifique el byte ACK (usando la condición while ya que la frecuencia SCL es muy pequeña en comparación con la frecuencia del reloj del microcontrolador). El byte ACK se puede comparar monitoreando el estado de TWSR.
 anular TWI_start(anular)
 {
   // Borrar el indicador de interrupción TWI, poner la condición de inicio en SDA, habilitar TWI
   TWCR= (1<<TWINT) (1<<TWSTA) (1<<TWEN);
   mientras(!(TWCR & (1<<TWINT))); //Esperar hasta que se transmita la condición de inicio. 
mientras((TWSR y 0xF8)!= 0x08); // Comprobar el acuse de recibo
 }
Paso 3: enviar la dirección del esclavo, el bit de dirección de datos (escritura) y esperar la señal ACK
Bit de condição inicial no TWI
Fig. 3: Bit de condición inicial en TWI
Estos tres procesos están controlados por los registros TWI del AVR .
1. Coloque la dirección esclava de siete bits y el bit de control de dirección en el TWDR.
dos. Borre la bandera TWINT.
3. Habilite TWI escribiendo uno lógico en el bit TWEN.
4. Supervise el estado del indicador TWINT; el indicador TWINT se borrará cuando se transmitan datos en TWDR.
5. Compruebe el reconocimiento correcto.
 void TWI_read_address (datos de caracteres sin firmar)
 {
   TWDR=fecha;   // Dirección y lectura de instrucciones.
   TWCR=(1<<TWINT) (1<<TWEN);   // Borrar el indicador de interrupción TWI, habilitar TWI
   mientras (!(TWCR & (1<<TWINT))); // Espere hasta que se reciba el byte TWDR completo
   mientras((TWSR y 0xF8)!= 0x40); // Comprobar el acuse de recibo
 }
Paso 4: envíe datos de 8 bits y espere ACK
Transferência de dados em TWI do AVR
Fig. 4: Transferencia de datos en TWI desde el AVR
1. Coloque datos de 8 bits en TWDR.
8 bits = dirección esclava de 7 bits + bit de dirección de datos (escritura = 0).
dos. Borre la bandera TWINT.
3. Establezca el bit TWEN para habilitar TWI.
4. Supervise el estado del indicador TWINT para completar la transmisión de datos.
5. Comprobar reconocimiento.
 void TWI_write_data (datos de caracteres sin firmar)
 {
   TWDR=fecha;   //poner datos en TWDR
   TWCR=(1<<TWINT) (1<<TWEN);   // Borrar el indicador de interrupción TWI, habilitar TWI
   mientras (!(TWCR & (1<<TWINT))); // Espere hasta que se transmita el byte TWDR completo
   mientras((TWSR y 0xF8) != 0x28); // Comprobar el acuse de recibo
 }
Paso 5: Enviar la condición STOP

Bit de condição TWI STOP

Fig.5: Bit de condición TWI STOP

Para enviar la condición de parada utilice TWSTO
1. Borre la bandera TWINT.
dos. Establecer VECE bits
3. Escriba uno lógico en el bit TWSTO para enviar la condición STOP en la línea SDA y SCL.
4. Supervise el estado del bit TWSTO, ya que borrar el bit TWSO significa que se ha transmitido la condición de parada.
 anular TWI_stop(anular)
 {
   // Borrar el indicador de interrupción TWI, poner la condición de parada en SDA, habilitar TWI
   TWCR= (1<<TWINT) (1<<TWEN) (1<<TWSTO);
   mientras(!(TWCR & (1<<TWSTO))); // Esperar hasta que se transmita la condición de parada
 }
Hasta ahora la transmisión de datos del lado esclavo está completa, el MAESTRO está funcionando en modo uno. Según el objetivo, los datos recibidos por MASTER se muestran en PORTB. A continuación se muestra el diagrama de flujo de MASTER como transmisor (modo uno).

Fluxograma do MASTER como transmissor na interface TWI usando AVR

Fig. 6: Diagrama de flujo de MASTER como transmisor en la interfaz TWI usando AVR

A partir de aquí el MASTER estaría trabajando en modo dos, es decir, el MASTER pasaría a ser un receptor. El AVR TWI funciona en modo 2.
Paso 6: Enviar la condición de INICIO en las líneas de autobús
Este paso es muy similar al anterior.
Nota : En el Paso 6, la condición de INICIO se envía después de la condición de PARADA. Si se envía una condición de inicio más antes de la condición de PARADA intermedia, se denomina condición de inicio repetida. La condición de inicio repetida es la misma que la condición de INICIO, pero la única diferencia está entre las confirmaciones. Para obtener más detalles sobre el arranque repetitivo, consulte la hoja de datos. Si los datos se envían continuamente en la misma dirección, no hay necesidad de una condición de inicio, un inicio repetitivo o una condición de parada intermedia. Los segundos datos se pueden transmitir inmediatamente después de recibir el acuse de recibo del primer byte de datos (como se muestra en el diagrama de flujo anterior).
Paso 7: enviar la dirección del esclavo y el bit de dirección de datos (lectura) y esperar la señal ACK
1. Coloque datos de 8 bits en TWDR.
8 bits = dirección esclava de 7 bits + bit de dirección de datos (lectura = 1).
dos. Borre la bandera TWINT.
3. Establezca el bit TWEN para habilitar TWI.
4. Supervise el estado del indicador TWINT para completar la transmisión de datos.
5. Comprobar reconocimiento.
 void TWI_read_address (datos de caracteres sin firmar)
 {
   TWDR=fecha;   // Dirección y lectura de instrucciones.
   TWCR=(1<<TWINT) (1<<TWEN);   // Borrar el indicador de interrupción TWI, habilitar TWI
   mientras (!(TWCR & (1<<TWINT))); // Espere hasta que se reciba el byte TWDR completo
   mientras((TWSR y 0xF8)!= 0x40); // Comprobar el acuse de recibo
 }
Paso 8: leer datos del bus SDA
1. Borrar bandera TWINT
dos. Establezca el bit TWEN, habilite TWI
3. Supervise el estado del indicador TWINT, ya que el indicador TIWNT establecido indica que se ha recibido el valor en TWDR.
4. Comprobar reconocimiento. Si el maestro quiere recibir el último byte del esclavo, el estado del registro TWSR será 0x58. Después de recibir el último byte, el maestro emite una condición de inicio repetitiva para continuar la comunicación o el maestro debe dar una condición de parada para detener el proceso de comunicación. De lo contrario, si el maestro quiere seguir recibiendo más bytes del esclavo, el estado del registro TWSR será 0x50.
Para confirmar el guardado del último byte, se utiliza el bit TWEA durante la transmisión de datos. Si se establece el bit TWEA, la recepción será continua en el lado MAESTRO. Y si el bit TWEA está bajo, el MAESTRO ordena al esclavo que envíe el último byte.
5. Obtenga los datos recibidos. Y enviarlo a PORTB.
 anular TWI_read_data (anular)
 {
   TWCR=(1<<TWINT) (1<<TWEN);   // Borrar el indicador de interrupción TWI, habilitar TWI
   mientras (!(TWCR & (1<<TWINT))); // Espere hasta que se transmita el byte TWDR completo
   mientras((TWSR y 0xF8) != 0x58); // Comprobar el acuse de recibo
   recv_data=TWDR;
   PORTB=recv_data;
 }
Paso 9: Enviar condición DETENER
La condición de parada ya ha sido explicada.

Fluxograma do MASTER como receptor na interface TWI usando AVR

Fig. 7: Diagrama de flujo de MASTER como receptor en la interfaz TWI usando AVR

Explicación del código para el controlador SLAVE:
Paso 1: Inicializando el control Slave R
La inicialización del controlador esclavo se realiza asignando una dirección al esclavo. La dirección esclava de siete bits se completa en el Registro de direcciones esclavas TWI (TWAR). El LSB del TWAR, es decir, el bit TWGCE, se utiliza para permitir que el esclavo reconozca la dirección de llamada general (0x00).
 void TWI_init_slave(void) // Función para inicializar el esclavo
 {
   TWAR=0x20;   // Completa la dirección del esclavo en TWAR
 }
Paso 2: Verifique el estado de registro de TWSR
Si el valor de TWSR es 0x60, significa que los datos enviados por el maestro en el siguiente paso deben ser leídos solo por este esclavo específico y el esclavo devuelve el acuse de recibo al maestro correspondiente a la operación de lectura. Si el estado de TWSR es 0x70, se solicita a SLAVE que lea los datos en la llamada general (0x00). En esta fase el ESCLAVO actúa como receptor. AVR TWI está funcionando en modo 3.
1. Borre la bandera TWIN.
dos. Habilite TWI.
3. Configure TEWA para recibir reconocimiento.
4. Supervise el estado de la bandera TWINT.
5. Coincide con el estado de TWSR. Si el estado es 0x60, lea los datos o salte a (1)
void TWI_match_read_slave(void) //Función para hacer coincidir la dirección del esclavo y el bit de dirección del esclavo (lectura)
 {
   while((TWSR & 0xF8)!= 0x60) // Bucle hasta que se haya recibido el reconocimiento correcto
   {
      // Obtener confirmación, habilitar TWI, borrar el indicador de interrupción TWI
      TWCR=(1<<TWEA) (1<<TWEN) (1<<TWINT);
      mientras (!(TWCR & (1<<TWINT))); //Esperar la bandera TWINT
   }
 }
Paso 3: leer los datos
Leer los datos enviados por MASTER.
1. Borre la bandera TWINT.
dos. Habilite TWI.
3. Configure TWEA para recibir ACK.
4. Obtenga el formulario de datos TWDR y muéstrelo en PORTB.


 

TWI_read_slave vacío (vacío)
{
// Borrar el indicador de interrupción TWI, obtener confirmación, habilitar TWI
TWCR= (1< mientras (!(TWCR & (1< mientras((TWSR y 0xF8)!=0x80); //Esperar confirmación
recv_data=TWDR; // Obtiene el valor TWDR
PORTB=recv_dados; // envía el valor recibido en PORTB
}

Escravo como receptor na interface TWI usando AVR
Fig. 8: Esclavo como receptor en la interfaz TWI usando AVR
A partir de aquí, el esclavo se convierte en transmisor a petición del maestro para enviar datos. El AVR TWI funciona en modo 4.
Paso 4: Verifique el estado de registro de TWSR
Si el valor de TWSR es 0xA8, significa que el maestro quiere recibir datos del esclavo específico y el esclavo devuelve el acuse de recibo al maestro correspondiente a la operación de escritura.
1. Borre la bandera TWIN.
dos. Habilite TWI.
3. Configure TEWA para recibir reconocimiento.
4. Supervise el estado de la bandera TWINT.
5. Coincide con el estado de TWSR. Si el estado es 0xA8 envíe datos o pase a (1)
 void TWI_match_write_slave(void) //Función para hacer coincidir la dirección del esclavo y el bit de dirección del esclavo (escritura)
 {
   while((TWSR & 0xF8)!= 0xA8) // Bucle hasta que se haya recibido el reconocimiento correcto
   {
      // Obtener confirmación, habilitar TWI, borrar el indicador de interrupción TWI
      TWCR=(1<<TWEA) (1<<TWEN) (1<<TWINT);
      mientras (!(TWCR & (1<<TWINT))); //Esperar la bandera TWINT
   }
 }
Paso 5: escribir datos en el bus SDA
1. Pon los datos en el TWDR.
dos. Habilite TWI.
3. Pega la bandera TWINT.
4. Supervise la bandera TWINT. Como se aclara, significa que los datos han sido enviados.
5. Marque ACK. Como el bit TWEA no se estableció al escribir datos en el bus SDA, significa que el maestro es el último dato en enviarse y a su vez recibe un NOT ACK y el estado TWSR pasa a ser 0xC0. Y si el bit TWEA se configuró durante la transmisión de datos, recibe un ACK y el estado de TWSR pasa a ser 0xB8. Para más detalles consultar la ficha técnica.


 

void TWI_write_slave(void) // Función para escribir datos
{
TWDR= escribir_datos; // Llena el registro TWDR con los datos a enviar
TWCR= (1<
mientras((TWSR y 0xF8) != 0xC0); //Esperar reconocimiento
}

Escravo como Transmissor e Interface TWI usando AVR

Fig. 9: Esclavo como transmisor en la interfaz TWI usando AVR

Código fuente del proyecto

###


 //Programa para el modo maestro
// Verifique el Código 2 para ver el programa en modo esclavo #incluir #incluir #incluir vacío TWI_start(vacío); nulo TWI_repeated_start(nulo); vacío TWI_init_master(vacío); void TWI_write_address (carácter sin firmar); void TWI_read_address (carácter sin firmar); void TWI_write_data(carácter sin firmar); nulo TWI_read_data(nulo); anular TWI_stop(anular); dirección de carácter sin signo = 0x20, lectura = 1, escritura = 0; carácter sin firmar write_data = 0x01, recv_data; int principal (vacío) { _delay_ms(2000); DDRB=0xff; TWI_init_master; //Función para inicializar TWI mientras(1) { si(escribir_datos==0x00) escribir_datos=1; TWI_inicio; //Función para enviar condición de inicio TWI_write_address(dirección+escritura); //Función para escribir bits de dirección y dirección de datos en SDA TWI_write_data(escribir_datos); //Función para escribir datos al esclavo TWI_parada; //Función para enviar condición de parada _delay_ms(10); // retraso de 10 milisegundos TWI_inicio; TWI_read_address(dirección+lectura); //Función para escribir dirección y bit de dirección de datos (lectura) en SDA TWI_read_data; //Función para leer datos del esclavo TWI_parada; _delay_ms(1000); escribir_datos = escribir_datos * 2; } } void TWI_init_master(void) // Función para inicializar el maestro { TWBR=0x01; // tasa de bits TWSR=(0< //Configurando bits preescalar // Frecuencia SCL= F_CPU/(16+2(TWBR).4^TWPS) } vacío TWI_start(vacío) { // Borrar el indicador de interrupción TWI, establecer la condición de inicio en SDA, habilitar TWI TWCR= (1< mientras(!(TWCR & (1< mientras((TWSR y 0xF8)!= 0x08); //Comprobar reconocimiento } vacío TWI_repeated_start(nulo) { // Borrar el indicador de interrupción TWI, establecer la condición de inicio en SDA, habilitar TWI TWCR= (1< mientras(!(TWCR & (1< mientras((TWSR y 0xF8)!= 0x10); //Comprobar reconocimiento } void TWI_write_address (datos de caracteres sin firmar) { TWDR=datos; // Dirigir y escribir instrucciones TWCR=(1< mientras (!(TWCR & (1< mientras((TWSR y 0xF8)!= 0x18); //Comprobar reconocimiento } void TWI_read_address (datos de caracteres sin firmar) { TWDR=datos; // Dirección y lectura de instrucciones. TWCR=(1< mientras (!(TWCR & (1< mientras((TWSR y 0xF8)!= 0x40); //Comprobar reconocimiento } void TWI_write_data (datos de caracteres sin firmar) { TWDR=datos; //poner datos en TWDR TWCR=(1< mientras (!(TWCR & (1< mientras((TWSR y 0xF8) != 0x28); //Comprobar reconocimiento } TWI_read_data vacío (nulo) { TWCR=(1< mientras (!(TWCR & (1< mientras((TWSR y 0xF8) != 0x58); //Comprobar reconocimiento recv_data=TWDR; PORTB=recv_dados; } vacío TWI_stop(vacío) { // Borrar el indicador de interrupción TWI, colocar la condición de parada en SDA, habilitar TWI TWCR= (1< mientras(!(TWCR & (1< }

###

Código fuente del proyecto

###



 //Programa para modo esclavo
#incluir #incluir vacío TWI_init_slave(vacío); nulo TWI_match_read_slave(nulo); vacío TWI_read_slave(vacío); nulo TWI_match_write_slave(nulo); vacío TWI_write_slave(void); carácter sin firmar write_data, recv_data; int principal (vacío) { DDRB=0xff; TWI_init_slave; //Función para inicializar el esclavo mientras(1) { TWI_match_read_slave; //Función para combinar la dirección del esclavo y el bit de dirección del esclavo (lectura) TWI_read_slave; //Función para leer datos write_data=~recv_data; // Alternar datos recibidos TWI_match_write_slave; //Función para combinar la dirección del esclavo y el bit de dirección del esclavo (escritura) TWI_write_slave; //Función para escribir datos } } void TWI_init_slave(void) // Función para inicializar el esclavo { TWAR=0x20; //Completa la dirección del esclavo para TWAR } void TWI_write_slave(void) // Función para escribir datos { TWDR= escribir_datos; // Llena el registro TWDR con los datos a enviar TWCR= (1< mientras((TWSR y 0xF8) != 0xC0); //Esperar reconocimiento } void TWI_match_write_slave(void) //Función para hacer coincidir la dirección del esclavo y el bit de dirección del esclavo (escritura) { mientras((TWSR y 0xF8)!= 0xA8) // Bucle hasta que se reciba el acuse de recibo correcto { // Obtener confirmación, habilitar TWI, borrar el indicador de interrupción TWI TWCR=(1< mientras (!(TWCR & (1< } } TWI_read_slave vacío (vacío) { // Borrar el indicador de interrupción TWI, obtener confirmación, habilitar TWI TWCR= (1< mientras (!(TWCR & (1< //Espera la bandera TWINT mientras((TWSR y 0xF8)!=0x80); //Esperar confirmación recv_data=TWDR; // Obtiene el valor TWDR PORTB=recv_dados; // envía el valor recibido en PORTB } void TWI_match_read_slave(void) //Función para hacer coincidir la dirección del esclavo y el bit de dirección del esclavo (lectura) { while((TWSR & 0xF8)!= 0x60) // Bucle hasta que se reciba el reconocimiento correcto { // Obtener confirmación, habilitar TWI, borrar el indicador de interrupción TWI TWCR=(1< mientras (!(TWCR & (1< } }

###

Diagramas de circuito

Diagrama de circuito de cómo utilizar la interfaz I2C-TWI de dos cables en AVR-ATmega32

Componentes del proyecto

  • ATmega32
  • CONDUJO

Vídeo del proyecto

Regresar al blog

Deja un comentario

Ten en cuenta que los comentarios deben aprobarse antes de que se publiquen.