🔋 BMS 通讯测试 · CAN 基础

⚡ 中小学生色系 · 轻松掌握
📘 工艺实战课程 · 第2章
🚌 CAN 物理层特性 差分信号 & 终端电阻
特性说明典型值 / 细节
差分信号CAN_H 与 CAN_L 电压差表示逻辑状态显性 (Dominant) : 差分 ≈ 2V;隐性 (Recessive) : 差分 ≈ 0V
终端电阻总线两端各并联 120Ω 电阻,抑制信号反射标准 CAN: 2×120Ω → 等效 60Ω;高速 CAN 必备
共模电压CAN_H / CAN_L 对地静态电压约 2.5V (隐性) ;显性时 CAN_H≈3.5V, CAN_L≈1.5V
线缆双绞线 (屏蔽/非屏蔽)特性阻抗 120Ω,推荐 1Mbps 以内
差分信号示意 CAN_H CAN_L 显性差≈2V
⭐ 差分信号:CAN_H 与 CAN_L 反向变化,抗干扰强
  • 🔹 终端电阻 – 位于总线最远两端,阻值 120Ω,消除反射。
  • 🔹 为什么是 120Ω? – 匹配双绞线特性阻抗,保证信号完整性。
  • 🔹 BMS 测试注意 – 断开终端电阻会导致通讯失败或波形畸变。
📦 CAN 数据帧结构 SOF · ID · DLC · Data · CRC · ACK
字段全称长度 (bits)功能 / 备注
SOFStart Of Frame1显性位,同步所有节点
IDIdentifier11 (标准) / 29 (扩展)决定优先级 & 报文过滤
DLCData Length Code4数据字节数 (0~8)
Data数据场0~64 (0~8 字节)BMS 电压、温度、SOC 等
CRCCyclic Redundancy Check15校验数据完整性,含 1 位定界符
ACKAcknowledge2 (1位应答+1位定界)接收节点置显性表示确认
SOF ID (11/29) DLC Data (0~8 Byte) CRC ACK EOF ⬆ 标准 CAN 数据帧 (11bit ID) ⬆
🧩 数据帧结构:从 SOF 到 ACK,每个字段都至关重要
  • 📌 ID 优先级 – 数值越小优先级越高,BMS 通常使用高优先级报文 (如错误、状态)。
  • 📌 DLC – BMS 常用 8 字节数据帧 (电压、温度、电流打包)。
  • 📌 CRC 校验 – 15位 CRC + 1位定界符,保证数据可靠。
⚖️ CAN 总线仲裁机制 非破坏性逐位仲裁
🏁

ID 越小
优先级越高

0️⃣1️⃣

显性位 (0)
战胜隐性位 (1)

🔁

逐位比较
直到分出胜负

📡

获胜节点继续发送
失败节点自动退出发送

  • ⚡ 仲裁原理 – 多个节点同时发送时,从 SOF 开始逐位比较 ID。显性位 (逻辑 0) 覆盖隐性位 (逻辑 1)。
  • ⚡ 非破坏性 – 仲裁失败的节点立即转为接收,不破坏总线数据。
  • ⚡ BMS 应用 – 电池状态报文 (如 SOC) 通常分配较低 ID,确保紧急数据优先通过。
节点A (ID=0b101) 1 (隐性) 0 (显性) 胜出 节点B (ID=0b110) 1 (隐性) 1 (隐性) 仲裁失败 🔍 第2位: 节点A显性0 → 仲裁获胜
🏆 逐位仲裁:ID 低位优先,显性位 “0” 赢得总线

🧪 BMS 测试实战提醒

  • 终端电阻测量:断开总线,用万用表测 CAN_H 与 CAN_L 之间电阻,应为 60Ω (两端各120Ω并联)。
  • 使用示波器观察差分信号:显性位差分电压约 2V,隐性约 0V。
  • CAN 报文 ID 规划:BMS 通常使用 0x100~0x7FF 范围,优先级按功能分配。

📟 CAN 帧解析示例 (C 语言风格)

typedef struct {
    uint8_t  SOF;        // 1 bit, 固定显性
    uint16_t ID;         // 11 bit (标准) 或 29 bit (扩展)
    uint8_t  DLC;        // 4 bit, 数据长度
    uint8_t  Data[8];    // 0~8 字节
    uint16_t CRC;        // 15 bit + 1 定界符
    uint8_t  ACK;        // 2 bit (应答+定界)
} CAN_Frame;

// 示例:BMS 电压报文 ID=0x351, DLC=8
CAN_Frame bms_voltage = {
    .SOF = 0,
    .ID  = 0x351,
    .DLC = 8,
    .Data = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0},
    .CRC = 0x4A2F,
    .ACK = 0x01
};