【通信进阶】为什么大疆机甲大师全用 CAN?一文看懂 CAN 总线“非破坏性仲裁”的底层魔法
前言在单片机开发中串口UART是最常用的点对点通信方式。但如果你的小车上有 4 个轮毂电机、1 个云台、1 个主控它们需要在一个网络里互相通信怎么办 用串口你需要拉无数根线形成一个复杂的星型网络。 用 I2C线距稍微长一点电容一变大波形直接糊掉而且主从架构下从机不能主动发数据实时性极差。为了解决多节点、高实时性、强抗干扰的痛点博世Bosch公司在 80 年代发明了汽车级的通信协议——CAN 总线Controller Area Network。今天我们抛开枯燥的协议手册直击 CAN 总线最天才的设计“线与逻辑”与“非破坏性仲裁”。一、 物理层的暴力美学差分信号与“显隐性”CAN 总线只有两根线CAN_H和CAN_L。它完全抛弃了传统的 TTL 电平高电平为 1低电平为 0而是采用了差分信号。隐性状态逻辑 1CAN_H 和 CAN_L 电压相等通常都是 2.5V。此时两线之间的电压差为 0V。你可以把它想象成总线处于“放松”状态没有任何人驱动它。显性状态逻辑 0CAN_H 被拉高约 3.5VCAN_L 被拉低约 1.5V。此时两线之间的电压差为 2V。这是一种被强行“驱动”的状态。核心物理法则线与逻辑Wired-AND 只要总线上有一个节点输出显性逻辑 0整个总线就会表现为显性逻辑 0 只有当所有节点都输出隐性逻辑 1时总线才表现为隐性逻辑 1。换句话说0 能覆盖 11 覆盖不了 0。0 是真正的霸主。二、 灵魂拷问大家同时说话怎么不打架在以太网CSMA/CD中如果两个节点同时发送数据总线上的电平会发生碰撞冲突。两个节点检测到冲突后会同时停止发送随机等待一段时间后再试。这叫“破坏性仲裁”非常浪费时间。但 CAN 总线采用了极其优雅的**“非破坏性仲裁CSMA/CDAMP”**。CAN 协议规定每个数据帧的开头是一个11 位或 29 位的 ID标识符。这个 ID 既代表了这条数据的含义也决定了这条数据的优先级。仲裁的微观过程名场面假设节点 A 和节点 B 同时侦听到总线空闲同时开始发送数据。它们会一边向总线上发送自己 ID 的每一位一边同时读取总线上的电平。第 1 位节点 A 发送 0节点 B 发送 0。总线线与结果为 0。A 和 B 读回来的都是 0。大家都觉得没毛病继续第 2 位节点 A 发送 0节点 B 发送 0。总线结果为 0。继续决战时刻比如第 3 位节点 A 的 ID 这一位是0显性节点 B 的 ID 这一位是1隐性。根据“0 覆盖 1”的原则总线上的实际电平变成了0。节点 A 读总线读到 0。A 想“我发的是 0读到的也是 0。很好没有冲突我继续发。”节点 B 读总线读到 0。B 瞬间倒吸一口凉气“等一下我明明发的是 1怎么读回来是 0总线上肯定有一个比我优先级更高的节点在发 0”节点 B 的反应立刻闭嘴停止发送转为接收模式。节点 A 的反应完全没有察觉到任何异常它就像走在空无一人的马路上一样继续把剩下的数据丝滑地发完。这就是“非破坏性”的精髓高优先级的数据没有任何延迟没有任何重发一次性穿透总线。而低优先级的节点会自动退让。三、 优先级的终极密码明白了仲裁过程你就立刻懂了 CAN 优先级的黄金定律ID 越小里面包含的 0显性位就越多且越靠前它的优先级就越高在电赛或实际工程中急停指令、电机转矩控制必须分配极小的 ID例如0x001哪怕总线再拥堵它也能佛挡杀佛瞬间送达。传感器温度心跳包分配较大的 ID例如0x5F0如果总线忙碌它就乖乖排队晚几毫秒送到也没关系。四、 总结没有复杂的握手协议没有主从机的轮询仅仅利用底层的“差分电平覆盖”机制加上精妙的 ID 位比较就实现了完美的分布式高可靠性通信。这也是为什么现代汽车里有上百个 ECU电子控制单元却能靠一根 CAN 巴士井然有序地运行。今日互动你在调试 CAN 总线时有没有遇到过“节点一直发不出数据最后进入 Bus-Off总线关闭状态”的悲剧你当时是怎么排查终端电阻或波特率问题的欢迎在评论区倒苦水