2. CAN FD 帧结构详解:数据帧、遥控帧、错误帧、过载帧,重点分析数据帧的位场

CAN FD 的帧结构,说白了就是通信的“信封”。你往总线上丢一包数据,总得告诉别人:你是谁、发给谁、数据多长、有没有错。CAN 协议把这件事分成了四种帧,我一个个拆开给你看。

我个人习惯把帧结构画成一张时序图来理解。尤其是数据帧,它是我们日常打交道最多的家伙。下面这张图是我自己整理的 CAN FD 数据帧位场结构,你看着它往下读会清楚很多。

CAN FD 标准数据帧位场结构(11位ID) SOF 1 bit 仲裁场 ID(11) + RTR(1) + IDE(1) 控制场 EDL+BRS+ESI+DLC(4) 数据场 0~64字节 CRC场 CRC(17/21)+Delimiter ACK 2 bit EOF 7 bit 说明: 数据场长度可变,CRC 多项式在 FD 模式下扩展到 17 或 21 位 位场与采样点关系 • 仲裁段(SOF ~ CRC Delimiter)以标称位时间采样,采样点靠后(70%~80%)。 • 数据段(BRS 置位后)以高速位时间采样,采样点靠前(50%~60%)。 • 如果采样点配置不当,BRS 位和 CRC 位最容易出错。我踩过这个坑。

2.1 四种帧类型,各有各的活

先快速过一遍四种帧的职责,我把它们的核心差异列在下面这张表里,你扫一眼就能区分。

帧类型 用途 是否有ID 是否有数据场 总线上是否产生错误
数据帧 发送节点把数据丢到总线上 有 有(0~64字节) 正常情况无
遥控帧 请求其他节点发送数据 有 无 正常情况无
错误帧 任何节点检测到总线错误时主动发出 无 无 触发后广播错误标志
过载帧 接收节点还没准备好,要求延迟发送 无 无 与错误帧结构相似,但条件不同

现实中,数据帧占了总线流量的 90% 以上。遥控帧你偶尔会用,比如在诊断时请求某个节点报告状态。错误帧和过载帧是异常情况,但异常情况往往能暴露采样点问题——我记得有一次,一台设备在高温下频繁产生错误帧,最后查出来是采样点偏移了。

2.2 数据帧位场深度拆解

数据帧是整门课的核心。CAN FD 的数据帧在标准 CAN 基础上加了几个特殊位,咱们一个场一个场来过。

2.2.1 SOF(帧起始)

就 1 个显性位。它告诉所有节点:我要开始发东西了,你们都同步一下。你想想看,总线空闲时大家都不发声,SOF 一出现,所有节点的位时钟都以此为准对齐。如果在 SOF 采样点就发生错误,那后续数据基本全废。我建议在做采样点调试时,先盯住 SOF 位看能不能稳定采样。

2.2.2 仲裁场

包含 11 位或 29 位标识符 + RTR 位 + IDE 位。CAN FD 里 IDE 位必须为显性,表示这是标准帧还是扩展帧。仲裁阶段用的是标称位时间,采样点通常设在 70%~80%。为什么后面再说。这里有个细节:CAN FD 的 RTR 位必须为显性,否则就回退到传统 CAN 模式了。

实战小技巧: 如果你看到很多节点同时发遥控帧,注意遥控帧的 RTR 位是隐性,数据帧是显性。仲裁时数据帧优先级更高。这在多主控系统里经常引起争抢,采样点要能抗住信号叠加后的跳变。

2.2.3 控制场

控制场在 CAN FD 里变得复杂了。它包括 EDL、BRS、ESI 和 DLC(4 位数据长度码)。

  • EDL(Extended Data Length):1 位,显性表示 CAN FD 帧,隐性表示传统 CAN 帧。
  • BRS(Bit Rate Switch):1 位,显性表示后面数据段切换到高速率,隐性表示全程用标称速率。
  • ESI(Error State Indicator):1 位,发送节点主动告诉别人自己当前是 error active 还是 error passive。
  • DLC:4 位,但 CAN FD 的编码不一样。比如 DLC=9 表示数据场 12 字节,DLC=15 表示 64 字节。这跟传统 CAN 的映射表不同,千万别搞混。
注意: BRS 位是采样点配置的分水岭。BRS 之前用标称位时间,BRS 之后用数据位时间。如果你把采样点设错了,BRS 位本身就可能被误判。我曾在项目中遇到 BRS 误码率高达 5%,原因是采样点设在 50% 附近,而 BRS 位跳变沿正好卡在采样点上。后来我把数据段采样点调到 55%,错误就没了。

2.2.4 数据场

0 到 64 字节,这是 CAN FD 最大的升级。传统 CAN 最多 8 字节,FD 能塞 64 字节,适合刷写固件、大数据日志。数据场用的位时序由 BRS 决定。高速率下位时间缩短,采样点必须更靠前才能躲开信号反射和振铃。我一般把数据段采样点设到 55%~60%,仲裁段 75%~80%。

2.2.5 CRC 场

CAN FD 的 CRC 有两种:17 位(数据场 ≤16 字节)或 21 位(数据场 >16 字节)。它后面还跟一个隐性 CRC 分隔符。CRC 是整个帧的“指纹”,任何一位出错都会导致 CRC 错误。这时接收节点会发错误帧,发送节点重发。如果你的采样点偏移,CRC 场最容易出错——尤其是在高速数据段,因为位时间短,采样窗口窄。我记得有一次,一辆车的 OBD 诊断总是在长报文时失败,后来抓波形发现 CRC 分隔符正好落在采样点抖动区。把数据段采样点从 60% 改到 57%,问题就解决了。

// 一个快速判断采样点是否合适的经验法则(C伪代码)
if (data_phase_bitrate > 2 Mbps) {
    // 高速:采样点推荐 55%~60%
    sample_point = (t_prop + t_phase1) / t_bit;
} else {
    // 低速:可以接受 70%~80%
    sample_point = (t_sync + t_prop + t_phase1) / t_bit;
}
// 如果 sample_point 不在推荐区间,你需要调整相位缓冲段

2.2.6 ACK 场

2 位:ACK 槽 + ACK 分隔符。ACK 槽由接收节点置隐性,如果收到 ACK 槽被拉显性(即接收节点回应),发送节点就认为帧被确认了。如果 ACK 槽采样失败,发送节点会以为没人接收,不停重发。这会引起总线拥堵。你想想看,如果采样点太靠前,刚好跳变沿还没稳定,就可能把隐性误判成显性。我建议在调试时单独测量 ACK 槽的采样裕量。

2.2.7 EOF(帧结束)

7 个隐性位。连续 7 个隐性表示帧结束。如果中间有一个显性位,其他节点会认为是错误并发送错误帧。EOF 的采样点要求不高,因为它位宽大(7 bit),但如果你在数据段末尾采样点抖动,EOF 的第一个隐性位可能被误判为显性。这不太常见,但我在实验室抓到过一次——数据段最后一位的振铃影响了 EOF 采样。后面我把数据段 RC 滤波调了一下,就稳了。

2.3 遥控帧:没数据也要刷存在感

遥控帧结构与数据帧几乎一样,只是没有数据场,RTR 位为隐性。它的作用相当于“给我发数据”。仲裁时数据帧优先级高于遥控帧,因为数据帧 RTR 是显性。采样点配置参考数据帧的仲裁段规则。如果你用遥控帧做周期性请求,要注意请求间隔必须大于当前总线负载,否则可能触发过载帧。

2.4 错误帧与过载帧:异常时的“救命稻草”

错误帧由 6 个显性位(错误标志) + 8 个隐性位(错误分隔符)组成。任何节点检测到总线错误(位错误、填充错误、CRC 错误、格式错误、ACK 错误)都会立即打断当前帧,发送错误标志。过载帧结构与错误帧相似,但触发条件不同——它是由接收节点在帧间隔期间发送的,表示“我还没消化完,等一会儿”。

你知道吗?采样点错误最常见的表现就是总线频繁出现错误帧。我曾经调一个机器人手眼标定系统,只要把 CAN FD 速率提到 5 Mbps,总线一忙就冒错误帧。后来发现是数据段采样点设在 62%,刚好落在信号过冲区。降到 56%,错误帧就消失了。所以,当你的系统出现莫名错误帧时,第一个怀疑对象就是采样点。

核心观点: 错误帧和过载帧不仅是异常处理机制,更是采样点配置的一面“照妖镜”。如果错误帧集中在数据段,基本可以断定是数据段采样点偏后;如果错误帧集中在仲裁段,则是仲裁段采样点偏前。

2.5 小结:数据帧位场与采样点的强关联

为了让你看得更清楚,我画了一个表格来总结每个位场对采样点的敏感程度和推荐策略。

位场/段 对采样点敏感度 位时间类型 我的个人推荐
SOF~BRS(仲裁段) 中 标称 采样点 75%~80%
BRS 位本身 高 标称→数据过渡 采样点 55%~60%(配合过渡滤波器)
数据场(BRS 置位后) 高 数据段 采样点 55%~60%
CRC 场(数据段) 极高 数据段 采样点 55%~60%,且要额外验证 CRC 分隔符
ACK 场 中 标称(回到仲裁段后) 同仲裁段
EOF 低 标称 同仲裁段,但注意数据段末尾振铃