MSP430F2619: I2C Repeated Start sample code requirement

Part Number: MSP430F2619

Tool/software:

I am trying to implement I2C communications with a slave IC. The slave device is ACS37800 Power monitoring IC. The task is to
acheive an I2C read operation with the above format .


The use case requires a repeated start condition, I could only find example codes for conventional I2C slave read, (i.e without repeated starts).
Can a sample code to implement repeated start be provided for MSP430F2619.

Here is what I tried to implement [ SCL @ 143KHz]

#include <msp430.h>

// Define global variables
unsigned char RXData, Master_RX, TXByteCtr = 0, RXByteCtr = 4; // RXByteCtr set to the number of bytes to read
int i,c=0;
unsigned char RXDataarr[15]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};

// Function prototypes
void Master_TX_to_RX_Slave(void);
void MasterUSCIB0TX(void);

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT

P3SEL |= 0x06; // Assign I2C pins to USCI_B0

while (1)
{

Master_TX_to_RX_Slave(); // Perform Master TX to RX Slave communication
__bic_SR_register(GIE);
// Clear general interrupt enable
}
}

// USCI_B0 Data ISR1
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCIAB0TX_VECTOR
__interrupt void USCIAB0TX_ISR(void)
#elif defined(__GNUC__)
void __attribute__((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_ISR(void)
#else
#error Compiler not supported!
#endif
{
if (Master_RX == 0)
{
if (TXByteCtr == 1)
{ __delay_cycles(50);
UCB0TXBUF = 0x20; // Send the register address
TXByteCtr--;
}
else
{
Master_RX = 1;
//c=1;
UCB0CTL1 &= ~UCTR; // Switch to RX mode
UCB0CTL1 |= UCTXSTT; // Send repeated start condition

}//do
//{
}

if (Master_RX == 1)
{
if (UCB0CTL1 & UCTXSTT) // Ensure start condition was sent
return;
RXDataarr[c] = UCB0RXBUF;
c++;

if(c==8)
{

UCB0CTL1 |= UCTXSTP; // Send stop condition
IE2 &= ~UCB0TXIE;
IE2&= ~UCB0RXIE;
c=0;
}
}

}//isr


// Function to initiate Master TX to RX Slave communication
void Master_TX_to_RX_Slave(void)
{
MasterUSCIB0TX();

__bis_SR_register(GIE); // Enable general interrupts
TXByteCtr = 1; // Load TX byte counter

while (UCB0CTL1 & UCTXSTP); // Ensure stop condition was sent
UCB0CTL1 |= UCTR + UCTXSTT; // I2C TX, start condition

// Add a timeout mechanism to prevent infinite loop

while (UCB0CTL1 & UCTXSTT);

__bis_SR_register(GIE); // Enable interrupts
while (UCB0CTL1 & UCTXSTP); // Ensure stop condition was sent
}

// Function to configure USCI_B0 for Master transmission
void MasterUSCIB0TX(void)
{
UCB0CTL1 |= UCSWRST; // Enable software reset
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC; // I2C Master, synchronous mode
UCB0CTL1 = UCSSEL_2 + UCSWRST; // Use SMCLK, keep software reset
UCB0BR0 = 7; // Set SCL frequency 1Mhz / 7 ~~ 143Khz
UCB0BR1 = 0;
UCB0I2CSA = 0x7F; // Set slave address (adjust as needed)
UCB0CTL1 &= ~UCSWRST; // Clear software reset, resume operation
Master_RX = 0; // Initialize Master_RX flag
IE2 |= UCB0TXIE + UCB0RXIE ; // Enable TX and RX interrupts
}


The above code iterates through the ISR 9 times to receive 4 bytes of slave data. The transmit portion is more understandable but I couldn't figure out why the receive portion
needs to iterate 9 times to receive 4 bytes of slave data. when it should theoritically iterate only 4 times. I got this value of 9 via trial and error as 4 iterations only
yielded less than 4 bytes and ended in a premature termination of I2C communications.

Even after receiving 4 Bytes, the RXIFG flag remains SET and this is also an area of concern as i am expecting to terminate communications after 4 Bytes.

Any kind of solution or advice would be very helpful regarding why this issue is occuring.

Regards,

Anand VS

  • The TI Example MSP430x261x_usci_i2c_standard_master.c uses Repeated-Start to implement I2C_Mode I2C_Master_ReadReg(). (Look for SWITCH_TO_RX_MODE.)

    [Edit: Sorry I forgot the link:

    https://dev.ti.com/tirex/explore/node?node=A__AEJIFApgaCbL04wfEfe6XQ__msp430ware__IOGqZri__LATEST

  • Thanks Bruce, for your timely help in providing informative link. I used the code logic as such and flashed it. I am not getting any data in return. 

    I verified the hardware side, which is found to be intact. After implementing the new code, the return start condition is satisfied but no data is returned. Is there any solution for this?

  • How do you tell that no data is returned? NACK? Bus hang? No RXIFG interrupt?

    Looking at main() it reads 1 byte from register 0, 2 bytes starting at register 1 and 6 bytes starting at register 2. (It also does writes to registers 3, 4, and 5, which may or may not be appropriate.) The results go into arrays SlaveType[0/1/2]; do you see anything there?

  • Q1) How do you tell that no data is returned?

    I used an oscilloscope to monitor the SDA and SCL lines and there is no data or clock being transmitted, once i stepped through the code I could see that the TXIFG flag is not set and the ISR is not traversed through. Sometimes the data gets transmitted with the source code correctly traversed but the oscilloscope then shows just the Transmit portion alone. I was hoping to catch the RX bits via oscilloscope. I am including the function call statement i.e. I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH); in a while(1) continuously running loop.

    Q2)Looking at main() it reads 1 byte from register 0, 2 bytes starting at register 1 and 6 bytes starting at register 2. (It also does writes to registers 3, 4, and 5, which may or may not be appropriate.) The results go into arrays SlaveType[0/1/2]; do you see anything there?

    In my code, i had changed the code line  "#define TYPE_0_LENGTH  4 " , to read 4 Bytes from Slave.

    Coming to main(), i had commented out 3 write function calls and the rest of the two read function calls as per my use case, so the main function only includes:


    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

    initClockTo16MHz();
    initGPIO();
    initI2C();

    while(1)

    {

    I2C_Master_ReadReg(SLAVE_ADDR, CMD_TYPE_0_SLAVE, TYPE_0_LENGTH);

    }

  • How is your ACS37800 installed? Is this a commercial breakout board? I'm wondering about how DIO_0/_1 are configured.

    I'm not quite sure what to do with data sheet Table 2, since (1) DIO_0/_1 are single-valued (2) DIO_2 doesn't exist (3) the "Configuring the DIO pins" section (p. 21) talks about low=1. I'm not sure I believe any of it. So I would fall back on what Sparkfun says about this device, that the default I2C address (DIO_0/_1 pulled to GND) is 0x60.

    https://cdn.sparkfun.com/assets/1/9/f/6/9/Qwiic_Power_Meter-ACS37800_Schematic.pdf

    It  does seem to be ACK-ing 0x7F though; it bothers me that that's a reserved I2C address, though (to my knowledge) it has no current usage.

    And yes, the scope trace looks odd in any case. It might be useful to introduce an artificial delay (__delay_cycles(500) or some such) to see where the I2C unit thinks the transactions start/end.

**Attention** This is a public forum