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 communication problems with msp430f2274

1. I'm currently using eZ430 to acquire data from a compass module through i2c interface. The data coming from the compass module is two bytes, and based on my understanding on i2c protocol, msp320 needs to send an ACK to the compass after the first byte is read, then receive the second byte followed by a NACK + STOP. I haven't been able to find a solution to this. Is sending an ACK automatically taken care by the interrupt or something else? What is the code and the correct order to acquire two bytes from a I2C slave in master transmitter mode?  

(I also checked both SDK and SCL with a scope. No ACK was sent by the code I'm having right now. Instead, the second byte was missing, DSK and SCL were both high) 

 

2. The second question is about CCSv4. I was setting up several watch variables in CCS, and trying to monitor the received data bytes. I declare them as unsigned char. However, CCS has failed to give me any information about those variables.

I basically have

RxByte1 = UCB0RXBUF;
...
RxByte2 = UCB0RXBUF;

Of course, with my first problem, the second byte is missing but I'm still expecting something shows up for RxByte1. However, CCS has always showed a dot for the value of RxByte1. I'm wondering what's going on here?

 

Any help will be highly appreciated! Please point out my misunderstanding on any issues here.

Thanks!

  • The USCI I2C module implements everything, generation of start bit, calculation of R/W bit (and adding it to the 7 bit address, so remove the r/w bit from the address you read in the docs of the slave device before you write these 7 bits to the SA register), sending of the address, sendign of ACK bits where necessary etc.

    What you need to do is: set the SWRST bit, write the slave address to UCBxSA, clear the UCTR bit (as you want to read), configure the baudrate, clear the SWRST bit.
    Then (for the transfer) set the UCSTT bit, wait for it to clear. Check the UCNAMCIFG bit (if it is set at this point, the slave didn't answer), if it is clear, wait for UCRXIFG being set. The moment you read the just received byte from UCRXBUF, an ACK is sent and the next byte is received. If you don't want more bytes, set UCSTP before you read the byte. Then a NACK is sent, followed by a stop condition.

    The MSP430F5xx family users guide (which has the same USCI module, except for the interrupt verctor assignment and interrupt enable registers) contains nice sheets exactly showing the protocol flow and what bit is set/cleared when and what you have to do at which point of the transfer. You don't need an interrupt function at all, you can as well check for the IFG bit of this interrutp source to be set.

     

  • Hi Jens-Michael:

    Sorry for replying your response so late!

    Thank you so much for your detailed discussion! It did help me understand how it works. However, for some reason, I have to use interrupt to read from I2C. Otherwise, it just breaks the communication. I haven't figured it out why. With interrupts, I was able to read two bytes data easily.

    CCSv4 also works. I have to switch the format to binary for a char watch variable, otherwise, the value won't show up.

     

    Minzhen

  • Minzhen Ren said:
    for some reason, I have to use interrupt to read from I2C. Otherwise, it just breaks the communication. I haven't figured it out why. With interrupts, I was able to read two bytes data easily.

    Hmm, then there' sstill something wrong in th epolling code.

    An interrupt is sort of a

    while(!(x & yyyIFG));

    that is executed in the background 'before' entering the ISR. There are only a few occurrences where there are other side-effects (like the CCR0 interrupt, where entering the ISR will automatically clear the CCRIFG bit)

    If you got it working with interrupts, fine. Anyway, you should try to find out what was wrong with the non-interrupt code. (e.g. an IFG bit you didn't clear while it is cleared in the ISR when you read the IV register or something liek that). Jsut to understand what was wrong and how it works right. Else you might run into problems again if your prohject grows more complex.

  • I think I was kinda careless before to use the word interrupt. I was trying not to use ISR but interrupt flags to write the code, but for some reason I can only get it working by using ISR.

    I completely agree with you that I should figure out why exactly it's not working as desired. When I went back today to try a few different things, I was able to just use interrupt flags to write and read. However, some of the results just don't make a lot of sense to me: ( I don't know if I should start a new thread here since I have already verified the answer)

    1. When I do following

    UCB0CTL1 |= UCTXSTT; // I2C start condition
    while (UCB0CTL1 & UCTXSTT);             // Loop until I2C STT is sent

    the UCTXSTT was never set even if the start condition and the address were sent (I acquired it on a scope but not ACK was generated though)

     

    2. When I was trying to receive the two bytes, I have to do

    UCB0CTL1 |= UCTXSTP;

    right after the first byte was read. Otherwise, odd things happened. 

     

    3. It doesn't seems UCB0CTL1 |= UCTXNACK; is effective in the master transmission mode. I'm not so sure how to use it. Since

    UCB0CTL1 |= UCTXSTP; generates a NACK before the stop condition (said so in the documentation), why bother to have UCTXNACK bit?

     

  • Minzhen Ren said:
    1. When I do following
    UCB0CTL1 |= UCTXSTT; // I2C start condition
    while (UCB0CTL1 & UCTXSTT);             // Loop until I2C STT is sent
    the UCTXSTT was never set even if the start condition and the address were sent


    How do you know? If oyu set a breakpoint, the sending of the start might be finished before the debugger has taken control over the MSP. Remember, the USCI hardware is independent of the CPU and continues even if the CPU itself is halted. And the few µs required for the transfer have quickly passed.
    You'll need to put two (!) NOPs into the while loop and set a breakpoint on the second one. If it is hit, you know that UCTXSTT was set.
    If you just single-step over the instruction, things are gone before the debugger can show them. That's when real-time-reality hits debugging-theory.

    Minzhen Ren said:
    UCB0CTL1 |= UCTXSTP;
    right after the first byte was read. Otherwise, odd things happened.

    Actually after reading the first and before reading the second byte. I fyou do it after reading the second byte, the hardware will continue reading a third byte and stop then.

    Minzhen Ren said:
    It doesn't seems UCB0CTL1 |= UCTXNACK; is effective in the master transmission mode.

    Right. I tmay be useful to set it together with UCTXSTT for a repeated start (I'm not sure here, I don't use UCTXNACK for interfacing my RTC, even though I use repeated start), but UCTXSTP will do it for you anyway.
    You need it, however, in slave mode to end a master transfer (if you don't want more bytes) or to refuse a connection (if the master addresses you, the bus is halted by the slave hardware, until slave software either accepts or denies the connection). the 'TX' in the bit name does not mean 'master' but rather 'send' (which refers to slave receive mode too, where ACK or NACK is sent after receiving a byte or being addressed)

  • Jens-Michael Gross said:

    Remember, the USCI hardware is independent of the CPU and continues even if the CPU itself is halted. And the few µs required for the transfer have quickly passed.
    You'll need to put two (!) NOPs into the while loop and set a breakpoint on the second one. If it is hit, you know that UCTXSTT was set.
    If you just single-step over the instruction, things are gone before the debugger can show them. That's when real-time-reality hits debugging-theory.

    Jens-Michael Gross said:

    You need it, however, in slave mode to end a master transfer (if you don't want more bytes) or to refuse a connection (if the master addresses you, the bus is halted by the slave hardware, until slave software either accepts or denies the connection). the 'TX' in the bit name does not mean 'master' but rather 'send' (which refers to slave receive mode too, where ACK or NACK is sent after receiving a byte or being addressed)

    Thank you for the insights here! It's very helpful!

**Attention** This is a public forum