2、CAN总线基础回顾:CAN协议帧结构、CAN总线仲裁机制、CAN错误处理与总线状态

好,咱们开始第二讲。在正式进入FlexRay之前,我强烈建议先把CAN总线再捋一遍。为什么?因为FlexRay和CAN在物理层、协议层有不少相似之处,但差异也很大。你如果对CAN的理解不够扎实,后面学FlexRay时会很痛苦。我自己带项目时就吃过这个亏——团队里有人CAN协议没吃透,结果在混合网络设计时,把CAN的仲裁机制直接套用到FlexRay上,差点出大问题。

说白了,CAN总线到今天依然是车载网络的主力。它简单、可靠、成本低。但它的短板也很明显:带宽不够、实时性受限于仲裁机制。嗯,咱们先看它的核心——帧结构。

2.1 CAN协议帧结构

CAN的报文帧,我习惯把它分成这么几块:帧起始、仲裁场、控制场、数据场、CRC场、应答场、帧结束。你想想看,一个CAN帧在总线上跑,其实就是这么一串电平信号。

咱们重点看两种最常见的帧:数据帧和远程帧。数据帧用来发数据,远程帧用来请求数据。结构上几乎一样,区别在于远程帧没有数据场。

字段 长度(标准帧) 说明
帧起始(SOF) 1 bit 同步所有节点,显性电平
仲裁场(ID + RTR) 12 bits 11位ID + 1位RTR,决定优先级
控制场 6 bits IDE、保留位、DLC(数据长度)
数据场 0~8 bytes 实际数据内容
CRC场 16 bits 15位CRC + 1位CRC界定符
应答场 2 bits ACK Slot + ACK界定符
帧结束(EOF) 7 bits 隐性电平,表示帧结束

这里有个细节我提醒一下:标准帧的ID是11位,扩展帧是29位。我在项目中遇到过有人把标准帧和扩展帧混用,结果仲裁逻辑全乱了。嗯,设计时一定要统一规划ID分配策略。

关键点:CAN帧的数据场最多8字节。这在很多应用场景下是够用的,但对于需要传输大量数据的场景(比如OTA升级、高精度地图),8字节就成了瓶颈。这也是为什么后来有了CAN FD,甚至FlexRay。

2.2 CAN总线仲裁机制

仲裁机制,说白了就是多个节点同时发数据时,谁说了算。CAN用的是“载波监听多路访问/冲突检测”的变体,但它的处理方式很巧妙——非破坏性逐位仲裁。

怎么理解?每个节点在发送仲裁场时,会同时监听总线电平。如果自己发的是隐性电平(1),但总线上是显性电平(0),那它就输了,立刻停止发送,转为接收模式。赢的那个节点继续发。

举个例子:节点A的ID是0x100,节点B的ID是0x200。二进制展开后,0x100的ID值更小,所以它在仲裁时占优势。为什么?因为ID值越小,显性位越多,优先级越高。

// 伪代码示意:CAN仲裁过程
if (发送位 == 1 && 总线电平 == 0) {
    停止发送; // 仲裁失败
    转为接收模式;
} else {
    继续发送; // 仲裁成功
}

我个人习惯把CAN的仲裁机制总结成一句话:ID越小,优先级越高。你想想看,这其实是一种“谁的数字小谁先走”的逻辑。我在调试一个多节点系统时,曾经因为ID分配不合理,导致某个关键报文总是被低优先级的报文阻塞。后来重新规划了ID分配,问题才解决。

避坑指南:我曾经在项目中遇到一个奇怪的问题——两个节点同时发送相同ID的报文,结果总线一直处于仲裁状态,系统卡死。后来发现是ID分配重复了。所以,ID分配一定要全局唯一,别偷懒。

2.3 CAN错误处理与总线状态

CAN的错误处理机制,我觉得是它最牛的地方之一。它不像其他总线那样,出错了就重传,而是有一套完整的错误检测和恢复机制。

CAN定义了五种错误类型:

  • 位错误:发送节点发送的位与总线上的位不一致。比如你发了个显性,但总线上是隐性,那就出错了。
  • 填充错误:连续出现6个相同电平。CAN用了位填充机制,每5个相同位后插入一个相反位。如果检测到6个相同位,说明填充错误。
  • CRC错误:接收节点计算的CRC与发送节点的不一致。这个最常见,通常是总线干扰导致的。
  • 格式错误:帧格式不符合规范。比如EOF应该是7个隐性位,结果出现了显性位。
  • 应答错误:发送节点没有收到ACK。说白了,就是没人响应它。

每个节点都有两个计数器:发送错误计数器(TEC)和接收错误计数器(REC)。这两个计数器决定了节点的总线状态。嗯,这里有个状态机:

总线状态 条件 行为
错误主动 TEC < 128 且 REC < 128 正常发送,出错时发送主动错误帧
错误被动 TEC ≥ 128 或 REC ≥ 128 只能发送被动错误帧,且发送前要等待8个隐性位
总线关闭 TEC > 255 完全脱离总线,不再参与任何通信

我在项目中遇到过最头疼的问题就是“总线关闭”。一个节点因为持续出错,TEC飙升到256以上,直接离线了。整个系统其他节点还在跑,但那个节点就是死活不响应。后来排查发现是它的CAN收发器供电不稳,导致发送电平异常。

警告:总线关闭状态是CAN网络中最严重的故障之一。节点一旦进入总线关闭,必须由主机控制器手动复位才能恢复。所以,设计时一定要考虑错误恢复策略,别指望节点自己就能活过来。

最后说一句,CAN的错误处理机制虽然强大,但它也有代价——频繁的错误重传会占用总线带宽。在FlexRay中,这个问题被很好地解决了,因为它用了时分多址的机制,从根本上避免了冲突。嗯,这个咱们后面再细聊。

好了,CAN的基础回顾就到这里。下一讲咱们正式进入FlexRay的世界,看看它和CAN到底有什么不同。