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 线路低电平、I2C 通信停止

Guru**** 1756570 points
Other Parts Discussed in Thread: BQ76940, MSP430FR6989
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1405860/bq76940-sdl-line-low-and-i2c-communication-stops

器件型号:BQ76940
Thread 中讨论的其他器件: MSP430FR6989

工具与软件:

大家好!

我使用 BQ76940 IC 进行电池平衡和监控的 BMS 设计。 我使用 MSP430FR6989 LaunchPad 来监控 i2c 通信期间 IC 的性能。 在我的代码中、我调用一次 i2c 函数来读取电池电压、然后再次 调用另一个 i2c 函数、从同一 IC 读取电池温度、在此期间通信停止、发现 SDL 线路很低。 SDL Line 变为高电平、仅在重置硬件后。 您能否提供帮助、说明代码是否出错、或者它是否存在任何硬件问题?  我在这里发送代码。

#include
#include "driverlib.h"

//定义 BQ76940的 I2C 地址
#define BQ76940_I2C_ADDRESS 0x08

//定义 BQ76940电芯电压读数的寄存器地址
#define CELL_VOLTAGE_START_REG1 0x14
#define CELL_VOLTAGE_START_REG2 0x16

//函数原型
void initClock (void);
void initI2C76 (void);
void initI2C34Z (void);
uint8_t readCellVoltage1 (uint16_t 电压);
uint8_t readCellVoltage2 (uint16_t 电压);
void I2C_BUS_RESET (void);
void delay (uint16_t ms);

void initClock (void){
//将 DCO 设置为8MHz
CS_setDCOFreq (CS_DCORSEL_0、CS_DCOFSEL_6);

//配置时钟源
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

//可选:将8MHz 的 FRAM 等待状态设置为0
FRAMCTL_configureWaitStateControl (FRAMCTL_ACCESS_TIME_CYCLES_0);
}

void initI2C76 (void){
//配置 I2C 引脚
GPIO_setAsPeripheralModuleFunctionInputPin (GPIO_PORT_P1、GPIO_PIN6 + GPIO_PIN7、GPIO_PRIMARY_MODULE_FUNCTION);

//初始化 I2C 主器件以与 BQ76940通信
EUSCI_B_I2C_initMasterParam i2cMasterParams ={
EUSCI_B_I2C_CLOCKSOURCE_SMCLK、//使用 SMCLK
8000000、// SMCLK = 8MHz
EUSCI_B_I2C_SET_DATA_RATE_100KBPS、// I2C 速度100kHz
0、//无字节计数器阈值
EUSCI_B_I2C_NO_AUTO_STOP //无自动停止
};

EUSCI_B_I2C_initMaster (EUSCI_B0_BASE、&i2cMasterParams);

}


//读取 BQ76940的电池电压
uint8_t readCellVoltage1 (uint16_t 电压)

uint8_t txData;
uint8_t rxData1[2];//两个字节用于电压  

//计算指定单元格的寄存器地址
txData = CELL_VOLTAGE_START_REG1;

//设置 I2C 从机地址
EUSCI_B_I2C_setSlaveAddress (EUSCI_B0_BASE、BQ76940_I2C_ADDRESS);
//启用 i2c
EUSCI_B_I2C_ENABLE (EUSCI_B0_BASE);
EUSCI_B_I2C_masterSendSingleByte (EUSCI_B0_BASE、txData);

//读取电压数据  
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);
}

//读取 BQ76940的电池电压
uint8_t readCellVoltage2 (uint16_t 电压)

uint8_t txData;
uint8_t rxData2[2];//两个字节用于电压  

//计算指定单元格的寄存器地址
txData = CELL_VOLTAGE_START_REG2;

//设置 I2C 从机地址
EUSCI_B_I2C_setSlaveAddress (EUSCI_B0_BASE、BQ76940_I2C_ADDRESS);
//启用 i2c
EUSCI_B_I2C_ENABLE (EUSCI_B0_BASE);
EUSCI_B_I2C_masterSendSingleByte (EUSCI_B0_BASE、txData);

//使用 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 |=位6;
P1DIR |=位7;


//切换 SCL 以释放任何内容

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

P1OUT^=BIT6;//切换
_delay_cycles (1000);

//生成停止条件
P1OUT|=BIT7;// SDA 高电平
P1OUT|=BIT6;// SCL 高电平

_delay_cycles (1000);

}
}

// main
int main (void)

WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器

//初始化系统时钟

initClock();
uint8_t 状态;
uint8_t 状态1;
uint8_t 状态2;


//初始化 I2C 接口  
initI2C76();

//先前配置的端口设置
PM5CTL0 &=~μ H LOCKLPM5;
//启用全局中断
___ enable_interrupt ();


Status1 = readCellVoltage1 (电压);
I2C_BUS_RESET();
Status2 = readCellVoltage2 (电压);

//延迟以使 BQ76940达到稳定
delay (100);// 100ms delay

返回0;
}

void delay (uint16_t ms){
while (ms=ms-1){
__delay_cycles (8000);//假设8 MHz 时钟延迟为1ms
}
}


//编译器版本// 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
错误编译器不受支持!
#endif

uint8_t rx_val = 0;
switch (__EVEN_IN_RANGE (UCB0IV、USCI_I2C_UCBIT9IFG)){
case USCI_NONE:break;//向量0:无中断
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:时钟低电平超时
case USCI_I2C_UCBIT9IFG:break;// Vector 30:9 bit
默认值:中断;
}
}

此致

saptarishi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好、Saptarishi、

    BQ76940是从器件、因此不会驱动 SDA 线路。  

    如果 SDA 卡在低电平、您应该发送9个时钟信号、这也应该会释放数据总线。 我建议使用逻辑分析仪/示波器捕获来检查 I2C 信号完整性。

    此致、

    Luis Hernandez Salomon