Quiero establecer una conexión I2C entre dos atmega2560. El primero es trabajar como maestro, y el segundo como esclavo. El maestro funciona en un modo de transmisor y el esclavo funciona como receptor.
En el lado del maestro: el maestro parece funcionar correctamente, porque todo el código proviene de la hoja de datos. El maestro puede enviar una condición de inicio. Cuando escribe la dirección del esclavo, recibe un NACK del esclavo. Cuando eso sucede, el maestro intenta comenzar desde el principio.
En el lado del esclavo: el esclavo no puede reconocer la condición de inicio, y el indicador TWINT nunca sube. Es por eso que el registro de estado de esclavo TWSR nunca se actualiza y es igual a 0xF8 .
Estoy usando el esquema eléctrico de la hoja de datos, 2 resistencias de extracción 10kOm . Así que tal vez mi código de esclavo no es correcto.
La hoja de datos dice
Esto ocurre entre otros estados, y cuando el TWI no está involucrado en una transferencia en serie.
¿Eso significa que el esclavo ni siquiera está conectado a las líneas TWI?
Ocurrieron cosas interesantes cuando intenté conectar el maestro a un RTC D1307. El maestro puede enviar direcciones y datos del esclavo y el esclavo puede recibirlos. Pero solo N veces. La transmisión es así: el Maestro envía SLA_R, recibe ACK, envía Datos, recibe ACK. Y en el primer intento, solo el maestro puede enviar 5 veces y luego la línea SDA baja. En el segundo intento puede enviar solo 2 veces, SDA baja, 1 vez, SDA baja, 15 veces, SDA baja. Y eso continúa repetidamente.
void master(){
//init master
DDRC = 0xff;
TWSR = (1<<TWPS0); //TWPS = 4
TWBR = 40; //F_SLAVE > SCL * 16
TWCR = (1<<TWEN);
uint8_t seconds;
uint8_t minutes;
uint8_t hours;
uint8_t day;
uint8_t date;
uint8_t month;
uint8_t year;
uint8_t address = 0b1101000; //Slave address
//_delay_ms(2000);
while(1){
TWIStart();
if (TW_STATUS == TW_START){
PORTC ^= 1<<0;
}
TWIWrite((address << 1) | READ);
switch (TW_STATUS) {
case TW_MR_SLA_ACK: {
PORTC ^= 1<<1; //LEDs for indicating status
break;
}
case TW_MR_SLA_NACK: {
PORTC ^= 1<<2;
break;
}
default:{
PORTC ^= 1<<3;
}
}
seconds = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC ^= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC ^= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
minutes = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
hours = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
day = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
date = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
month = TWIRead();
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
year = toDec(TWIRead());
switch (TW_STATUS)
{
case TW_MR_DATA_ACK:{
PORTC |= 1<<4;
break;
}
case TW_MR_DATA_NACK:{
PORTC |= 1<<5;
break;
}
default:{
PORTC = 0x00;
}
}
if(year == 15){
PORTC |= 1<<7;
}
TWIStop();
_delay_ms(1000);
}