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.

MSP-EXP430F5529LP: Why do I have to read a dummy byte?

Part Number: MSP-EXP430F5529LP
Other Parts Discussed in Thread: MSP430F5529

I've got my I2C library working fine, but for some reason I have to read an additional dummy byte after sending the STOP condition, or else it won't read the actual final byte and everything gets truncated. I still can't figure out why this is happening. Here's the read section of my code:

    case READ:
        UCB0CTL1 &= ~UCTR; // set listener mode
        UCB0CTL1 |= UCTXSTT; // send a START
        while(UCB0CTL1 & UCTXSTT) ; // wait for start condition done
        if (!(UCB0CTL1 & UCTXSTT) && (UCB0IFG & UCNACKIFG)) { // peripheral n'acked on address
            UCB0CTL1 |= UCTXSTP;
            while(UCB0CTL1 & UCTXSTP) ;
            return NACK_ADDR;
        }
        while (!(UCB0IFG & UCRXIFG)) ;
        if (length == 1) {
            UCB0CTL1 |= UCTXSTP; // we must set the STOP bit while the first byte is being read,
            // if it's a single byte only read
            UCB0IFG &= ~UCTXIFG;
            *data = UCB0RXBUF;
            while(UCB0CTL1 & UCTXSTP) ; // wait for STOP to complete
            return SUCCESS;
        } else {
            for(i = 0; i < length; i++) {
                if(i == length - 1) { // if we are on the last byte, it's a special case
                    UCB0CTL1 |= UCTXSTP; // send stop
                    *(data + i) = UCB0RXBUF; // read byte
                    UCB0IFG &= ~UCTXIFG;
                    while(UCB0CTL1 & UCTXSTP) ; // wait for STOP to complete

                    break;
                }
                *(data + i) = UCB0RXBUF; // read byte
                while (!(UCB0IFG & UCRXIFG)) ; // wait for next byte to come
            }
            dummyByte = UCB0RXBUF; // read a dummy byte or everything gets messed up
        }

When I read say, 3 bytes, I can see that the dummyByte read does indeed read a 4th byte on the bus, typically 0xFF because that's what the chip sends. If I comment out this line, the chip will only read TWO bytes. I already have to do the weird last byte special case because the MSP430F5529 requires us to send the STOP condition before reading the final byte.

This doesn't really matter, as everything works -- it's just one of those irritating little bugs that I want to fix but haven't been able to. Any suggestions are greatly welcomed!

 In this example, if I were to eliminate the dummyByte line, *data would contain 0x72, 0x76 and then the next time around, it would contain 0xBC, 0x72, etc. It's like the buffer isn't being cleared, hence why I added the dummyByte read in the first place.

  • I see some timing troubles. For example, in the case of length = 1 you wait for RXIFG (data available) before setting the stop condition flag. Which means that single byte of data has already arrived.

    The following for() loop has a similar problem. When you perform the test for i == length - 1 you have data waiting in RXBUF and another byte in transit.  But the next iteration of for() will now drop out of the loop. Leaving your dummy read to pick up that last byte.

    Off by one errors bother me frequently but I am trying to do better.

  • Ugh, this whole problem comes from the fact that the datasheet says you have to set the stop bit before reading the byte from RXBUF if you're only reading a single byte (or it's the last byte). 

    The first while() loop has to be there, because we can't start reading from RXBUF before there's a byte in there, right? I'm not sure how to fix this while also preserving that special case. I've written so many I2C libraries but the MSP430 does everything so differently, it's taken some getting used to.

    I'll try and play around with the order things are done in. 

  • For the case of a single byte read the way to tell when you can set UCTXSTP is to wait for UCTXSTT to clear after you set it to start things off.

**Attention** This is a public forum