从Wireshark抓包实战看UDS网络层:SF、FF、FC、CF四类帧到底怎么玩?
2026/5/16 21:24:12 网站建设 项目流程

从Wireshark抓包实战看UDS网络层:SF、FF、FC、CF四类帧到底怎么玩?

在车载诊断领域,UDS协议的网络层就像一位隐形的交通指挥官,默默协调着数据在CAN总线上的有序流动。当你用Wireshark捕获到一堆看似杂乱的CAN报文时,那些以0x7DF开头的ID背后,其实隐藏着一套精妙的通信规则。本文将带你像侦探破案一样,通过真实抓包案例拆解单帧(SF)、首帧(FF)、流控帧(FC)和连续帧(CF)的协作机制。

1. 初识UDS网络层的四类关键帧

打开Wireshark捕获的CAN报文,首先要注意数据域的第一个字节——这个被称为N_PCI(网络层协议控制信息)的字段,就是识别帧类型的"身份证"。高4位数值直接决定了帧的类别:

  • 0x0:单帧(Single Frame)
  • 0x1:首帧(First Frame)
  • 0x2:连续帧(Consecutive Frame)
  • 0x3:流控帧(Flow Control)

实际抓包中常见混淆点:ECU回复的0x30帧容易被误认为数据帧,其实是流控指令

通过过滤器can.id == 0x7DF && frame.len == 8可以快速定位诊断报文。下图展示了一个典型的多帧交互过程:

帧类型示例数据 (Hex)说明
FF10 23 00 01 02 03 04总长度0x2300字节
FC30 20 0A 00 00 00 00允许连续发送32帧,间隔10ms
CF21 05 06 07 08 09 0A序列号1的数据块

2. 单帧(SF)的快速识别技巧

当数据量小于等于7字节时(标准寻址),网络层会直接采用单帧传输。识别单帧有两个关键特征:

  1. 数据域首字节高半字节=0x0
  2. 低半字节表示有效数据长度(DL)

例如捕获到报文02 10 03 00 00 00 00 00

  • 首字节0x02 → SF且有效长度2字节
  • 实际数据为0x10 0x03(诊断会话控制请求)

常见陷阱

  • 填充字节可能包含历史数据(如00 FF AA等)
  • 某些ECU会使用0x7E作为填充值(需确认厂商规范)

3. 多帧传输的启动信号:首帧(FF)解析

当Wireshark捕获到首字节高4位为1的报文时,意味着一个多帧传输序列的开始。FF帧的特殊性在于:

  • 使用首字节低4位+第二字节共12位表示总数据长度(FF_DL)
  • 最大支持4095字节数据传输
  • 必须等待接收方回复FC帧才能继续

实战案例:报文10 82 00 01 02 03 04 05解析:

# Python解析FF帧示例 raw_data = [0x10, 0x82, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05] pci_type = (raw_data[0] & 0xF0) >> 4 # 得到0x1 → FF total_length = ((raw_data[0] & 0x0F) << 8) | raw_data[1] # 0x0820 → 2080字节

重要提示:某些ECU在FF后会立即发送FC,而另一些需要人工触发

4. 流控帧(FC)的参数调优实战

FC帧是控制多帧传输节奏的核心,包含三个关键参数:

  1. FS(流状态)

    • 0x0:继续发送(CTS)
    • 0x1:等待(WT)
    • 0x2:溢出(OVFLW)
  2. BS(块大小)

    • 0x00表示无限制
    • 其他数值表示允许连续发送的CF帧数
  3. STmin(最小间隔时间)

    • 0x00-0x7F:毫秒值
    • 0xF1-0xF9:100-900微秒

在实车测试中,这些参数的优化直接影响诊断效率:

  • BS=0x20, STmin=0x0A→ 每32帧一组,间隔10ms
  • BS=0x00, STmin=0x05→ 连续发送,间隔5ms
// 典型FC帧生成代码示例 uint8_t GenerateFC(uint8_t fs, uint8_t bs, uint8_t stmin) { uint8_t fc_frame[8] = {0}; fc_frame[0] = 0x30 | (fs & 0x0F); // 类型+FS fc_frame[1] = bs; // 块大小 fc_frame[2] = stmin; // 时间间隔 return fc_frame; }

5. 连续帧(CF)的顺序校验机制

CF帧最易出错的就是序列号(SN)管理。正确的SN应该:

  • 从1开始递增(FF隐含为0)
  • 每帧递增1,到0xF后归零
  • 不受FC帧影响而重置

在重组数据时,建议采用如下校验流程:

  1. 检查首个CF的SN是否为1
  2. 验证后续SN是否连续
  3. 处理FC帧后继续校验SN

例如以下CF序列(已提取数据部分):

帧序号数据有效SN
CF121 01 02 03 04 051
CF222 06 07 08 09 0A2
CF323 0B 0C 0D 0E 0F3

当遇到SN跳变(如从3直接到5),应当:

  • 记录N_WRONG_SN错误
  • 请求重新传输
  • 在Wireshark中用红色标记异常帧

6. 实战:从抓包文件还原完整UDS服务

现在我们用真实案例演示如何解析一个完整的ReadDataByIdentifier服务:

  1. 请求端发送

    22 F1 90 00 00 00 00 00 // SF帧:读取DID F190
  2. 响应端回复流程

    • FF帧:10 1A 62 F1 90 00 01 02→ 总长度0x1A字节
    • FC帧:30 00 14 00 00 00 00 00→ 立即发送,间隔20ms
    • CF序列:
      21 03 04 05 06 07 08 09 22 0A 0B 0C 0D 0E 0F 10 23 11 12 13 14 15 16 17
  3. 数据重组结果

    # 重组后的完整响应数据 data = [ 0x62, 0xF1, 0x90, 0x00, 0x01, 0x02, # FF帧数据 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 ]

在实车测试中,经常会遇到ECU回复WT状态(FS=1)。这时合理的处理方式是:

  • 等待至少100ms再重试
  • 检查ECU是否处于高负载状态
  • 考虑调整STmin参数降低发送速率

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询