第1章:CAN FD帧结构深度解析

各位工程师朋友,今天我们来聊聊CAN FD的帧结构。说实话,我在刚接触CAN FD时,也被那一堆缩写搞得头晕——SOF、EDL、BRS、ESI……但搞懂这些,你才能真正理解CAN FD为什么比传统CAN快那么多。

我个人习惯把CAN FD帧结构拆成几个关键部分来理解。咱们一个一个过。

1.1 帧起始(SOF)

SOF,全称Start of Frame。说白了就是告诉总线上所有节点:“我要开始发消息了!”

它只有一个显性位(Dominant bit)。嗯,这里要注意:SOF是同步的基础。所有节点的时钟都靠它对齐。我在项目中遇到过一个问题——某个节点在SOF阶段出现了毛刺,导致整个网络同步失败。排查了整整两天,最后发现是CAN收发器的上电时序有问题。

关键点:SOF必须是显性位。如果总线上同时有多个节点发送,SOF的显性电平会覆盖隐性电平,这就是仲裁的基础。

1.2 仲裁场(11位/29位ID)

仲裁场,这是CAN协议的精髓所在。你想想看,多个节点同时发消息怎么办?谁先发?答案就是:ID越小,优先级越高。

CAN FD支持两种ID长度:

  • 标准帧:11位ID,范围0x000~0x7FF
  • 扩展帧:29位ID,范围0x00000000~0x1FFFFFFF

我刚开始做CAN开发时,总觉得扩展帧29位太浪费。后来在车载网络中,节点数量一多,11位ID根本不够用。扩展帧的优势就体现出来了。

避坑指南:我曾经犯过一个低级错误——把标准帧和扩展帧混在同一网络中,结果仲裁逻辑全乱了。记住:同一网络最好统一帧格式,或者严格区分ID范围。

1.3 控制场(EDL、BRS、ESI详解)

控制场是CAN FD和传统CAN最大的区别所在。它包含三个关键位:

位名称 全称 作用
EDL Extended Data Length 标识是否为CAN FD帧(1=FD帧,0=传统CAN)
BRS Bit Rate Switch 是否切换高速率(1=切换,0=不切换)
ESI Error State Indicator 发送节点是否处于错误被动状态(1=被动,0=主动)

我个人觉得,BRS位是最有意思的。它让CAN FD在数据段可以跑更高的速率(比如8Mbps),而仲裁段还是用原来的速率(比如500kbps)。为什么这样设计?因为仲裁需要所有节点都能听到,速率不能太高;但数据传输可以快一点,反正只有发送和接收两个节点在听。

注意:EDL位必须为1,才能使用CAN FD的特性。如果EDL=0,那就是传统CAN帧,后面的BRS和ESI位都会被忽略。我见过有人把EDL位设错了,结果CAN FD设备死活不工作。

1.4 数据场(0~64字节)

传统CAN的数据场最多8字节,CAN FD直接干到64字节。为什么?因为现代汽车电子系统越来越复杂,8字节根本不够用。比如一个高精度地图更新包,8字节得发多少次?

数据场的长度由控制场中的DLC(Data Length Code)决定。CAN FD的DLC编码和传统CAN不一样:

DLC值 传统CAN数据长度 CAN FD数据长度
0~8 0~8字节 0~8字节
9 8字节 12字节
10 8字节 16字节
11 8字节 20字节
12 8字节 24字节
13 8字节 32字节
14 8字节 48字节
15 8字节 64字节

我在项目中遇到过一个问题:某个ECU发送了DLC=15的数据,但接收端只支持到48字节。结果数据被截断,系统报错。所以,设计时一定要确认所有节点都支持64字节。

1.5 CRC场(17位/21位CRC)

CRC(循环冗余校验)是保证数据完整性的关键。CAN FD的CRC有两种长度:

  • 17位CRC:用于数据长度≤16字节的帧
  • 21位CRC:用于数据长度>16字节的帧

为什么需要两种?因为数据越长,CRC的检错能力要求越高。21位CRC的生成多项式更复杂,能检测更多类型的错误。

技术细节:CRC的计算范围包括SOF、仲裁场、控制场和数据场。但要注意,CRC本身和后面的ACK场、EOF不参与计算。我刚开始用Wireshark抓包时,总搞不清楚CRC校验失败的原因,后来才发现是计算范围搞错了。

1.6 ACK场

ACK场只有两个位:ACK Slot和ACK Delimiter。ACK Slot由接收节点发送显性位来确认收到数据。如果没有任何节点确认,发送节点会认为传输失败并重发。

嗯,这里有个坑:如果总线上只有一个节点在发送,没有其他节点接收,那ACK Slot会保持隐性位。发送节点就会一直重发,直到超时。我在测试单节点系统时就遇到过这个问题,后来加了一个虚拟接收节点才解决。

1.7 帧结束(EOF)

EOF由7个隐性位组成。它的作用是告诉所有节点:“这帧结束了,准备接收下一帧吧。”

EOF必须严格保持7个隐性位。如果出现显性位,那就是填充错误(Stuff Error),节点会发送错误帧。我见过一个案例——某个节点的时钟漂移导致EOF被截断,结果整个网络频繁报错。最后换了高精度的晶振才解决。

知识体系总览

为了让你更直观地理解CAN FD帧结构,我画了一张图:

CAN FD帧结构总览 SOF 仲裁场 控制场 数据场 CRC场 ACK场 EOF 1位 11/29位 6位 0~64字节 17/21位 2位 7位 控制场细节 EDL: 1位 BRS: 1位 ESI: 1位 DLC: 4位 数据场细节 长度: 0~64字节 由DLC决定 传统CAN: 8字节 CAN FD: 最大64字节 CRC场细节 17位: ≤16字节 21位: >16字节 生成多项式不同 注:CAN FD帧在控制场之后可切换高速率(BRS=1时) CRC计算范围:SOF + 仲裁场 + 控制场 + 数据场

这张图把CAN FD帧的各个部分都标出来了。你可以看到,控制场、数据场和CRC场是CAN FD和传统CAN差异最大的地方。我个人建议,在Wireshark中抓包时,重点关注EDL、BRS和ESI这三个位,它们能告诉你这帧是不是CAN FD、速率有没有切换、发送节点状态如何。

实用技巧:在Wireshark中,你可以用过滤器 canfd 来只显示CAN FD帧。或者用 canfd.brs == 1 来查看那些使用了高速率传输的帧。我调试时经常用这个过滤器,能快速定位问题。

好了,CAN FD帧结构就讲到这里。记住:SOF是起点,仲裁场决定优先级,控制场藏着CAN FD的秘密,数据场可以很大,CRC保证不出错,ACK确认收到,EOF收尾。搞懂这些,你就能看懂Wireshark里的CAN FD报文了。


公众号:蓝海资料掘金营,微信deep3321