I'm trying to implement TWI Master on a ATMEGA4808
The device is a superb device, very rich on features, but the datasheet makes understanding thw TWI interface quite hard!
First the problem...
I'm trying read register 0 on a TAS5575M which is at address 0x34 (7 bit address)
I seem to be able to send the address byte with read-btit set no problem, but then nothing...
Here's my setup code:
static volatile uint8_t dummy_u8; void i2c_master_init(void) { PORTMUX.TWISPIROUTEA=PORTMUX_TWI0_DEFAULT_gc; TWI0.MBAUD = 70; TWI0.MCTRLB |= TWI_FLUSH_bm; TWI0.MSTATUS |= (TWI_RIF_bm | TWI_WIF_bm); i2c_master_enable(); } void i2c_master_enable() { TWI0.MCTRLA = TWI_ENABLE_bm; TWI0_MSTATUS |= TWI_BUSSTATE_IDLE_gc; }
And then I send a start using this (sending 0x34 as the address):
uint8_t i2c_master_start(uint8_t addr) { if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) != TWI_BUSSTATE_BUSY_gc) { TWI0.MCTRLB &= ~(TWI_ACKACT_bm); TWI0.MADDR = addr; if (addr & 0x01) { // wait for RIF which means the ADDR byte in read mode has been sent. while (!(TWI0_MSTATUS & TWI_RIF_bm)); } else { while (!(TWI0_MSTATUS & TWI_WIF_bm)); } return TWI0.MSTATUS; } else return TWI0.MSTATUS; }
And then I try to send the register address using this, with 0x00 as the data:
uint8_t i2c_master_write(uint8_t data) { if ((TWI0.MSTATUS & TWI_BUSSTATE_gm) == TWI_BUSSTATE_OWNER_gc) { dummy_u8 = TWI0_MSTATUS; TWI0.MDATA = data; while(1) { dummy_u8 = TWI0_MSTATUS; if(dummy_u8 & TWI_WIF_bm) { break; } } } return TWI0.MSTATUS; }
Now it just hangs in the while loop and MSTATUS stays stubbornly stuck at 0x22
If I add a break point, so that it stops immedaitely after line "TWI0.MADDR = addr;" in i2c_master_start(), ie immediately after sending the Address Byte with Read Bit, my logic analyzer shows me this :
Which seems to be (almost) correct for a Read from a device at 0x34 - but what are all those extra clocks?
So not sure what is going on!
Anyone got any working TWI Master code for the 0-series I can compare with?