EmbeddedRelated.com
Forums

Help with TWI module on ATmega128

Started by larwe January 15, 2006
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

larwe wrote:
> 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.