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.

MSP430FR2676: I2C Communication Problem

Part Number: MSP430FR2676


Trying to talk with IS31FL3236A LED driver. When I am talking with the driver, it will suddenly stop working and freeze the whole program.

Initializing the driver works great, but as soon as the LEDs begin to turn on, the software gets stuck.

Upon inspection, with a logic analyzer I am getting a random NACK, and its never at the same place (randomly either after the slave address byte, or register address or data bytes):

The NACK flag is being set and causes the bus to be busy and the SCL line to go low and all communication is completely halted.

Any help is MUCH appreciated I've scoured the family user guide and datasheets but I can't seem to find my answer.

I2C code I am using is below, along with the datasheet for the LED Driver.

#include "eusci_iic_driver.h"


// NEED TO TRACK USCI STATUS AND PROVIDE DATA POINTER FOR USE IN ISR
volatile eUSCI_status ui8Status;
uint8_t* pData;
uint8_t ui8DummyRead;

/* ***************************************************************************
 * UCB0_MasterI2C_init
 * INITIALIZE I2C IN MASTER MODE
 * SEE EUSCI_DEF.H FOR SETUP DEFINITIONS
 *
*/
void UCB1_MasterI2C_init(void)
{
    UCB1CTLW0 = UCSWRST; // RESET USCI MODULE
    UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
    UCB1BRW = USCI_B1_BAUD; // SET BAUDRATE
    UCB1CTLW0 &= ~UCSWRST; // ENABLE USCI MODULE
}

/*
 * MASTER I2C WRITE
 * RETURNS: FALSE IF NO ERRORS
 * RETURNS: TRUE IF SLAVE NACK'D
 */
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
    uint8_t ui8index;

    UCB1CTLW0 |= UCSWRST;
    UCB1CTLW0 = UCMST + UCMODE_3 + UCSYNC + UCSSEL__SMCLK; // I2C SINGLE MASTER, SYNC MODE, 7 BIT ADDRS, CLOCK SELECT (DEFINED IN EUSCI_DEF.H)
    UCB1CTLW1 |= UCASTP_1;
    UCB1TBCNT = ui8ByteCount + 1;
    UCB1I2CSA = ui8Addr;
    UCB1CTLW0 &= ~UCSWRST;
    UCB1CTLW0 |= (UCTR + UCTXSTT);

    while(!(UCB1IFG & UCTXIFG)); //WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT
    UCB1TXBUF = ui8Reg; //LOAD TXBUF WITH THE TARGET REGISTER
    for(ui8index = 0; ui8index < ui8ByteCount; ui8index++)
    {
        while(!(UCB1IFG & UCTXIFG0));
            UCB1TXBUF = Data[ui8index];
    }
    while(!(UCB1IFG & UCTXIFG));
    while (!(UCB1IFG & UCBCNTIFG));
    UCB1CTL1 |= UCTXSTP;
    while (!(UCB1IFG & UCSTPIFG));     // Ensure stop condition got sent
    UCB1CTL1  |= UCSWRST;

    return(true);
}

/*
 * MASTER I2C READ
 * RETURNS: FALSE IF NO ERRORS
 * RETURNS: TRUE IF SLAVE NACK'D
 */
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount)
{
    uint8_t ui8index;

    UCB1CTLW0 |= UCSWRST;
    UCB1TBCNT = 0x0002; // SETUP THE NUMBER OF BYTES TO RECEIVE (CAN ONLY BE DONE HERE WHEN EUSCI IN RESET)
    UCB1CTLW1 |= UCASTP_1; // GENERATE AUTOMATIC STOP BIT WHEN UCB0TBCNT = TARGET
    UCB1I2CSA = ui8Addr; // LOAD THE DEVICE SLAVE ADDRESS
    UCB1CTLW0 &= ~UCSWRST; // RESUME
    UCB1CTLW0 |= (UCTR + UCTXSTT);
    while(!(UCB1IFG & UCTXIFG)); // WAIT FOR THE FIRST TXBUF EMPTY INTERRUPT BEFORE LOADING TARGET REGISTER
    UCB1TXBUF = ui8Reg; // LOAD TXBUF WITH THE TARGET REGISTER
    while(!(UCB1IFG & UCTXIFG));
    UCB1CTL1 &= ~UCTR; //TURN OFF TRANSMIT (ENABLE RECEIVE)
    UCB1CTL1 |= UCTXSTT; // GENERATE (RE-)START BIT
    while(!(UCB0IFG & UCRXIFG0));

    for(ui8index = 0; ui8index < ui8ByteCount - 1; ui8index++)
    {
        while(!(UCB1IFG & UCRXIFG0));
        Data[ui8index] = UCB0RXBUF;
        if(ui8index == ui8ByteCount - 1)
        {
            UCB1CTL1 |= UCTXSTP;    //send stop after next RX
        }
    }

    UCB1CTLW0 |= UCTXSTP;           //send stop after next RX
    while(!(UCB1IFG & UCRXIFG));
    Data[ui8index] = UCB1RXBUF;
    while (!(UCB1IFG & UCSTPIFG));  // Ensure stop condition got sent
    UCB1CTL1  |= UCSWRST;
    return(true);
}

#ifndef EUSCI_IIC_DRIVER_H_
#define EUSCI_IIC_DRIVER_H_
#include <msp430.h>
#include <stdint.h>
#include <stdbool.h>
#include "driverlib.h"
#define USCI_B1_BAUD 5

typedef enum {
    eUSCI_IDLE=0,
    eUSCI_SUCCESS = 0,
    eUSCI_BUSY =1,
    eUSCI_NACK=2,
    eUSCI_STOP,
    eUSCI_START
}eUSCI_status;

void UCB1_MasterI2C_init(void);
bool UCB1_I2C_write(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);
bool UCB1_I2C_read(uint8_t ui8Addr, uint8_t ui8Reg, uint8_t *Data, uint8_t ui8ByteCount);


#endif

IS31FL3236A_DS.pdf

  • The reason your software hangs is because your transmit code doesn't catch the NACK.

    Since you say that the problem happens after the LEDs start turning on, it could be a power problem. Not enough or even current causing voltage drops in unexpected places. You should look over your power wiring.

  • Hello David, 

    Thanks for the response.

    This is what I thought as well but even if I enable interrupts and handle the NACK upon the flag being thrown by adding in this:

    #pragma vector = USCI_B1_VECTOR
    __interrupt void USCIB1_ISR(void)
    {  switch(__even_in_range(UCB1IV,USCI_I2C_UCBIT9IFG))
        {
            case USCI_I2C_UCNACKIFG:
                    UCB1CTLW0 |= UCTXSTP;
                    //UCB1IFG &= ~UCTXIFG;
                    //UCB1CTL1 |= UCTXSTT;                //resend start if NACK
            break;                                      // Vector 4: NACKIFG break;
            default: break;
        }
    }

    It still doesn't allow me to re-engage the bus. What am I supposed "to do" to handle the NACK so I can reset the bus for another transaction?

    I haven't looked into a power issue yet as I have the board powered by a benchtop power supply. But I will check into that tomorrow. I suspect this is not the issue because using a different i2c code I was able to get quite a bit further (lighting all LEDs to full brightness).

  • Note: the LED Driver datasheet specifically says that if a NACK is received then a STOP should be sent to end the transaction early. However, If I try this I am unable to get the STOP bit to be sent for some reason.

  • Besides sending a stop you need to make the data transfer start over from the beginning. As it is, the transfer loop is waiting for TXIFG.

    Different I2C code? If that works, why are you messing with this?

  • Hi David,

    I am still unable to get to the bottom of what is going on. Seems my I2C is operating fine now, however, my capacitive sensors for the captivate module seem to suddenly stop responding. If you're able to direct message me I would much appreciate it, so I can send you full code of my project and maybe you'll have some more insight on what's causing this.

  • Hi  

    Is there anything wrong with your I2C?  You could submit another post of capacitive problem for everyone to refer to the similar questions.

**Attention** This is a public forum