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**** 2558250 points
Other Parts Discussed in Thread: BQ76940

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

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

器件型号:BQ76940

各位专家、您好!

我正在使用    BQ7694003设计13节 BMS。 我在写入 BQ 寄存器时遇到问题。 IC 不会在第9个周期提供 ACK。 SDA 线在第9个周期内不会被拉低。  https://e2e.ti.com/support/power-management/f/196/t/323329之前也提出了同样的问题 、但未指出解决方案和原因。 我更换了 BMS IC、但问题仍未解决。

我研究 了 http://www.ti.com/lit/zip/sluc583上提供的代码 和 ap note http://www.ti.com/lit/pdf/slva626 、并相应地编写了我的代码。  

在我的 I2C 设置中-  

主机 MCU -> 主器件(始终)
BQ76940 -> 从器件(始终)

我认为这种设置是正确的、因为 BQ 不会生成 SCL、因此在任何事件(TX 或 Rx)中它都不能是主器件。 因此、它将始终是从器件、而 MCU 将始终是主器件、因为它会生成 SCL。 我的理解是否正确?

接下来介绍 I2C 软件。 为了解释我的软件流程、我将考虑 CC_CFG 寄存器的示例

Bq_addr = 0x08或0000 1000
CC_CFG :addr = 0x0B 或0000 1011
         数据= 0x19或0001 1001
 CRC = 0x89或1000 1001

CRC 多项式:x8 + x2 + x + 1 = 1 0000 0111
CRC 的计算公式为:Bq_addr (8位) | CC_CFG (8位) | DATA (8位)  

                      0000 1000 | 0000 1011 | 0001 1001

由于 CRC 多项式的幂为8、因此在上述二进制数后附加8个零、然后计算 CRC
我得到了0x89作为上述情况的 CRC

然后、整个 I2C 帧被发送到 BQ。 BQ 在接收到的每个字节后发送一个 ACK。 帧格式为
START |   SLAVE_ADDR (7)+W (1)   |  REGISTER_ADDR (8)  DATA (8) |   CRC (8)  |   STOP

(n) ->表示位数

SLAVE_ADDR + W = 0001 0000 (BQ_ADDR 左移1)
REGISTER_ADDR = 0000 1011
数据= 0001 1001
CRC = 1000 1001

SLAVE_ADDR 是左移1位的 BQ 地址。 该域的第8位为0、表示主机处于传输模式(MT 模式)。 因此、主器件将数据写入从器件的寄存器。

现在的问题是 、BQ 不是在 SLAVE_ADDR + W 之后的第9个周期发送 ACK。SLAVE_ADDR + W 字节已成功发送、但 BQ 在第9个周期给出了 NACK、SDA 未拉低。  
以下是我在 BQ IC 的不同引脚上观察到的电压读数-  

(所有电压均为 WRT 接地)

TS1 = 0.0V (启动后)
TS2 = 20.2V
TS3 = 36.4V
CAP1 = 3.28V
CAP2 = 23.7V
CAP3 = 40.1V
REGSRC = 18.4V
VC5X = 20.4V [C1、C2、C3、C4、C5]
VC10X = 36.7V [C6、C7.C8.C10]
BAT = 53.2V [C11、C12、C13、C15]
PACK+ = 53.3V

我使用了3个10k NTC 热敏电阻、每个热敏电阻焊接在 TS1-GND、TS2-VC5X、TS3-VC10X 之间。 当我按下 BOOT 按钮时、TS1电压上升至2.7V。此外、在连接电池后应用 BOOT 信号。 BQ 启动后会启动 I2C 通信。
我还使用了3.3 - 5V 双向逻辑电平转换器、以实现5V MCU 和3.3V BQ IC 之间的安全且正确的通信。

那么、引发此问题的原因是什么? BQ 为何不发送 ACK? (PS:我无法访问 EVM 板、因此不要要求在 EVM 上测试 I2C)

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

    您可能已经使用以下未移位地址计算了 CRC:0000 1000 | 0000 1011 | 0001 1001
    如果使用发送到器件的实际字节(0001 0000 | 0000 1011 | 0001 1001)进行计算、则 CRC 应为0x7A

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

    您好、Matt

    在这种情况下、我是否应该在 CRC 字节传输后获得 NACK? 为什么我在 SLA+W 字节后得到否定应答、即使它已正确发送

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

    要真正进行调试、您需要使用示波器捕获波形。 您应该在电平转换器的 BQ76940侧捕获波形。

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

    问题已解决!

    经过数周的调试、我终于让 BMS 与 MCU 进行通信。 因此、我将发布检查清单、要执行的操作、预防措施和调试过程中要遵循的步骤

    我的设置是:
    MCU:Arduino 微型(5V 型号)
    BMS:BQ7694003 (3.3V 型号)
    电池组:13-15s 可配置

    硬件调试

    1.从原理图开始、确保遵循与 BQ 相关的数据表和参考设计。 我发现 TIDR773和 TIDA00792非常有用。 TIDR 使用 P 沟道 MOSFET
    而 TIDA00792使用 N 沟道 MOSFET 实现平衡。 首选项由您决定。 REST 在两种设计中的所有内容在概念上都是相似的。

    2.确保根据需要将电容器放置在靠近 IC 引脚的位置。 使负载电路远离敏感数字电路、以最大限度地减少耦合到数字电路中的噪声。  

    3.专门接地的完整 PCB 层将显著降低噪声。  

    尽管 BQ 设计用于处理电池随机连接、但仍处于更安全的状态、请先插入电池、GND 先插入电池、然后插入电池芯1、再插入电池芯2、再插入电池芯3、依此类推、直至插入最后一个电池。

    5.保持 I2C 布线较短,并确保两者之间没有太多电容耦合。 这种耦合会导致 I2C 通信期间误识别位

    6.使用开尔文连接进行 R_sense 连接。 它可以获得更好的 CC 结果。  https://www.analogue.com/en/analogue-dialog/articles/optimize-high-current-sensing-accuracy.html

    7.不要忘记 I2C 的上拉电阻器! 否则整个通信将失败。 通常、4.7K - 10k 电阻器用于上拉。 以下是有关 I2C 通信基础知识的良好指南。 www.ti.com/lit/an/slva704/slva704.pdf

    8.如果与我一样、BMS 和 MCU 之间存在逻辑电平差异、请使用逻辑电平转换器。  在我的示例中、虽然5V MCU 能够从3.3V BMS 读取数据、但它错误地读取了一些寄存器。 因此、为了避免这种情况、请使用逻辑电平转换器。  https://learn.sparkfun.com/tutorials/bi-directional-logic-level-converter-hookup-guide/all。在我的情况下、BMS 高电平(最大值)和 MCU 高电平(最小值)之间的差异仅为0.1V。  因此、我依靠运气正确识别 I2C 信号。

    9.现在最重要的是、请检查数据表并验证以下引脚上的标称电压读数。  
    TS0、TS1、TS2
    CAP1、CAP2、CAP3
    V5X、VC10X、BAT
    REGSRC
    REGOUT

    CAP1 - GND = 3.3V
    CAP2 - VC5X = 3.3V
    CAP3 - VC10X = 3.3V
    REGOUT = 3.3V  

    如果所有这些引脚上的电压读数都正确、那么您可以稍微放松一下! 您的硬件没有故障。

    10.也连接 NC 引脚! 此外、如果未使用热敏电阻、则通过10k 电阻器将相应的 TSX 引脚下拉至 GND。

    11.在 TS1引脚上需要一个引导信号来唤醒 BQ76940 IC。 不要指望 IC 自己唤醒:)

    12.将 BQ 的 ALERT 引脚连接到 MCU 上的中断引脚。 这将帮助您快速识别和清除故障



    软件调试

    如果你喜欢摇滚,那么你会喜欢软件调试,因为它涉及很多的头砰砰声:)

    1.给自己拿一杯咖啡。

    2.确保所有的引脚声明和 ISR 均已设置并正常工作。 逐段调试整个代码。 不要同时调试1000行代码。

    3.要测试 I2C 通信,首先运行 I2C 扫描器代码以查找 BQ IC。 这将同时完成两件事情-您可以验证 BQ IC 的 I2C 地址、此外、如果器件响应、则可以确保器件处于活动状态!

    4. MCU 识别到 BQ 后、测试 I2C 读取和写入功能。 (可选)读取 BQ 器件的所有寄存器并记下它们。
    对于所有 Arduino 扇形机,请使用 Wire() Library。 读取序列为-  

    /*读取1个字节*/
    字节寄存器 Read (字节 regAddress)

    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    wire.endTransmission ();
    Wire.requestFrom (bqI2CAddress、1);

    return (Wire.read());

     

    /*读取2个字节 */
    int 寄存器 DoubleRead (字节 regAddress)


    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    wire.endTransmission ();

    Wire.requestFrom (bqI2CAddress、2);

    字节 reg1 = Wire.read();
    字节 reg2 = Wire.read();

    int bined =(int) reg1 << 8;
    组合|= reg2;

    返回(合并);



    5.查找数据表以查找您的 BQ IC 是否启用了 CRC。 如果未启用 CRC、则可以使用正常的 I2C 通信协议直接写入 BQ 寄存器。 如果启用了 CRC、则必须计算 CRC 并将其发送到 BQ、否则它不会接受对其寄存器的任何写入请求。
    同样、TI 在 I2C http://www.ti.com/lit/an/slva704/slva704.pdf 上提供了一个超性感且简单的指南 


    /*不带 CRC 的写操作*/
    空寄存器写入(字节 regAddress、字节 regData)


    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    Wire.write (regData);
    Wire.write (0x7A);
    wire.endTransmission ();


    /*用 CRC*/写入

    空寄存器 WriteCRC (unsigned char regAddress、unsigned char regData)

    uint8_t values[3]={(bqI2CAddress << 1)、regAddress、regData};
    uint8_t crc = calc_crc (值、3);

    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    Wire.write (regData);
    Wire.write (CRC);
    wire.endTransmission ();

    unsigned char calc_crc (unsigned char * ptr、unsigned char len)

    unsigned char key = 7;
    unsigned char i;
    unsigned char CRC = 0;

    while (len--!=0)

    对于(I = 0x80;I!= 0;I /= 2)

    if ((CRC & 0x80)!= 0)

    CRC *= 2;
    CRC ^= KEY;

    其他
    CRC *= 2;

    如果(*ptr & I)!= 0)
    CRC ^= KEY;

    PTR++;

    返回(CRC);

     




    这是调试会话的结果!

    最适合您的 BMS 项目。  
    我希望这对您有所帮助!

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

    问题已解决!

    经过数周的调试、我终于让 BMS 与 MCU 进行通信。 因此、我将发布检查清单、要执行的操作、预防措施和调试过程中要遵循的步骤

    我的设置是:
    MCU: Arduino 微型(5V 型号)
    BMS: BQ7694003 (3.3V 型号)
    电池组: 13-15s 可配置

    硬件调试

    1.从原理图开始、确保遵循与 BQ 相关的数据表和参考设计。 我发现 TIDR773和 TIDA00792非常有用。 TIDR 使用 P 沟道 MOSFET
    而 TIDA00792使用 N 沟道 MOSFET 实现平衡。 首选项由您决定。 REST 在两种设计中的所有内容在概念上都是相似的。

    2.确保根据需要将电容器放置在靠近 IC 引脚的位置。 使负载电路远离敏感数字电路、以最大限度地减少耦合到数字电路中的噪声。  

    3.专门接地的完整 PCB 层将显著降低噪声。  

    尽管 BQ 设计用于处理电池随机连接、但仍处于更安全的状态、请先插入电池、GND 先插入电池、然后插入电池芯1、再插入电池芯2、再插入电池芯3、依此类推、直至插入最后一个电池。

    5.保持 I2C 布线较短,并确保两者之间没有太多电容耦合。 这种耦合会导致 I2C 通信期间误识别位

    6.使用开尔文连接进行 R_sense 连接。 它可以获得更好的 CC 结果。  https://www.analogue.com/en/analogue-dialog/articles/optimize-high-current-sensing-accuracy.html

    7.不要忘记 I2C 的上拉电阻器! 否则整个通信将失败。 通常、4.7K - 10k 电阻器用于上拉。 以下是有关 I2C 通信基础知识的良好指南。 www.ti.com/lit/an/slva704/slva704.pdf

    8.如果与我一样、BMS 和 MCU 之间存在逻辑电平差异、请使用逻辑电平转换器。  在我的示例中、虽然5V MCU 能够从3.3V BMS 读取数据、但它错误地读取了一些寄存器。 因此、为了避免这种情况、请使用逻辑电平转换器。  https://learn.sparkfun.com/tutorials/bi-directional-logic-level-converter-hookup-guide/all。在我的情况下、BMS 高电平(最大值)和 MCU 高电平(最小值)之间的差异仅为0.1V。  因此、我依靠运气正确识别 I2C 信号。

    9.现在最重要的是、请检查数据表并验证以下引脚上的标称电压读数。  
    TS0、TS1、TS2
    CAP1、CAP2、CAP3
    V5X、VC10X、BAT
    REGSRC
    REGOUT

    CAP1 - GND = 3.3V
    CAP2 - VC5X = 3.3V
    CAP3 - VC10X = 3.3V
    REGOUT = 3.3V  

    如果所有这些引脚上的电压读数都正确、那么您可以稍微放松一下! 您的硬件没有故障。

    10.也连接 NC 引脚! 此外、如果未使用热敏电阻、则通过10k 电阻器将相应的 TSX 引脚下拉至 GND。

    11.在 TS1引脚上需要一个引导信号来唤醒 BQ76940 IC。 不要指望 IC 自己唤醒:)

    12.将 BQ 的 ALERT 引脚连接到 MCU 上的中断引脚。 这将帮助您快速识别和清除故障



     软件调试

    如果你喜欢摇滚,那么你会喜欢软件调试,因为它涉及很多的头砰砰声:)

    1.给自己拿一杯咖啡。

    2.确保所有的引脚声明和 ISR 均已设置并正常工作。 逐段调试整个代码。 不要同时调试1000行代码。

    3.要测试 I2C 通信,首先运行 I2C 扫描器代码以查找 BQ IC。 这将同时完成两件事情-您可以验证 BQ IC 的 I2C 地址、此外、如果器件响应、则可以确保器件处于活动状态!

    4. MCU 识别到 BQ 后、测试 I2C 读取和写入功能。 (可选)读取 BQ 器件的所有寄存器并记下它们。
    对于所有 Arduino 扇形机,请使用 Wire() Library。 读取序列为-  

    /*读取1个字节*/
    字节寄存器 Read (字节 regAddress)

    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    wire.endTransmission ();
    Wire.requestFrom (bqI2CAddress、1);

    return (Wire.read());

    /*读取2个字节 */
    int 寄存器 DoubleRead (字节 regAddress)

    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    wire.endTransmission ();

    Wire.requestFrom (bqI2CAddress、2);

    字节 reg1 = Wire.read();
    字节 reg2 = Wire.read();

    int bined =(int) reg1 << 8;
    组合|= reg2;

    返回(合并);



    5.查找数据表以查找您的 BQ IC 是否启用了 CRC。 如果未启用 CRC、则可以使用正常的 I2C 通信协议直接写入 BQ 寄存器。 如果启用了 CRC、则必须计算 CRC 并将其发送到 BQ、否则它不会接受对其寄存器的任何写入请求。  
    同样、TI 在 I2C http://www.ti.com/lit/an/slva704/slva704.pdf 上提供了一个超性感且简单的指南 


    /*不带 CRC 的写操作*/
    空寄存器写入(字节 regAddress、字节 regData)


    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    Wire.write (regData);
    Wire.write (0x7A);
    wire.endTransmission ();



    /*用 CRC*/写入

    空寄存器 WriteCRC (unsigned char regAddress、unsigned char regData)

    uint8_t values[3]={(bqI2CAddress << 1)、regAddress、regData};
    uint8_t crc = calc_crc (值、3);

    Wire.beginTransmission(bqI2CAddress);
    Wire.write (regAddress);
    Wire.write (regData);
    Wire.write (CRC);
    wire.endTransmission ();

    unsigned char calc_crc (unsigned char * ptr、unsigned char len)

    unsigned char key = 7;
    unsigned char i;
    unsigned char CRC = 0;

    while (len--!=0)

    对于(I = 0x80;I!= 0;I /= 2)

    if ((CRC & 0x80)!= 0)

    CRC *= 2;
    CRC ^= KEY;

    其他
    CRC *= 2;

    如果(*ptr & I)!= 0)
    CRC ^= KEY;

    PTR++;

    返回(CRC);

     

    对于 BQ769x0、CRC 多项式为 x^8 + x^2 + x + 1。 键为7。  https://www.digikey.com/eewiki/display/microcontroller/CRC+Basics 

    请随意了解 CRC 计算的步骤。 此外、使用 CRC 时、传输顺序和 CRC 计算稍有不同、因此请确保查看数据表以了解更多详细信息。

    CRC 是根据发送的字节计算得出的

    6.确保将接收到的字节转换为实际值(伏特、安培等)。 请查阅数据表以了解公式。 正如我之前提到的、你一定会像摇滚一样! 编写软件将涉及很多  

    有点裂和头裂。 您必须在 HEX、DEC 和 BIN 世界中感到舒适

    7.要检查写功能是否正常工作、只需将值写入寄存器并读回寄存器即可。 如果您的 MCU 读取的值与您之前写入的值相同、则写入功能为

    正常工作、读取功能也是如此!

    8.确保在 XREADY 位置位时将其清零。 这样做将帮助您识别 BQ IC 面临某些问题时的事件 l (例如、系统瞬变过大)




    这是调试会话的结果!

    最适合您的 BMS 项目。  
    我希望这对您有所帮助!