EXPLAINER / SVG ANIMATION
CAN 总线仲裁是怎么进行的
用可单步的动画演示多个节点同时发送时,如何通过 ID 逐位比较、显性位覆盖隐性位,无冲突地选出优先级最高的报文。
INTERACTIVE SIMULATION / CanArbitration
多个节点同时发送时,逐位比较:发隐性 1 却读到显性 0 的节点立即退出,发送显性 0 的节点继续。
| Node | 位 0 | 位 1 | 位 2 | 位 3 | 位 4 | 位 5 | 位 6 | 位 7 | Status |
|---|---|---|---|---|---|---|---|---|---|
| 0x120 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | — |
| 0x250 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | — |
| 0x3A0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | — |
显性 0 / 隐性 1
原理拆解
为什么需要仲裁
CAN 是多主总线:任何节点都可以在总线空闲时开始发送。如果两个节点同时开口,总线并不会”撞车丢包”——物理层把总线实现为”线与”:
- 显性位(dominant, 0):任一节点拉低,总线即为低。
- 隐性位(recessive, 1):所有节点都释放,总线才为高。
因此发送隐性位却读回显性位的节点,立刻知道自己输了,于是停止发送、转为接收。没有任何位被破坏,胜者无需重发——这就是 CAN 的非破坏性仲裁。
关键结论
- 仲裁只在 仲裁场(ID + RTR)进行,进入数据场后只有一个发送者。
- ID 数值越小,优先级越高,因为先出现显性 0 的一方获胜。
- 输掉的节点会自动转为接收,并在总线空闲后重试,报文不会丢。
- 标准帧(11 位 ID)与扩展帧(29 位 ID)可以共存:标准帧的 IDE 位为显性,因此同 ID 前缀时标准帧优先。
动手验证
上面的动画里,0x120 与 0x250 在第 0 位就分出胜负:0x120 发 0,0x250 发 1 却读回 0,于是 0x250 退出。0x3A0 坚持到第 2 位才输给 0x120。
理解了仲裁,再看 CAN 位定时计算器 就知道为什么采样点必须落在相位缓冲段之前:节点要在采样点读到总线真实电平,才能及时判断自己是否输掉仲裁。
APPLY IT / TOOLS