Ok, I am trying to create an I2C library for avr.
My set up: atmega328P, AVR Dragon running debugWire in AVR Studio 7. LCD with I2C backpack (pcf8574 expander chip on back pack). Cheap knock off of Saleae logic analyzer using the Saleae software.
My bit rate is 100K=kHz, as confirmed with the logic analyzer. (mcu running at 8Mghtz, 32 in the BR register, 0's in the prescaler);
My problem is that none of my data bytes are being transmitted. I send a start, send the address+W byte, get an ACK, and then instead of my data being sent, the analyzer shows the stop being sent right away.
I'm not doing any error checking in the code just yet, just watching the relevant registers in the debugger.
After I send a start, I get 0x08 in the TWSR register. My understanding is that this is correct.
After I load the the address into TWDR, I get 0x18 in the TWSR. Again, i believe this is correct. At this point in the process, the logic analyzer shows all is as expected, including an ACK after the address+w is sent.
as I next step the debugger, just BEFORE I load the data to be sent into TWDR, TWSR reads 0x28. To me, this is odd, as that code means the data has already been sent, and an ACK recieved. (if i read the datasheet right anyway).
I then load the TWDR, and send a stop. TWSR still reads 0x28 at this point.
According to the logic analyzer, all that happened was START->Address+W->ACK->STOP. No sign of the data byte.
My gut says I'm not handling the setting of the TWINT bit correctly. Its been a source of confusion for me. I feel like my process follows the datasheet's correctly, but other stuff I read seems to conflict. Specifically, my code (and the datasheet as far as I can tell) say to set TWINT HIGH before I do anything, and to wait for it to go LOW before continuing. My other resource, the Make:AVR programming book seems to imply I should wait for it to go HIGH before continuing.
I never see TWINT go low in the debugger, as I thought I should.
Here is the code for my Write, Start, and Stop routines.
//Send start
void TWI_Start(uint8_t address)
{
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); //TWINT clears interrupt flag (sets it to 1); TWSTA sends start bit; TWEN enables TWI
while(!(TWCR & (1<<TWINT))) //check for interrupt flag to have been set to 0 by MCU before continuing
{
continue;
}
TWDR = address; //send slave address
TWCR = (1<< TWINT) | (1<< TWEN); //clear interrupt flag.
}
//write to current slave
void Write_TWI(uint8_t data)
{
TWI_Start(_writeAddress);
TWCR = (1<<TWINT) | (1<<TWEN); //clear interrupt flag
TWDR = data; //load byte to be sent into data register
TWCR = (1<<TWINT) | (1<<TWEN); //clear interrupt flag
while(!(TWCR & (1<<TWINT))) //check for interrupt flag to have been set to 0 by MCU before continuing
{
continue;
}
TWI_Stop();
}
//Send stop
void TWI_Stop(void)
{
TWCR = (1<<TWINT) | (1<<TWSTO) | (1<<TWEN); //TWINT clears interrupt flag (sets it to 1); TWSTO sends stop bit; TWEN enables TWI
}