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: I2C Target (aka SLAVE) device won't send an ACK

Part Number: MSP-EXP430F5529LP

Tool/software:

Hello Everyone, 

I am trying to establish a communication between an I2C based sensor and the MSP430 development board. Please see my code below. The sensor won't send an ACK. I have not changed the clock of the system, using the default 1MHz. And the I2C Comm speed is 100KHz.

As shown in the image, I have connected the 4.7K ohm pull up resistors to I2C lines. 


#include "driverlib.h"
#include <msp430.h>
#include "inc/hw_memmap.h"
#include "uart_debug.h"

#define    BAUD_RATE    115200
//******************************************************************************
//!
//!   Empty Project that includes driverlib
//!
//******************************************************************************

//******************************************************************************
//!
//!   Local Function Prototypes
//!
//******************************************************************************
static void watchdog_stop (void);
static void init_i2c(void);
static void check_i2c_slave(void);
//******************************************************************************
//!
//!   Local Variables
//!
//******************************************************************************

int main (void)
{

    watchdog_stop();
    init_debug_uart();
    init_i2c();
    //check_i2c_slave();
    while(1)
    {
        debug_print("Debugging Working\n\r");
        check_i2c_slave();
        __delay_cycles(3000000); //3sn
    }
}

//******************************************************************************
//!
//!   Local Function Definitions
//!
//******************************************************************************
static void watchdog_stop (void)
{
    WDTCTL = WDTPW + WDTHOLD;
}

static void init_i2c(void)
{
    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN2 | GPIO_PIN1);//P4.1 SDA, P4.2 SCL
    UCB1CTL1 |= UCSWRST;                        // Enable SW reset
    UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;       // Master, I2C, Synchronous mode
    UCB1CTL1 = UCSSEL_2 + UCSWRST + UCTR;       // Use SMCLK, keep SW reset
    UCB1BR0 = 10;                               // set prescaler, since SMCLK is 1MHz, /10 will give 100KHz
    UCB1BR1 = 0;
    UCB1I2CSA =  0x74;                          // Set slave address
    UCB1CTL1 &= ~UCSWRST;                       // Clear SW reset, resume operation
    while (UCB1STAT & UCBBUSY);                 // Wait for the I2C Bus to get free.
}

static void check_i2c_slave (void)
{
    // Send start condition (this happens when the first byte is sent)
    UCB1CTL1 |= UCTR + UCTXSTT; // Transmit mode, send start bit

    while (UCB1CTL1 & UCTXSTT); // Wait for start bit to be transmitted
    debug_print("Start Bit Transmission Complete\r\n");

    // Now, you can send data or address
    //UCB1TXBUF = (0x74) << 1; // Send slave address with write operation

    // Wait for data transmission to complete
    while (UCB1CTL1 & UCTXSTT); // Wait for start condition to be sent
    debug_print("Data Transmission Complete\r\n");

    // For now, let's just stop the transmission.
    UCB1CTL1 |= UCTXSTP; // Send stop condition

    // Wait for stop condition
    while (UCB1CTL1 & UCTXSTP);
    debug_print("Stop Bit Transmission Complete\r\n");
}

  • You have misunderstood the I2C timing. UCTXSTT clears after the target acknowledges the address.The I2C port holds the clock until it has data to transmit. Which means that since you never provide that data, the acknowledge cycle can't complete (rising edge of clock). So UCTXSTT never clears.

  • How certain are you that the I2C address (0x74) is correct? More generally: What sensor/breakout board are you using?

    Looking at the Adafruit I2C address list (not authoritative, but pretty good) the only sensor per se at 0x74 is the PCT2075, which can have any of 27 different addresses. The Adafruit breakout board (as delivered) is address 0x37.

  • Hey! Sorry I didn't specify in the post. I am working with a touchpad EVB and we have a code base on a different microcontroller. I am porting it to TI. The address is 0x74 as specified in the data sheet of the sensor. 

    I also tried this: 
    I have an RTC break-out board from Micro-Crystal who's address is 0x52. I tried to run the same code on this RTC Break-out board and still the RTC board did not give an ACK. Hence I am pretty sure that something is wrong in the code I have written. The same RTC breakout board responded to an Arduino sketch which scans the I2C bus. Hence we know that the breakout board is working fine. 

  • Thanks for the reply, David. 

    Are you suggesting that I should uncomment the following lines?

    // Now, you can send data or address
    //UCB1TXBUF = (0x74) << 1; // Send slave address with write operation

    If this is what you're suggesting, then I did try that, but it did not work. 

  • Hey David, 
    This code worked: 

    static void I2C_write(uint16_t regAddr, uint8_t *data, uint8_t size)
    {
        uint8_t data_idx;
        // Wait for any previous stop condition to complete
        while (UCB1CTL1 & UCTXSTP);
    
        // Set the device to transmit mode and send the start condition
        UCB1CTL1 |= UCTR + UCTXSTT;
    
        // Wait for the transmit buffer to be ready to send the slave address
        while (!( UCB1IFG & UCTXIFG));
    
        // Send the high byte of the register address
        UCB1TXBUF = (uint8_t)(regAddr >> 8);  // Send high byte of register address (0x04)
    
        // Wait for the high byte to be transmitted
        while (!(UCB1IFG & UCTXIFG));
    
        // Send the low byte of the register address
        UCB1TXBUF = (uint8_t)(regAddr & 0xFF);  // Send low byte of register address (0x31)
    
        // Wait for the low byte to be transmitted
        while (!(UCB1IFG & UCTXIFG));
    
        // Send the bytes
        for (data_idx = 0; data_idx < size; data_idx++)
        {
            // Send the data byte
            UCB1TXBUF = data[data_idx];
    
            // Wait for the data byte to be transmitted
            while (!(UCB1IFG & UCTXIFG));
        }
    
        // Send the stop condition
        UCB1CTL1 |= UCTXSTP;
    
        // Wait for stop condition to be completed
        while (UCB1CTL1 & UCTXSTP);
    }

    And I am not sure why!

  • I explained it very carefully but I will try again.

    You were waiting for the start condition flag to clear before writing data to TXBUF.  In order for the address acknowledge to complete, clearing STT, the I2C port must have data to transmit. It didn't because you were waiting for the start condition flag to clear before writing data.

    Now you are waiting on TXIFG. Which gets set early.

**Attention** This is a public forum