CANFD协议与UDS服务

CANFD与CAN的差异

二者差异主要集中在MAC层上,依旧是分为非扩展帧和扩展帧,

非扩展:

  • RTR→RRS
  • r0→FDF
  • 新增res、BRS、ESI
  • CRC段之前多出Stuff-bitcounter
  • CRC变为17/21位,且包含固定填充位
段名 帧起始 仲裁段 控制段 数据段 CRC段 ACK段 帧结束
含义 SOF ID RRS IDE FDF res BRS ESI DLC Data SBC CRC DEL ACK DEL EOF
长度 1 11 1 1 1 1 1 1 4 0~64字节 4(3+1) 17/21 1 1 1 7

扩展:

仲裁段 控制段
ID SSR IDE EID RRS IDE FDF res BRS ESI DLC
11 1 1 18 1 1 1 1 1 1 4

仲裁段

  • RRS:RemoteRequestSubstitution,替代ClassicalCAN的RTR,CANFD中固定为显性0,不再表示远程帧
  • SSR:在 Classical CAN 中“保证标准帧优先级高于扩展帧”的仲裁功能,但在纯CANFD环境里并没有被复用,即在CANFD仅作为“为了帧结构兼容而保留的占位位”

控制段

  • FDF:FDFormatbit,=1表示本帧为CANFD帧格式(Classical CAN中对应r0,保留并固定为显性0)
  • res:新保留位(类似Classical CAN中的r0),为将来协议扩展预留
  • BRS:BitRateSwitch,=1时表示从本位开始进入数据段后,比特率切换到高速;=0时保持仲裁段速率
  • ESI:ErrorStateIndicator,显性=ErrorActive,隐性=ErrorPassive,用于指示发送节点的错误状态

数据段

  • DLC:仍为4位,但含义扩展:0~8同Classical CAN;9~15分别对应12/16/20/24/32/48/64字节
  • SBC:StuffBitCounter,在CRC段之前新增,由3位格雷码+1位奇偶校验构成(这里统一写成4位)
  • CRC:17位(数据≤16字节)或21位(数据>16字节),不再是ClassicalCAN的15位

UDS统一诊断服务

UDS是一种应用层协议,通常跑可以在CAN、LIN、Flexray、Interact等协议上

UDS通讯基础

UDS使用Client-Server模型,诊断仪发送“Request”,ECU返回“Response” ,如下:

Client (诊断仪/Tester) 方向 Server (ECU)
场景 1:仅 SID (以 0x14 清除故障信息为例)
服务请求:14 FF FF FF (请求清除所有 DIDs) ->
<- 肯定响应(格式为 SID + 0x40):
54 (计算:14 + 40 = 54)
<- 否定响应(格式固定为 7F + SID + NRC):
7F 14 13 (NRC 13:报文长度错误或格式不正确)
场景 2:SID + SF (以 0x10 会话控制为例)
服务请求:10 03 (请求进入扩展会话) ->
<- 肯定响应:50 03 [P2 Time parameters] (50 是 10+40,03 是回显子功能)
<- 否定响应:7F 10 22 (NRC 22:当前条件不满足,如车速不为0)
场景 3:SID + DID (以 0x22 读取数据为例)
服务请求:22 F1 90 (请求读取 VIN 码) ->
<- 肯定响应:62 F1 90 [VIN Data...] (62 是 22+40,F1 90 是数据标识符)
<- 否定响应:7F 22 31 (NRC 31:请求的标识符不存在/超出范围)
场景 4:SID + SF + DID (以 0x31 例程控制为例)
服务请求:31 01 02 01 (启动 0201 号灯光测试程序) ->
<- 肯定响应:71 01 02 01 [Status] (71 是 31+40,01 是启动,02 01 是程序ID)
<- 否定响应:7F 31 33 (NRC 33:安全访问拒绝,可能需要先执行 0x27 解锁)

SID:服务ID,决定当前诊断通信的性质,类似于HTTP的Method,常见有

  • 0x10:会话控制,切换 ECU 的工作状态(如进入调试、编程模式),支持NRC0x120x130x22,常见SubFunction

    • 默认会话0x01:最小权限的会话,提供基本诊断能力,但不具备高风险功能,当前状态下下不需要任何诊断应⽤程序的在线服务(0x3E 服务)保持此模式激活。如果在其他状态下请求 10 01 回到默认会话并收到了肯定响应,之前激活的控制服务(如 0x28 通信控制)会复位,已解锁的安全访问(0x27)也会重新锁定
    • 扩展会话0x03:扩展会话状态⽀持在 ECU 存储器中进⾏操作,比起默认会话,允许更多高权限操作,⽐如0x22/0x2E 读/写服务、0x28 通信控制、0x31 例程等操作。扩展会话状态通常仅可从默认会话状态进入
    • 编程会话0x02:编程会话⽀持 ECU 内存编程操作,⼀般在此会话下执⾏ bootloader(刷写)操作,会有更多高权限功能,比如0x34请求下载、0x36 传输数据、0x37请求传输退出、0x31例程控制等,但安全要求非常严格,需要通过0x27服务做验证,同时通常仅可通过扩展会话状态进入,并且不可退回到扩展会话状态
    • 安全系统诊断会话0x04:比较少见
    • 自定义会话0x05~0x3F、0x41~0x7F
  • 0x11:复位服务,请求ECU 重启,根据SF采用不同的重启方式,支持NRC:0x120x130x220x33,常见SubFunction

    • 硬复位0x01:模拟掉电重启
    • 钥匙复位0x02:模拟点火从关到开的过程
    • 软复位0x03:不初始化数据,仅重置PC寄存器,不完全重启
    • 启用快速下电休眠0x04:针对具备待机模式的 ECU
    • 抑制快速下电休眠0x05
  • 0x14:清除DTC(诊断故障码)及其相关数据

  • 0x19:读取DTC

  • 0x22:读数据,通过DID获取ECU内部存储的信息,支持NRC:0x130x140x220x310x33,常见DID:F1 90 (VIN码)、 F1 8C (序列号) 等 。

  • 0x27:安全访问,通过 Seed & Key 算法解锁高权限服务(如写数据、刷写、下载),支持 NRC:0x120x130x220x24(请求顺序错误)、0x350x36(超过尝试次数) 、0x37(错误延迟未到),常见SubFunction

    • 奇数 (0x01, 0x03…):请求种子 (Request Seed) 。
    • 偶数 (0x02, 0x04…):发送密钥 (Send Key) 。
    • Seed 为 0 通常表示已解锁 。
  • 0x28:通信控制,开启或关闭 ECU 的应用层报文(非诊断报文)发送或接收,常用于刷写前清理总线带宽

    • 常见SubFunction

      • 恢复正常通信:0x00
      • 只读不写:0x01
      • 只写不读:0x02
      • 完全静默:0x03(最常用,禁止收发)
    • 常见参数 (CommunicationType):

      • 0x01:应用报文;0x02:网管报文;0x03:两者都控制
  • 0x2E:写数据,通过DID修改ECU的配置或参数,支持NRC:0x130x220x310x330x72(编程错误),请求格式:0x2E+DID+数据

  • 0x31:例程(Routine)控制,如擦除内存、自检、校验,请求格式:0x31+RoutineID+参数

    • 常见SubFunction
      • 启动例程:0x01
      • 停止例程:0x02
      • 查询例程执行结果:0x03
  • 0x34:请求下载,启动数据传输,用于协商传输参数

    • dataFormatIdentifier:高四位为压缩方式,低四位为加密方式 (通常 0x00) 。
    • addressAndLengthFormatIdentifier:定义后续地址和长度占几个字节 (如 0x44 表示各占 4 字节)
    • memoryAddress:写入的起始地址
    • memorySize:数据总大小
  • 0x35:请求上传,与0x34反向

  • 0x36:实际传输数据块,在0x34或0x35之后使用

    • BlockSequenceCounter:块序列号 (01-FF 循环),用于防丢包
    • transferRequestParameterRecord:实际数据内容
  • 0x37:请求退出传输,数据传输完成后,通知ECU结束传输流程,通常会触发 ECU 进行数据完整性校验

    • 可包含校验和 (Checksum/CRC) 供ECU验证,若发送方没有包含,ECU也会返回CRC32供客户端进行验证
  • 0x3E:会话保持,告诉 ECU 诊断仪还在线,用于保持非默认会话(如扩展/编程会话)不超时退回,通常 2-4 秒发一次,支持NRC0x120x13 ,常见SubFunction

    • 需要响应0x00:ECU 收到后回复 7E 00,用于确认连接正常
    • 抑制响应0x80:ECU 收到后保持会话但不回复,用于减少总线负载
  • 0x85:暂停/恢复 DTC 状态位的更新(冻结故障记录)

DID:数据标识符,是 0x220x2E 服务的操作对象,类似于变量名,常见有

  • 0xF190:车架号。车辆的唯一身份证
  • 0xF18C:ECU 序列号。硬件的唯一标识
  • 0xF19E:版本号。当前 ECU 运行的软件版本
  • 0x0100 - 0xEFFF:厂家自定义 DID,比如读取水温、发动机转速、电池电压等实时动态参数
  • 0xFD01:标定数据。用于存储影响车辆性能的配置参数

RoutineID:例程标识符,专属于 0x31 服务,类似于远程代码执行,常见有

  • 0xFF00:擦除内存。刷写固件前的必备步骤
  • 0xFF01:检查结果。比如检查刚刚刷入的固件校验和(Checksum)是否正确
  • 0x0201:自检例程。让全车灯光闪烁或仪表盘指针扫表
  • 0xDF01:依赖性检查。检查当前的硬件版本是否兼容即将刷入的软件

NRC:否定代码,类似于HTTP的400响应码,常见有

  • 0x11:服务不支持
  • 0x12:服务支持,但子功能不对
  • 0x13:服务支持,但长度不对
  • 0x22:服务支持,子功能存在,但条件不满足,比如在车开的时候刷写固件,ECU会回这个
  • 0x31:请求超出范围,标识符超出范围、服务器不支持或当前会话不支持
  • 0x33:安全访问拒绝,说明服务器没解锁不让用
  • 0x35:密钥错误,暴力破解失败时会出现
  • 0x78:ECU 忙,这会延长超时时间

使用CAN传输UDS报文(DoCAN)

CAN以及CANFD传输数据时单帧能传输的数据相当有限,为了传输更多的数据,与TCP/IP的设计类似(MSS/MTU),设计了分包的传输机制CAN TP

UDS在通讯时使用CAN ID进行寻址,共有两种寻址方式:

  • 物理寻址:1对1,物理地址(标识符)与CAN仲裁ID一致,诊断仪通过0x7xx进行请求,ECU用0x6xx作为响应ID,两个ID的低8位在工程设计上常定义成一样的值,也有逆序和固定增值,没有强制规定
  • 功能/逻辑寻址:广播1对多,常见诊断仪通过0x7DF进行广播,各ECU用0x7E8–0x7EF范围内的CAN ID作为响应ID

同一个ECU在面对不同类型寻址方式时返回地址不一样,这是为了区别物理寻址和功能寻址

UDS在传输数据时总共有四种报文类型,这里展示在数据段的结构

报文类型 位7~4 位3~0 字节1 字节2 字节3~7 描述
单帧(SF) 0000 DLC<=7 DATA 数据长度<7字节
第一帧(FF) 0001 7<DLC<4095 DLC后半段 DATA 第一包,告诉 ECU 后面还有多少数据
控制帧(FC) 0011 FS BS STmin - ECU 收到首帧后,回复 FC
连续帧(CF) 0010 SN(帧序号,0~F循环计数) DATA 后续的数据包

FS(流状态):

  • FS=0,CTS:继续发送
  • FS=1,WT:暂停发送,等待下一个FS
  • FS=2,OVFLW:接收方溢出,要求停止发送

BS(块大小):

  • BS=0:块大小不受限制,可以一直发送
  • BS=01~FF:在没有接受流控帧期间能发送的最大数目的连续帧

STmin(发送间隔):单位为毫秒

DLC:

  • 这里的DLC与CAN上控制段的DLC并不指的是同一个值,此DLC仅描述报文内的数据长度

一个仍在爬山的人