CAN 仲裁是使用 ID 完成的,总线上的任何节点都可以使用任何 ID 进行传输(理想情况下不应该,但讨厌的节点可以)。
如果连接在同一 CAN 总线上的两个不同节点发送具有相同 ID 但数据字节不同的消息怎么办?
我的想法:它会在公共汽车上产生垃圾。谁拥有占主导地位的位,只有那些会被传输。
CAN 仲裁是使用 ID 完成的,总线上的任何节点都可以使用任何 ID 进行传输(理想情况下不应该,但讨厌的节点可以)。
如果连接在同一 CAN 总线上的两个不同节点发送具有相同 ID 但数据字节不同的消息怎么办?
我的想法:它会在公共汽车上产生垃圾。谁拥有占主导地位的位,只有那些会被传输。
CAN 规范第 6.1 节:
位错误:在总线上发送位的单元也监视总线。当监控的位值与发送的位值不同时,必须在该位时间检测位错误。一个例外是在仲裁字段的填充比特流期间或在 ACK SLOT 期间发送“隐性”比特。
因此,当另一个节点正在发送“0”时,首先发送“1”的节点将注意到比特错误,然后正常发出错误信号 - 通过发送错误标志(参见第 3.1.3 节),如正式所述在第 6.2 节中。
非正式地,如果该节点是错误激活的(这应该是通常的情况),它将发送一个 6 个显性位的错误标志,所有其他节点也将检测到(作为填充错误)。这具有完全销毁该消息的效果:
然后,每个发送器将尝试重新发送 - 根据重新发送的精确时间,一个发送器可能在另一个之前充分启动总线的增益控制。否则,同样的顺序可能会再次发生。(或者另一个更高优先级的消息可能会让它们都关闭一段时间!)
受@clabbacchio 下面的答案启发的扩展答案。
您提到“讨厌的节点”,clabbacchio 提出了一个有效的观点,即如果两个节点在不同时间传输,每个接收器需要决定如何处理它的多个接收。
去年的一次黑客攻击证明了这一点。该论文在“PSCM 细节”部分讨论了攻击者如何与总线上的常规消息同步,并在“好”ECU 即将发送的消息之前播放他们的恶意消息。接收 ECU 接受较早的消息,更新其消息计数器,然后将“好”消息作为错误丢弃,因为它的消息计数器没有增加。
在您的问题中,您提出了这个假设:
谁拥有占主导地位的位,只有那些会被传输。
假设这两条消息是同时传输的,这是一个更普遍问题的特定情况。Martin 的有效答案涵盖了这个特定问题,但忽略了两个节点在不同时间传输的(更一般的)情况。
在这种情况下,总线上将会有两条 ID 相同但有效载荷不同的消息在循环,这取决于接收者的逻辑来区分这两条消息,并决定是否是他们需要接收的内容。如果他们无法区分这两条消息,他们可能会误解数据并导致比错误帧更严重的问题。
例如,一条消息包含温度传感器的读数,另一条消息包含执行器在同一字节上的目标位置(在现实生活中永远不会发生),您可能会让执行器在不知道的情况下将其作为其目标。
如果消息数据字段不同,您将(希望!)由于错误的 CRC 在总线上收到错误帧。