This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

i2c read byte requires dummy read

Hello,

Currently I find that I need to read a register twice to get the correct data. If I run a single time, the byte read is the previous byte. For example:

rtcMonth = readMonth();
rtcMonth = readMonth();
rtcYear = readYear();

gives me an rtcMonth equal to 0x01 (january) but it also gives me 0x01 for the year. If I perform a second readYear operation, rtcYear will be 0x16 (2016). My i2c is set to not generate an autostop.

My code follows:

#define i2cDelay 1000

unsigned char i2cReadByte(const unsigned char slvAddr, const unsigned char regAddr){
	char rxByte;
	while (stopBusy());
	UCB0I2CSA = slvAddr;  // set slave addr
	UCB0CTLW0 |= UCTR + UCTXSTT;  // i2c start
	while(txBusy() | startBusy());
	UCB0TXBUF = regAddr;
	while(txBusy());
	UCB0CTLW0 &= ~UCTR ;
	UCB0CTLW0 |= UCTXSTT;
	while(rxBusy() | startBusy());
	UCB0CTLW0 |= UCTXSTP;  // i2c stop
	rxByte = UCB0RXBUF;
	while (stopBusy());
	_delay_cycles(i2cDelay);
	return rxByte;

char txBusy(void){
	return !(UCB0IFG & UCTXIFG0);
}

char startBusy(void){
	return (UCB0CTLW0 & UCTXSTT);
}

char stopBusy(void){
	return (UCB0CTLW0 & UCTXSTP);
}

char rxBusy(void){
	return !(UCB0IFG & UCRXIFG0);
}

  • You did not mention your chip.

    But in the case of the USCI module, the documentation says:

    If a master wants to receive a single byte only, the UCTXSTP bit must be set while the byte is being received.

    So your code would need to look like this:

    ...
    CB0CTLW0 |= UCTXSTT;
    while(startBusy());
    UCB0CTLW0 |= UCTXSTP;
    while(rxBusy());
    rxByte = UCB0RXBUF;
    ...
  • I'm using the MSP432 launchpad. I hope to convert all of this to a non-blocking, interrupt driven approach but I would like to figure out what the issue is with this code.

    At some point in the past I'm pretty sure I put the stop generation before reading the rx buffer but it just hung in the rxBusy loop. I will try your suggestion, thanks for your help.
  • The MSP432 has the eUSCI module, whose documentation does not contain this sentence. But in theory, it should work the same.

  • Your suggested fix worked. I had accidentally tried my stopBusy function instead of rxBusy before, and it would hang there.

**Attention** This is a public forum