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.

BQ76940: SDL LINE LOW AND I2C COMMUNICATION STOPS

Part Number: BQ76940
Other Parts Discussed in Thread: MSP430FR6989

Tool/software:

Hi all,

I took BQ76940 IC for my BMS design for cell balancing and Monitoring. I took the MSP430FR6989 Launch Pad to Monitor the performance of the IC during i2c communication. In my code, I called i2c function one time to read the cell voltage and again one more i2c function called for cell temperature reading from same IC, where during that time Communication is stopped and found that SDL line is low. SDL Line becoming high, only after the resetting the hardware. Can you please assist whether the code is going wrong or is it any hardware issue?  I am sending the code here..

#include <msp430.h>
#include "driverlib.h"

// Defining I2C address OF BQ76940
#define BQ76940_I2C_ADDRESS 0x08

// Defining Register Adddress for cell voltage readings of BQ76940
#define CELL_VOLTAGE_START_REG1 0x14
#define CELL_VOLTAGE_START_REG2 0x16

// Function prototypes
void initClock(void);
void initI2C76(void);
void initI2C34Z(void);
uint8_t readCellVoltage1(uint16_t voltage);
uint8_t readCellVoltage2(uint16_t voltage);
void i2C_bus_reset(void);
void delay(uint16_t ms);

void initClock(void) {
// Set DCO to 8MHz
CS_setDCOFreq(CS_DCORSEL_0, CS_DCOFSEL_6);

// Configure clock sources
CS_initClockSignal(CS_ACLK, CS_VLOCLK_SELECT, CS_CLOCK_DIVIDER_1); // ACLK = VLOCLK
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); // SMCLK = DCO
CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); // MCLK = DCO

// Optional: Set FRAM wait state to 0 for 8MHz
FRAMCtl_configureWaitStateControl(FRAMCTL_ACCESS_TIME_CYCLES_0);
}

void initI2C76(void) {
// Configure the I2C pins
GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN6 + GPIO_PIN7, GPIO_PRIMARY_MODULE_FUNCTION);

// Initialize the I2C master to communicate with the BQ76940
EUSCI_B_I2C_initMasterParam i2cMasterParams = {
EUSCI_B_I2C_CLOCKSOURCE_SMCLK, // Use SMCLK
8000000, // SMCLK = 8MHz
EUSCI_B_I2C_SET_DATA_RATE_100KBPS, // I2C speed 100kHz
0, // No byte counter threshold
EUSCI_B_I2C_NO_AUTO_STOP // No autostop
};

EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &i2cMasterParams);

}


// READ CELL VOLTAGES OF BQ76940
uint8_t readCellVoltage1(uint16_t voltage)
{
uint8_t txData;
uint8_t rxData1[2]; // Two bytes for voltage 

// Calculate the register address for the specified cell
txData = CELL_VOLTAGE_START_REG1;

// Set the I2C slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, BQ76940_I2C_ADDRESS);
// enable i2c
EUSCI_B_I2C_enable(EUSCI_B0_BASE);
EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, txData);

// Read the voltage data 
EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
rxData1[0]= UCB0RXBUF;
rxData1[1] = UCB0RXBUF;
EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
EUSCI_B_I2C_disable(EUSCI_B0_BASE);
}

// READ CELL VOLTAGES OF BQ76940
uint8_t readCellVoltage2(uint16_t voltage)
{
uint8_t txData;
uint8_t rxData2[2]; // Two bytes for voltage 

// Calculate the register address for the specified cell
txData = CELL_VOLTAGE_START_REG2;

// Set the I2C slave address
EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE, BQ76940_I2C_ADDRESS);
// enable i2c
EUSCI_B_I2C_enable(EUSCI_B0_BASE);
EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, txData);

// Read the voltage data with CRC
EUSCI_B_I2C_masterReceiveStart(EUSCI_B0_BASE);
rxData2[0]= UCB0RXBUF;
rxData2[0] = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
rxData2[1] = EUSCI_B_I2C_masterReceiveMultiByteNext(EUSCI_B0_BASE);
EUSCI_B_I2C_masterReceiveMultiByteStop(EUSCI_B0_BASE);
EUSCI_B_I2C_disable(EUSCI_B0_BASE);
}

/

void i2c_bus_reset(void)
{
uint8_t i;
P1SEL1=~(BIT6+BIT7);
P1DIR |= BIT6;
P1DIR |= BIT7;


//Toggle SCL to release any

for(i=0;i<10;i++)
{

P1OUT^=BIT6; //Toggle
_delay_cycles(1000);

//Generate Stop Condition
P1OUT|=BIT7; // SDA high
P1OUT|=BIT6; // SCL high

_delay_cycles(1000);

}
}

// MAIN
int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // stop watchdog timer

// Initialize the system clock

initClock();
uint8_t status;
uint8_t status1;
uint8_t status2;


// Initialize the I2C interface 
initI2C76();

// previously configured port settings
PM5CTL0 &= ~LOCKLPM5;
// Enable global interrupt
__enable_interrupt();


status1 = readCellVoltage1(voltage);
i2C_bus_reset();
status2 = readCellVoltage2(voltage);

// Delay to allow the BQ76940 to stabilize
delay(100); // 100ms delay

return 0;
}

void delay(uint16_t ms) {
while (ms=ms-1) {
__delay_cycles(8000); // Assuming 8 MHz clock, 1 ms delay
}
}


// compiler version // Interrupt service routine for I2C
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = USCI_B0_VECTOR
__interrupt void USCI_B0_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void)
#else
#error Compiler not supported!
#endif
{
uint8_t rx_val = 0;
switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) {
case USCI_NONE: break; // Vector 0: No interrupts
case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG
case USCI_I2C_UCNACKIFG: break; // Vector 4: NACKIFG
case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG
case USCI_I2C_UCSTPIFG: break; // Vector 8: STPIFG
case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3
case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3
case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2
case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2
case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1
case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1
case USCI_I2C_UCRXIFG0: break; // Vector 22: RXIFG0
case USCI_I2C_UCTXIFG0: break; // Vector 24: TXIFG0
case USCI_I2C_UCBCNTIFG: break; // Vector 26: BCNTIFG
case USCI_I2C_UCCLTOIFG: break; // Vector 28: clock low timeout
case USCI_I2C_UCBIT9IFG: break; // Vector 30: 9th bit
default: break;
}
}

regards

saptarishi

  • Hello Saptarishi,

    The BQ76940 is a slave device, so it does not drive the SDA line. 

    If SDA is stuck low, you should send 9 clock signals, that should also release the data bus. I would suggest to use a logic analyzer/scope capture to check the I2C signal integrity.

    Best Regards,

    Luis Hernandez Salomon