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:I2C

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

https://e2e.ti.com/support/power-management-group/power-management/f/power-management-forum/1136143/bq76940-i2c

器件型号:BQ76940
主题中讨论的其他器件: BQ76920BQ76930MSP430F247

您好!

我正在设计 BMS 板固件、使用 mspf247作为主 MCU、使用 bq76940作为 AFE 来监控电池。 这两个器件之间的通信接口是 I2C。

困扰我的是每个新 PCBA 板在首次上电时、都正确读取了串联电池电压、电池组电压。

运行一段时间后、读数将被打乱。 和后续调试显示数据读取不正确。

基本编程逻辑是配置 bq76940持续监控电池电压、定期电池组电压、警报信号将每250ms 触发一次中断、

在 ISR 例程中设置相应的标志。

在任务中、将读取电压和库仑。

下面  、我提出了一些代码供参考、

void I2C_Initialize()

UCB0CTL1 |= UCSSEL_2+UCSWRST;//启用软件复位,使用 SMCLK 作为 USCI 时钟源
//UCB0CTL1 |= UCSSEL_1+UCSWRST;//启用软件复位,使用 ACLK 作为 USCI 时钟源
UCB0CTL0 = UCMST + UCMODE_3 + UCSYNC;//设置为 I2C 主控模式
UCB0BR0 = 10;// 92.16KHz @0.9216MHz 的 SCLK、确保 SCLK 不超过100KHz
UCB0BR1 = 0;
UCB0I2CIE = 0;//禁用 NACK、检测到停止条件、检测到启动条件、仲裁丢失中断
IE2 &=~(UCB0TXIE + UCB0RXIE);//禁用 Tx&Rx 中断
UCB0CTL1 &=~UCSWRST;//从复位状态释放
bqI2CError = false;//清除 i2c 故障错误标志
bqI2CStatusReadError = NO_ACTIVICE_INASIONY_STATUS_4;

// 76940初始化

空 BqInitializeqMaximo (空)

uint16_t count = 0;
bqCoulomb = 0;
bqTotalCoulomb = 0;
bqBalanceIndex = 0;
RAM_CELL_Balance=bqBalanceIndex;

//BQ76920/BQ76930/BQ76940从"发运至正常"转换至"首次读取操作"需要250ms/400ms/800ms、数据表、第21页。
///ALERT 将在船至正常转换后大约990ms 内设置。
//保持此处以设置警报。
while (true)

DELAY_1ms (1);
count++;
if (BqIsAlert()=true)

中断;

其他

if (计数>= 1200)

///MCU 已通电、但未设置 In 1s 警报...错误
中断;




//虚拟写入命令到 BQ
BqSetRegisterByte (SYS_STAT、0xff);//清除 ALERT
//t=BqGetRegisterByte (SYS_STAT);


//将 CC_CFG 设置为建议值0x19
//t=BqGetRegisterByte (CC_CFG);
BqSetRegisterByte (CC_CFG、0x19);
//t=BqGetRegisterByte (CC_CFG);

//读取 ADC 增益和偏移
bqAdcGain = BqGetAdcGain ();
bqAdcOffset = BqGetRegisterByte (ADCOFFSET);

//根据阈值设置和增益+偏移信息设置 OV_TRIP 和 UV_TRIP
OVPThreshold = logic.regbyte_ov_Trip;
BqSetRegisterByte (OV_TRIP、BqTripConversion (OVPThreshold、bqAdcGain、bqAdcOffset));
//t=BqGetRegisterByte (OV_TRIP);

UVPThreshold = logic.regbyte_uV_TRIP;
BqSetRegisterByte (UV_TRIP、BqTripConversion (UVPThreshold、bqAdcGain、bqAdcOffset));
//t=BqGetRegisterByte (uV_TRIP);

//设置保护
//SCD
regPROTECt1_t protect1;
protect1.Protect1BIT.scd_delay = SCDDelay;
protect1.Protect1BIT.SCD_THRESH = SCDThresh;
protect1.Protect1Bit.RSNS=1;
BqSetRegisterByte (PROTECT1、protect1.Protect1Byte);
//t=BqGetRegisterByte (PROTECT1);

//OCD
regPROTECT2_t protect2;
protect2.Protect2bit。ocd_delay = OCDDelay;
protect2.Protect2bit。ocd_thresh = OCDThresh;
BqSetRegisterByte (PROTECT2、protect2.Protect2Byte);
//t=BqGetRegisterByte (PROTECT2);

//OVDelay、UVDelay
regPROTECT3_t protect3;
protect3.Protect3Bit.OV_delay = OVDelay;
protect3.Protect3Bit.uV_delay = UVDelay;
BqSetRegisterByte (PROTECT3、protect3.Protect3Byte);
//t=BqGetRegisterByte (PROTECT3);

//设置系统控件
regSYS_CTRL1_t ctrl1;
ctrl1.SysCtrl1BIT.ADC_EN = logic.regbit_ADC_en;
ctrl1.SysCtrl1BIT.load_present = 0;//只读位
ctrl1.SysCtrl1BIT.shut_a = 0;//不要进入运输模式
ctrl1.SysCtrl1BIT.shut_B = 0;//不要进入运输模式
ctrl1.SysCtrl1BIT.TEMP_SEL = logic.regbit_temp_SEL;//External热 敏电阻;//0 =芯片温度;1 =热敏电阻温度
BqSetRegisterByte (SYS_CTRL1、ctrl1.SysCtrl1Byte);
//t=BqGetRegisterByte (SYS_CTRL1);

regSYS_CTRL2_t ctrl2;
ctrl2.SysCtrl2BIT.CC_EN = logic.regbyte_sys_ctrl2.SysCtrl2BIT.CC_EN;//0 =禁用连续读取;1 =启用
ctrl2.SysCtrl2Bit.CC_OneShot = 0;//0 =无操作;1 =触发单次读取
ctrl2.SysCtrl2bit。delay_DIS = 0;//0 =正常延迟;1 =无延迟(250ms)
ctrl2.SysCtrl2BIT.CHG_ON = 0;// 0 = CHG FET 关闭;1= CHG FET 打开
ctrl2.SysCtrl2BIT.DSG_ON = 0;//0 = DSG FET 关闭;1 = DSG FET 关闭
/ctrl2.SysCtrl2bit。WAKE_EN = 0;// BQ76930中不存在
/ctrl2.SysCtrl2BIT.WAKE_T =0;// BQ76930中不存在
BqSetRegisterByte (SYS_CTRL2、ctrl2.SysCtrl2Byte);//初始化时关闭 chg 和 DSG
//t=BqGetRegisterByte (SYS_CTRL2);

regSYS_STAT_t 状态;
STATUS.StatusByte = BqGetRegisterByte (SYS_STAT);
if (STATUS.STATUSByte 和 STAT_FLAGS)

//由于某种原因设置了设备状态标志,请将其清除。
BqSetRegisterByte (SYS_STAT、STAT_FLAGS);

#pragma vector=Port1_vector
_interrupt void ISR_PORT_1 (void)

中频(P1IFG 和 BIT5)

//读取 SYS_STAT 字节
bqI2CError = no_significance;
bqStatus.StatusByte = BqGetRegisterByte (SYS_STAT);
bqI2CStatusReadError = bqI2CError;
BqSetRegisterByte (SYS_STAT、STAT_CC_READY);
P1IFG &=~BIT4;//清除中断标志

void Taska (空)

uint8_t i;
静态 uint16_t TIME_OUT_COUNTER = 0;

TIME_OUT_COUNTER++;

if (bqI2CStatusReadError =false || TIME_OUT_COUNTER >100)

if (bqStatus.StatusBit.DEVICE_XREADY =true)

//此故障数据不可信任
FAULT.BQ.bit.XREADY = true;

其他

// 250ms 周期完成
if (bqStatus.StatusBit.CC_READY = true)

//读取库仑计数器
int32_t cur;
int16_t tmp;
tmp = BqGetCoulombCounter();
if (bqI2CError == false)

bqCoulomb =温度;
bqTotalCoulomb += bqCoulomb;
//此处计算电流,BQ 电流>0 -充电
CUR=(Int16_t)((bqCoulomb*8.44)/(Rsense));// 1uA 单元
CUR=(-cur/100000);//单位0.01A
RAM_Shunt_I=cur;

其他

//I2C 错误
FAULT.BQ.bit.i2c =真;


//读取电池电压
uint16_t min=65535、max=0;
for (i=0;<NUMBER_OF_CELLS;i++)

tmp = BqGetCellVoltage (I+1);
if (bqI2CError == false)

RAM_Vol_Cell[i]= tmp;
IF (RAM_Vol_Cell[i]<min)

MIN=RAM_VolT_Cell[i];
LowestCellIndex = I;

IF (RAM_Vol_Cell[I]>max)
Max=RAM_Vol_Cell[i];

其他

//I2C 错误
FAULT.BQ.bit.i2c =真;


RAM_HighestVol=最大值;
RAM_LowestVol=最小值;
IF (RAM_HighestVolt > RAM_MaxVolt)

RAM_MaxVolt = RAM_HighestVolt;

IF (RAM_LowestVolt < RAM_MinVolt)

RAM_MINVolt = RAM_LowestVolt;


如果(!(Flag_Work&Flag_After1rstReadVolt))

flag_work |=Flag_After1rstReadVolt;
SoC_FirstDataAvailable((U16*) RAM_Vol_Cell);


//读取电池组电压
tmp = BqGetPackVoltage();
if (bqI2CError == false)

bqPackVoltage = tmp;
RAM_SUM_Cells = tmp;

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

    大家好、Kevin、

    我们提供了一些软件示例、您可以查看这些示例、以帮助您进行调试。 除此之外、您还可以尝试使用另一个 IC 更换 IC、以查看问题是否仍然存在。 如果是软件隔离的、我强烈建议您查看示例代码。

    谢谢、
    Caleb

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

    谢谢 Perez、我不熟悉这个论坛、在哪里可以找到示例代码?

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

    大家好、Kevin、

    不用担心。 您可以在产品页面上找到示例代码。 这是链接。  https://www.ti.com/product/BQ76940#software-development 向下滚动、直至找到"Software Development"选项卡。

    谢谢、
    Caleb

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

    您好!

    我听从您的建议、i2c 的演示代码与我使用的代码相同、我通过在上电后执行以下操作来简化固件逻辑:

    I2C 设置为主模式、使用 SMCLK 作为 USCI 时钟源、时钟频率为92160、等待大约1200ms、然后开始写入控制1和控制2寄存器、并读回这两个寄存器的设置、

    for (;;)

    //LPM3;

    if (Flag_1ms = true)

    flag_1ms = false;
    //taskHandler();//每1ms 运行一次任务处理程序
    //设置系统控件
    regSYS_CTRL1_t ctrl1;
    ctrl1.SysCtrl1Byte=0x10;
    BqSetRegisterByte (SYS_CTRL1、ctrl1.SysCtrl1Byte);
    SYS_REG_COTR1=BqGetRegisterByte (SYS_CTRL1);

    regSYS_CTRL2_t ctrl2;
    ctrl2.SysCtrl2Byte=0x40;
    BqSetRegisterByte (SYS_CTRL2、ctrl2.SysCtrl2Byte);
    SYS_REG_COTR2=BqGetRegisterByte (SYS_CTRL2);

    RST_HWWDT();

    对于控制1寄存器、我写入值0x10、读回值0x98、

    对于控制2寄存器、我写入了值0x40并读回0x98、

    请帮助我找到线索、

    谢谢!

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

    尊敬的 Kevin:

    此问题是否与您最初报告的问题不同? 这似乎是一个不同的问题-您在写入之前代码中的这些控制寄存器时遇到了问题吗?

    此致、

    Matt

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

    您好、Matt、

    是的、使用我的原始代码写入这些控制寄存器也会出现问题。  

    在我的原始代码中、对于每个新的 PCBA、第一次上电时、我认为写入这些控制寄存器是成功的、因为我可以看到全部11节电池电压、并且电池组电压被正确读回。  仅在运行一段时间后、才会关闭 BMS 并再次打开电源、电压读数不再正确。

    我调试了76940初始化过程、发现对这些控制寄存器的写入和读回是完全不同的。

    因此、原始代码和新的简化代码存在相同的问题。

    这些控制寄存器设置不正确、76940无法正常工作。

    这是原始代码的逻辑、

    在 ADC_EN 打开的情况下设置 SYS_CTRL1寄存器。 在 CC_EN 打开的情况下设置 SYS_CTRL2。

    76940将每250ms 切换一次 ALERT 信号、ALERT 信号将触发 MCU 中断。

    将在 中断例程中读取和清除 SYS_STAT 寄存器。

    实际读取电压和库仑计数将在任务中执行。

    谢谢

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

    尊敬的 Kevin:

    这不是一个常见问题。 我建议使用您的代码捕获逻辑分析仪、以查看可能发生的情况。 您可以通过将 EVM 连接到 GUI 并在逻辑分析仪上进行捕获进行比较、从而对此进行比较。

    此致、

    Matt

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

    您好、Matt、

    我听从您的建议、捕获这样的波形

    在 AL 上无信号

    L

    有什么建议吗?

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

    尊敬的 Kevin:

    这不能由 BQ76940器件引起、因为主机应驱动通信。 BQ76940将无法控制 I2C 时钟、仅控制主机。

    此致、

    Matt

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

    您好、Matt、

    我知道 BQ76940是由主机驱动的、在我们的设计中是 msp430F247 MCU。 我使用 TI 评估软件测试了电路板上的 BQ76940、BQ76940工作正常。 它肯定是在 mastor 侧。 向 BQ 器件发送写入命令时、I2C 似乎会成功生成起始位并发送从器件地址、但始终无法传输数据。

    根据 MCU 用户指南上的 I2C 模块说明、  当 一个字节的数据被发出时、UCB0TXIFG 标志应该被置位、但是它永远不会被置位、为什么呢?

    I2C 模块看起来不能正常工作。

     

    静态 INT8_t I2CSendBytes (uint8_t I2CSlaveAddress、uint8_t *数据缓冲区、uint16_t ByteCount、uint16_t * pSentByte)

      uint16_t DelayCounter = 0;
      uint16_t NumberOfBytesSent = 0;
      uint8_t *DataPointer;

      UCB0I2CSA = I2CSlaveAddress;
      DataPointer = pDataBuffer;

      //设置到传输方向,生成起始位
      UCB0CTL1 |= UCTR;
      UCB0CTL1 |= UCTXSTT;


      //等待生成起始条件和发送从机地址
      while (!(IFG2 & UCB0TXIFG))
      {
        DelayCounter ++;
        IF (DelayCounter >= Delay_Limit)
         中断;
      }


      //如果产生起始条件超时,则发送停止位
      IF (DelayCounter >= Delay_Limit)
      {
        *pSentByte = NumberOfBytesSent;
        UCB0CTL1 |= UCTXSTP;
        返回-1;
      }


      //起始位和从器件地址已成功发送,
      //接下来发送数据缓冲区中的所有数据
      for (NumberOfBytesSent = 0;NumberOfBytesSent < ByteCount;NumberOfBytesSent++)
      {
        UCB0TXBUF=*DataPointer;        =================== 这里的数据被写入传输缓冲器、 UCB0TXIFG 应该是                      

                                             自动清除 ===================

        DelayCounter = 0;
        

        //检查字节是否已发送


        while (DelayCounter < DELAY_LIMIT &&(!(IFG2和 UCB0TXIFG)||(UCB0CTL1和 UCTXSTT)))
        {
          DelayCounter++;
        }


        //检查是否发生 NACK 条件


        if (DelayCounter >= delay_limit)
        {
          *pSentByte = NumberOfBytesSent;
          //发送停止条件
          UCB0CTL1 |= UCTXSTP;
          返回-1;      ======================================================================== 发送一个字节++++++++++++++++++++++++++++++++++++++++时、始终在此处停止
        }


        //此处已成功发送一个字节
        DataPointer++;
      }


      //发送所有数据,清除 TX 标志,发送停止位
      IFG2 &=~UCB0TXIFG;
      UCB0CTL1 |= UCTXSTP;

      DelayCounter = 0;
      while (DelayCounter < DELAY_LIMIT &&((UCB0CTL1 & UCTXSTP)))
      {
        DelayCounter++;
      }


      *pSentByte = NumberOfBytesSent;
      //检查是否发生 NACK 条件
      IF (DelayCounter >= Delay_Limit)
      {
        UCB0CTL1 |= UCSWRST;
        返回-1;
      }
      其他
        返回0;

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

    尊敬的 Kevin:

    由于您的问题与 MSP430代码有关、我建议在  msp430F247上启动一个新的线程 -这样、该线程将被分配给 MSP430产品专家、他们可能会为您提供帮助。 我将关闭此主题、因为电池监控器不存在问题。

    此致、

    Matt