I have the following I2C configuration with an ATmega168 (1 MHz) as the master and an Arduino Uno (16 MHz) as the slave.
The command for the LED connected to the slave comes from the master and vice versa. I can't get the I2C to work. The LEDs are at whatever value I initially set ledValue to be, and it is not getting it from the slave/master.
The code running on the master.
#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;
}
The code running on the slave.
#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;
}
}