Tengo la siguiente configuración I2C con un ATmega168 (1 MHz) como maestro y un Arduino Uno (16 MHz) como esclavo.
El comando para el LED conectado al esclavo proviene del maestro y viceversa. No consigo que el I2C funcione. Los LED están en cualquier valor que inicialmente puse ledValue, y no lo está obteniendo del esclavo / maestro.
El código que se ejecuta en el maestro.
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint8_t slaveAddress = 5;
volatile uint8_t ledValue = 0;
volatile uint8_t refValue = 100;
volatile uint8_t rw;
void send_start(){ TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWSTA) | (1 << TWEN) | (1 << TWIE); }
void send_stop(){ TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWSTO) | (1 << TWEN) | (1 << TWIE); }
void send_data(){ TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); }
ISR(TWI_vect)
{
volatile uint8_t status = TWSR & 0xF8;
if(status == 0x08) // start send successfully - now send SLA+R/W
{
TWDR = (slaveAddress << 1) + rw;
send_data();
return;
}
if(status == 0x50 || status == 0x58) //receive mode - data received - read it - send stop
{
ledValue = TWDR;
send_stop();
return;
}
if(status == 0x18 || status == 0x20) //transmit mode - SLA+W successfully sent - now send data
{
TWDR = refValue; //data to be transmitted
send_data();
return;
}
if(status == 0x28 || status == 0x30) //transmit mode - data successfully sent - now send stop
{
send_stop();
return;
}
//anything else - clear TWINT
TWCR |= (1 << TWINT);
}
void initialize_pwm()
{
DDRD |= (1 << DDD3);
TCCR2A |= (1 << COM2B1) | (1 << WGM20);
TCCR2B |= (1 << CS20);
}
int main(void)
{
initialize_pwm();
TWBR = 0;
//TWSR &= ~((1 << TWPS1) | (1 << TWPS0)); // prescaler 1
// SCL = 1 MHz/(16 + 2*0*1) = 1/16 MHz
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE);
sei();
while(1)
{
rw = 1; //read
send_start();
_delay_ms(1000);
OCR2B = ledValue;
rw = 0; //write
send_start();
}
return 0;
}
El código que se ejecuta en el esclavo.
#include <stdint.h>
#include <util/delay.h>
#include <avr/interrupt.h>
volatile uint8_t slaveAddress = 5;
volatile uint8_t ledValue = 0;
volatile uint8_t refValue = 100;
void send_data(){ TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); }
ISR(TWI_vect)
{
volatile uint8_t status = TWSR & 0xF8;
if(status == 0xA8) // trasmit mode - master sent SLA+R - now send data back
{
TWDR = refValue; //data to be transmitted
send_data();
return;
}
if(status == 0x80 || status == 0x88) // receive mode - master sent data after SLA+W - read it
{
ledValue = TWDR;
TWCR |= (1 << TWINT);
return;
}
//anything else - clear TWINT
TWCR |= (1 << TWINT);
}
void initialize_pwm()
{
DDRD |= (1 << DDD3);
TCCR2A |= (1 << COM2B1) | (1 << WGM20);
TCCR2B |= (1 << CS20);
}
int main(void)
{
initialize_pwm();
TWAR = (slaveAddress << 1);
TWCR = (1 << TWINT) | (1 << TWEN) | ( 1 << TWIE);
sei();
while(1)
{
_delay_ms(1000);
OCR2B = ledValue;
}
}