2. CAN FD 帧结构详解:数据帧、遥控帧、错误帧、过载帧,重点分析数据帧的位场
CAN FD 的帧结构,说白了就是通信的“信封”。你往总线上丢一包数据,总得告诉别人:你是谁、发给谁、数据多长、有没有错。CAN 协议把这件事分成了四种帧,我一个个拆开给你看。
我个人习惯把帧结构画成一张时序图来理解。尤其是数据帧,它是我们日常打交道最多的家伙。下面这张图是我自己整理的 CAN FD 数据帧位场结构,你看着它往下读会清楚很多。
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 模式了。
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 的映射表不同,千万别搞混。
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 | 低 | 标称 | 同仲裁段,但注意数据段末尾振铃 |