> Weird issue, but I can't receive data using the TWI module in the
> ATmega128. (Writing data is documented very well in the datasheet,
Never mind. TWINT is not set after sending a STOP. I'll extinguish my
crack pipe now.
Reply by larwe●January 15, 20062006-01-15
Weird issue, but I can't receive data using the TWI module in the
ATmega128. (Writing data is documented very well in the datasheet,
reading data is not). The code I'm trying to use is below. It hangs
while waiting for the final STOP to be sent. So it has sent SLA+R and
read a byte off the device. The byte read appears to be correct, too.
I know the addresses, speed etc. are OK because I can write to the
device concerned with no difficulty (it is an MCP23008 8-bit I/O
expander).
Before I start grabbing packets with the scope, can someone see the
obvious idiot mistake in my code? The mega128 datasheet is confusing;
for the situation where data byte has been Rxed and ACK sent, it does
not show a bit combination for the "next step" being a STOP.
Thanks for any advice.
// Set address counter
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START
while (!(TWCR & (1 << TWINT))); // wait for end of START tx
if ((TWSR & 0xF8) != TWI_START)
return 0;
TWDR = (MCP_CONTROL | ((addr & 0x07) << 1)); // load Tx buffer with
address/cmd
TWCR = (1 << TWINT) | (1 << TWEN); // send SLA_W
while (!(TWCR & (1 << TWINT))); // wait for end of SLA_W tx
if ((TWSR & 0xF8) != TWI_MT_SLA_ACK)
return 0;
TWDR = regnum; // load register address into Tx buf
TWCR = (1 << TWINT) | (1 << TWEN); // send register address
while (!(TWCR & (1 << TWINT))); // wait for end of register tx
if ((TWSR & 0xF8) != TWI_MT_DATA_ACK)
return 0;
TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send RESTART
while (!(TWCR & (1 << TWINT))); // wait for end of RESTART tx
if ((TWSR & 0xF8) != TWI_RESTART)
return 0;
TWDR = (MCP_CONTROL | ((addr & 0x07) << 1)) | 1; // load Tx buffer
with SLA+R
TWCR = (1 << TWINT) | (1 << TWEN); // send SLA_R
while (!(TWCR & (1 << TWINT))); // wait for end of RESTART tx
if ((TWSR & 0xF8) != TWI_SLA_ACK)
return 0;
TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWEA); // Rx data byte,
send ACK
while (!(TWCR & (1 << TWINT))); // wait for end of data Rx
if ((TWSR & 0xF8) != TWI_DATA_RX)
return 0;
result = TWDR;
TWCR = (1 << TWINT) | (1 << TWSTO) | (1 << TWEN); // send STOP
while (!(TWCR & (1 << TWINT))); // wait for end of STOP