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.

MSP430FR5962: I2C interrupt related issue , my cotroller getiingb

Part Number: MSP430FR5962

#include <msp430fr5962.h>
#include <msp430.h> // Adjust for your MCU
#include <stdint.h>

#include "math.h"

#define SLAVE_ADDR 0x65  // 7-bit slave address
#define max_buff 32
#define NUM_SLAVES 3
UINT8 SlaveAddr[NUM_SLAVES] = {0x65, 0x0B, 0x0C};
volatile UINT8 SlaveFlag = 0;
#define I2C_TIMEOUT 10  
UINT8 buffer;
volatile UINT8 *i2c_tx_ptr = 0,*i2c_rx_ptr=0;
volatile UINT8 i2c_tx_len = 0,i2c_rx_len=0,tx_count=0;
volatile UINT8 i2c_done = 0;
volatile UINT8 i2c_ack_rev = 1;
volatile UINT8 i2c_busy = 0;
volatile UINT8 i2c_result = 0;   // 0 = success, 1 = NACK, 2 = busy

volatile UINT8 rx_count = 0;
//******************************************************************************
// General I2C State Machine ***************************************************
//******************************************************************************


/* Used to track the state of the software state machine*/
I2C_Mode MasterMode = IDLE_MODE;

/* The Register Address/Command to use*/
UINT8 TransmitRegAddr = 0;

volatile UINT8 i2c_timeout = 0;

UINT8 ReceiveBuffer[MAX_BUFFER_SIZE] = {0};
UINT8 RXByteCtr = 0;
UINT8 ReceiveIndex = 0;
UINT8 TransmitBuffer[MAX_BUFFER_SIZE] = {0};
UINT8 TXByteCtr = 0;
UINT8 TransmitIndex = 0;

i2c_transmission_reception_wait(void )
{
    while(i2c_busy )
    {
    
    }
}

void i2c_init(void)
{
    UCB2CTLW0 = UCSWRST;

    // Configure as I2C master, synchronous mode
    UCB2CTLW0 |= UCMST | UCMODE_3 | UCSYNC;

    // Use SMCLK = 16 MHz
    UCB2CTLW0 |= UCSSEL__SMCLK;

    // Baud rate = SMCLK / UCB2BRW (100 kHz: 16,000,000 / 100,000 = 160)
    UCB2BRW = 40;

    // Route SDA/SCL pins (P7.0 = SDA, P7.1 = SCL)
    P7SEL0 |= BIT0 | BIT1;
    P7SEL1 &= ~(BIT0 | BIT1);

    // Release eUSCI_B2 from reset
    UCB2CTLW0 &= ~UCSWRST;

    // Enable TX, RX, and NACK interrupts
    UCB2IE = UCTXIE0 | UCRXIE0 | UCNACKIE;
}
void CopyArray(UINT8 *source, UINT8 *dest, UINT8 count)
{
    UINT8 copyIndex = 0;
    for (copyIndex = 0; copyIndex < count; copyIndex++)
    {
        dest[copyIndex] = source[copyIndex];
    }
}

// Add "UINT8 *rx_buf" argument
I2C_Mode i2c_start_rx(UINT8 addr, UINT8 cmd, UINT8 data_len, UINT8 *rx_buf)
{
    i2c_transmission_reception_wait();
    MasterMode = TX_REG_ADDRESS_MODE;
    TransmitRegAddr = cmd;
    RXByteCtr    = data_len;
    TXByteCtr    = 0;
    ReceiveIndex = 0;
    TransmitIndex = 0;
    if(addr == FLAME_SENSOR)
    {
        i2c_rx_ptr = flame_buf ;
    }
    else if(addr == SR_SENSOR)
    {
        i2c_rx_ptr = sr_buf ;
    }
    else
    {
        i2c_rx_ptr = hr_buf ;
    }
    
    i2c_rx_ptr = rx_buf;  // Assign the user buffer
    /* Initialize slave address and interrupts */
    UCB2I2CSA = addr;
    UCB2IFG &= ~(UCTXIFG + UCRXIFG);  // Clear any pending interrupts
    UCB2IE &= ~UCRXIE;                // Disable RX interrupt
    UCB2IE |= UCTXIE;                 // Enable TX interrupt
    UCB2CTLW0 |= UCTR + UCTXSTT;      // I2C TX, start condition
    i2c_busy = TRUE ;
    i2c_timeout = 5;
    return MasterMode;
}

I2C_Mode i2c_start_tx(UINT8 slave_addr,UINT8 cmd, UINT8 *data, UINT8 length)
    {
        /* Initialize state machine */
        i2c_transmission_reception_wait();
        MasterMode = TX_REG_ADDRESS_MODE;
        TransmitRegAddr = cmd;
        //Copy register data to TransmitBuffer
        CopyArray(data, TransmitBuffer, length);
        TXByteCtr = length;
        RXByteCtr = 0;
        ReceiveIndex = 0;
        TransmitIndex = 0;
        /* Initialize slave address and interrupts */
        UCB2I2CSA = slave_addr ;
        UCB2IFG &= ~(UCTXIFG + UCRXIFG);       // Clear any pending interrupts
        UCB2IE &= ~UCRXIE;                         // Disable RX interrupt
        UCB2IE |= UCTXIE;                         // Enable TX interrupt
        UCB2CTLW0 |= UCTR + UCTXSTT;             // I2C TX, start condition    
        i2c_busy = TRUE ;
        i2c_timeout = 5;
        return MasterMode;
    }


#pragma vector = USCI_B2_VECTOR
__interrupt void USCI_B2_ISR(void)
{
    
    UINT8 rx_val = 0;
    switch (__even_in_range(UCB2IV, USCI_I2C_UCBIT9IFG))
    {
        case USCI_I2C_UCRXIFG0: // RXIFG0
            rx_val = UCB2RXBUF;
            if (RXByteCtr)
            {
                i2c_rx_ptr[ReceiveIndex++] = rx_val;  // store into user buffer
                RXByteCtr--;
            }
            if (RXByteCtr == 1)
            {
                UCB2CTLW0 |= UCTXSTP;  // schedule stop for last byte
        //        i2c_busy = FALSE;           // important — allow TX to continue
            }
            else if (RXByteCtr == 0)
            {
                UCB2IE &= ~UCRXIE;
                MasterMode = IDLE_MODE;
                i2c_busy = FALSE;
                i2c_rx_ptr = 0; // clear pointer after done
            }
            break;        
        case USCI_I2C_UCNACKIFG:   // NACK received
            UCB2CTLW0 |= UCTXSTP;       // send stop
            UCB2IFG &= ~UCNACKIFG;       // clear NACK flag
        //    MasterMode = IDLE_MODE;
        //    i2c_rx_ptr = 0;            // clear pointer (optional)
            i2c_busy = FALSE;           // important — allow TX to continue
        break;
        case USCI_I2C_UCTXIFG0:                 // Vector 24: TXIFG0
            switch (MasterMode)
            {
                case TX_REG_ADDRESS_MODE:
                    UCB2TXBUF = TransmitRegAddr;
                    if (RXByteCtr)
                      MasterMode = SWITCH_TO_RX_MODE;   // Need to start receiving now
                    else
                      MasterMode = TX_DATA_MODE;        // Continue to transmision with the data in Transmit Buffer
                    break;

                case SWITCH_TO_RX_MODE:
                    UCB2IE |= UCRXIE;              // Enable RX interrupt
                    UCB2IE &= ~UCTXIE;             // Disable TX interrupt
                    UCB2CTLW0 &= ~UCTR;            // Switch to receiver
                    MasterMode = RX_DATA_MODE;    // State state is to receive data
                    UCB2CTLW0 |= UCTXSTT;          // Send repeated start
                    if (RXByteCtr == 1)
                        {
                          //Must send stop since this is the N-1 byte
                          while((UCB2CTLW0 & UCTXSTT));
                          UCB2CTLW0 |= UCTXSTP;      // Send stop condition
                        }
                break;

                case TX_DATA_MODE:
                    if (TXByteCtr)
                    {
                      UCB2TXBUF = TransmitBuffer[TransmitIndex++];
                      TXByteCtr--;
                    }
                    else
                    {
                      //Done with transmission
                      UCB2CTLW0 |= UCTXSTP;     // Send stop condition
                      MasterMode = IDLE_MODE;
                      UCB2IE &= ~UCTXIE;                       // disable TX interrupt
                    }
            break;
            default:
                    UCB2IFG = 0;
                    __no_operation();
            break;
        }
        break;
    default: break;
        }
}

int main(void)
{
    UINT8 flag = FALSE, counter = 0;
    UINT8 buf[11];
    UINT8 rx_buffer[8],rx_buffer1[8],rx_buffer2[8]; // Buffer for received data
    UINT8 cmd = 0x04;   // Command to send before reading
    i2c_init();
    while (1)
    {
        watch_clr();
        i2c_start_rx(0xA0 , 0X65, 5 ,rx_buffer);
        i2c_start_rx(0xA1 , 0X65, 5 ,rx_buffer1);
        i2c_start_rx(0xA2 , 0X65, 5 ,rx_buffer2);


    }
}

 

 

 

Hello Support Team,

I am facing an issue with my controller during I²C operation.
The controller boots normally and initializes without any problem.
However, after I²C communication starts, the controller resets unexpectedly after some time and enters a continuous reset loop.

Summary of the issue:

  • Controller initializes successfully

  • I²C communication starts

  • After some time, the controller resets by itself

  • The reset repeats continuously

  •  And also if my bus line seem low  when initating .then communication is not happening like continous reset .tempsnip.pngPlease advise what might be causing this issue. I can share logs, wiring diagrams, firmware details, or any additional information if needed.

Thank you.

 

  • Hi Ankush,

    Could you add some test code at the begin of main(), such as toggle a GPIO pin, to check whether really a MCU reset occurs for this issue?

    And do you have WDT configured in this example?

  • Lots missing from that code fragment. (Please use the Insert:code feature of the editor!) There is a comment hinting at a 16MHz MCLK but no hint of clock configuration. Also, LOCKLPM5 isn't cleared. Or at least that isn't shown.

    The watchdog is given a miss as well. There is a call to a watch_clr() function in the main loop so perhaps that does something. 

    Then you have three straight calls to start receiving data. And no attempt to wait for one to complete before starting another. The code to start receiving selects between three buffer addresses. Then says nevermind, use rx_buf.

    Of course it fails.

    It looks like someone copied some code they didn't understand and tried to modify it.

**Attention** This is a public forum