The chip datasheet for the XFS5152CE lists its I2C address as an 8-bit write address; however, the actual address used on the bus is a 7-bit address. The correct 7-bit address is 0x40. The least significant bit determines the operation: set to 1 for read (0x81) or 0 for write (0x80).
If you are implementing a software I2C (bit‑benging), you can handle this directly. The real trouble occurs when using a hardware I2C peripheral that expects the 7‑bit address. I spent several days debugging this because my MSP430 register‑based driver required the 7‑bit address 0x40.
Another issue appears with the UART interface: every time the chip powers up, it sends a status byte 0x4A over UART. When using I2C, this status byte is not sent automaticaly — you must read it explicit.
My approach is to write the voice command and then immediately read the status byte. On the first power‑up read after writing data, the value returned is 0x4A. Subsequent reads return either 0x41 or 0x4F.
Example Code (MSP430F5438A, I2C3 Module)
Below are the core I2C functions used to communicate with the XFS5152CE. Note the corrected stop condition handling to avoid a hang on subsequent transfers.
void i2c_send_start(uint8_t addr)
{
UCB3I2CSA = addr; // set 7-bit slave address
while (UCB3CTL1 & UCTXSTP); // wait for pending stop
UCB3CTL1 |= (UCTR + UCTXSTT); // transmitter mode + start
while (!(UCB3IFG & UCTXIFG)); // wait for TX buffer ready
UCB3IFG &= ~UCTXIFG; // clear flag
}
void i2c_write_byte(uint8_t data)
{
UCB3TXBUF = data;
while (!(UCB3IFG & UCTXIFG));
UCB3IFG &= ~UCTXIFG;
}
void i2c_write_bytes(uint8_t *buf, int length)
{
for (int i = 0; i < length; i++)
{
i2c_write_byte(*buf++);
}
}
void i2c_read_bytes(uint8_t *buf, uint8_t length)
{
UCB3CTL1 &= ~UCTR; // receiver mode
UCB3CTL1 |= UCTXSTT; // repeated start
for (uint8_t i = 0; i < length; i++)
{
while (!(UCB3IFG & UCRXIFG)); // wait for data
UCB3IFG &= ~UCRXIFG;
if (i == length - 1)
{
UCB3CTL1 |= UCTXSTP; // generate stop on last byte
while (UCB3CTL1 & UCTXSTP); // wait until stop is finished
}
*buf++ = UCB3RXBUF;
}
}
int xfs_write_and_read(uint8_t *cmd, int cmd_len, uint8_t *response, int resp_len)
{
i2c_send_start(0x40);
i2c_write_bytes(cmd, cmd_len);
i2c_read_bytes(response, resp_len);
return 0;
}
The critical fix in the i2c_read_bytes function is the addition of the while(UCB3CTL1 & UCTXSTP) loop after setting the stop condition. Without this check, subsequent I2C transactions may stall indefinitely.