第4章:CAN总线协议精讲:CAN 2.0A/B帧结构、数据帧/远程帧/错误帧/过载帧、位时序与同步机制

好,咱们进入CAN协议的核心地带。说实话,很多工程师用CANoe或者PCAN抓了一堆报文,但看到原始数据流还是懵的。为什么?因为不懂帧结构。这一章,我把CAN 2.0A和2.0B的底裤给你扒干净。

4.1 CAN 2.0A与2.0B:到底差在哪?

先解决一个基础问题:2.0A和2.0B有什么区别?

说白了,就是ID长度的区别。

  • CAN 2.0A:标准帧,11位ID。早期车厂够用,现在嘛...有点挤。
  • CAN 2.0B:扩展帧,29位ID。多出来的18位给了更多设备空间。

我刚开始做项目时,遇到一个坑:某ECU只支持2.0A,我发了个扩展帧过去,它直接不理我。嗯,兼容性问题,你想想看,这在实车上多危险。

关键点:2.0B控制器可以接收2.0A报文,但反过来不行。硬件上,2.0B是向下兼容的。

4.2 数据帧结构:逐位拆解

数据帧是咱们最常用的。我习惯把它分成三段:起始、仲裁、控制、数据、CRC、ACK、结束。来,咱们逐段看。

4.2.1 帧起始(SOF)

一个显性位(0)。告诉总线:“我要说话了”。就这么简单。

4.2.2 仲裁段

这是CAN协议的精华。标准帧11位ID,扩展帧29位ID。后面跟着RTR位(远程帧标志)和IDE位(扩展标志)。

我在项目中遇到过一个问题:两个节点同时发报文,ID小的获胜。为什么?因为显性位(0)会覆盖隐性位(1)。你想想看,这就像抢答器,谁的数字小谁先讲。

4.2.3 控制段

包含DLC(数据长度码),4位,表示数据段有多少字节。0到8字节。注意:DLC可以写0,但数据段就不存在了。

我的习惯:DLC尽量写实际数据长度,别写8却只发3个字节。有些老旧的CAN控制器会因此出问题。

4.2.4 数据段

0到8字节。这就是你真正要传的信息。比如车速、转速、温度。

4.2.5 CRC段

15位CRC校验码 + 1位CRC分隔符。用来检测传输错误。我曾经见过一个案例,CRC计算错误导致整个网络瘫痪。嗯,硬件问题,但排查起来真要命。

4.2.6 ACK段

2位:ACK槽 + ACK分隔符。发送方发隐性位,接收方如果正确收到,就在ACK槽拉成显性。这就是“我收到了”的信号。

4.2.7 帧结束(EOF)

7个隐性位。表示帧结束了。

4.3 远程帧:只问不拿

远程帧很有意思。它没有数据段,但DLC字段会指明它想要多少字节。说白了,就是A节点对B节点说:“把你那个数据给我发一下”。

我建议:远程帧少用。为什么?因为很多廉价CAN控制器对远程帧支持不好。我踩过这个坑,一个传感器节点收到远程帧后,回复的数据总是错位。最后发现是控制器固件bug。

避坑指南:我曾经用远程帧做诊断,结果ECU死机了。后来查手册才发现,该ECU不支持远程帧。所以,用之前一定看芯片手册。

4.4 错误帧:总线的“警察”

错误帧是CAN总线自我纠错的机制。当节点检测到错误时,它会主动发送错误帧,通知所有节点:“刚才那帧有问题,别用”。

错误帧由两部分组成:

  • 错误标志:6个连续显性位(主动错误)或6个连续隐性位(被动错误)
  • 错误分隔符:8个隐性位

你想想看,6个显性位会破坏任何正在进行的帧。这就是为什么错误帧能立刻终止通信。

我遇到过最头疼的问题:总线上一堆错误帧,查了半天发现是某个节点的晶振频率偏了。位时序不对,导致采样点偏移,老是CRC错误。

4.5 过载帧:慢一点,我跟不上

过载帧和错误帧长得很像,但目的不同。过载帧是说:“我太忙了,你等会儿再发”。

它由6个显性位 + 8个隐性位组成。但注意:过载帧只能在帧间空间(Interframe Space)发送,不能在中途打断。

说实话,过载帧在现代CAN网络中很少见。因为控制器处理速度都很快。但如果你用老旧设备,或者总线负载极高,可能会遇到。

4.6 位时序与同步机制:为什么CAN能跑1Mbps?

这是很多工程师的盲区。CAN没有单独的时钟线,所有节点靠同步来对齐时钟。怎么做到的?

4.6.1 位时间结构

一个位时间被分成4段:

段名 作用 典型长度
同步段(Sync_Seg) 检测边沿 1 Tq
传播段(Prop_Seg) 补偿物理延迟 1-8 Tq
相位缓冲段1(Phase_Seg1) 采样点前调整 1-8 Tq
相位缓冲段2(Phase_Seg2) 采样点后调整 1-8 Tq

采样点通常在Phase_Seg1和Phase_Seg2之间。我习惯把采样点设在87.5%左右,这样抗干扰能力最强。

4.6.2 同步机制

CAN有两种同步方式:

  • 硬同步:发生在帧起始SOF。所有节点强制对齐到SOF的下降沿。
  • 再同步:发生在帧内。如果节点发现边沿偏移,就调整Phase_Seg1或Phase_Seg2的长度。

我曾经调试过一个项目,总线长度50米,波特率500kbps。怎么调都不稳定。后来发现是传播段设置太短,信号在线上来回跑的时间超过了Prop_Seg。你想想看,信号还没到,采样点已经过了,能不丢帧吗?

经验公式:Prop_Seg ≥ 2 × (发送器延迟 + 总线延迟 + 接收器延迟)。总线延迟大约5ns/m,自己算。

4.7 实战建议:用CANoe看帧结构

我建议你打开CANoe,抓一段报文,然后切换到“Data”或“Raw”视图。你会看到每个位的排列。对照本章讲的帧结构,一个一个位去对。相信我,做一遍你就全懂了。

用PCAN的话,PCAN-View也有类似功能。但CANoe的分析更细致,能看到错误帧的详细原因。

嗯,这一章内容不少。但CAN协议的精髓就在这些帧结构和时序里。搞懂了,你就能从“会用工具”升级到“懂协议”的层次。下一章咱们讲CANoe的实战操作,到时候这些知识全用得上。