3、网络层与传输层:ISO 15765-2(CAN TP)协议详解

各位同学,咱们今天聊聊CAN总线上的“快递员”——ISO 15765-2,也就是常说的CAN TP(传输层)协议。说实话,很多刚入行的工程师觉得CAN就是发发报文,简单得很。但真到了做UDS诊断或者刷写Bootloader的时候,才发现数据发不过去,或者发过去车机没反应。嗯,这时候你就要回来好好看看这一章了。

我个人习惯把CAN TP看作是“拆快递”和“装快递”的过程。你想啊,CAN报文一帧最多只能带8个字节的数据,但诊断一条请求动辄几十上百个字节,怎么办?那就得拆包、分包、再组装。ISO 15765-2干的就是这个活儿。

3.1 单帧与多帧传输机制

先说最简单的——单帧。如果你的诊断数据(比如一条“读取VIN码”的请求)长度不超过7个字节(CAN标准帧数据场是8字节,但第一个字节被协议头占了),那直接一帧发过去就完事了。这种就叫单帧(Single Frame, SF)。

但问题来了,刷写ECU固件时,数据包动不动就是4096字节。这时候就得用多帧传输。多帧传输分三步走:

  • 第一帧(First Frame, FF):发送方先发一个“大件快递”通知,告诉接收方“我要发一个总长度为X字节的大包”。
  • 流控制帧(Flow Control, FC):接收方收到FF后,回复一个FC帧,说“我准备好了,你一次可以发几个包,间隔多少时间”。
  • 连续帧(Consecutive Frame, CF):发送方按照FC的要求,一帧一帧地把剩下的数据发完。

我在项目中遇到过一个问题:某次刷写时,ECU总是报“超时错误”。查了半天,发现是发送方连续帧发得太快,接收方来不及处理。后来调整了流控制参数里的“STmin”(最小间隔时间),问题就解决了。你想想看,这就像你往仓库里搬箱子,搬得太快,里面的人码不过来,肯定要喊停。

关键点:单帧的协议头(PCI)中,高4位表示帧类型(0x0表示单帧),低4位表示数据长度。多帧的FF中,高4位是0x1,低4位和第二个字节组合表示总长度(最大4095字节)。

3.2 流控制与时间参数

流控制机制说白了就是“协商”。接收方通过FC帧告诉发送方三个参数:

参数 含义 典型值
FS(Flow Status) 流状态:0=继续发送,1=等待,2=溢出/中止 0x00
BlockSize (BS) 一次连续发送的最大帧数。0表示不限 0x00 或 0x01~0xFF
Separation Time (STmin) 连续帧之间的最小间隔时间,单位有us和ms两种 0x10(1ms)

这里有个坑,我必须要提醒大家。STmin的编码方式有点绕:

  • 0x00~0x7F:直接表示0~127毫秒
  • 0xF1~0xF9:表示100us~900us(步长100us)
  • 0x80~0xF0:保留或特殊用途

我曾经因为STmin设置成了0xF1(100us),结果在某个低速CAN网络上(比如125kbps)频繁丢帧。后来改成0x10(1ms)就稳了。说白了,时间参数不能只看协议手册,还得看实际总线负载和ECU处理能力。

避坑指南:我曾经在调试一个Tier1的ECU时,发现对方要求BS=0(无限发送),但实际每发完128帧就必须等一个FC帧。后来才知道,这是对方硬件FIFO深度只有128。所以,BS=0并不代表真的无限,你得看接收方的实际缓冲区大小。

3.3 网络层寻址方式(N_AI与N_TA)

CAN TP的寻址,说白了就是解决“这条诊断消息是发给谁的”以及“谁发的”。ISO 15765-2定义了两种寻址模式:

  • 物理寻址(Physical Addressing):点对点通信。比如诊断仪发给ECU A,只有ECU A会响应。N_AI(网络地址信息)中包含了目标地址(N_TA)和源地址(N_SA)。
  • 功能寻址(Functional Addressing):一对多通信。比如诊断仪发一条“请所有ECU报告电压”,所有ECU都会响应。这时候N_TA是一个组播地址。

在CAN ID的分配上,通常用29位扩展ID来实现。举个例子:

// 物理寻址示例(29位ID)
// 优先级: 0x18
// 目标地址: 0xDA (ECU A)
// 源地址: 0xF1 (诊断仪)
// 最终CAN ID: 0x18DAF1xx

// 功能寻址示例
// 目标地址: 0xDF (所有ECU)
// 最终CAN ID: 0x18DFF1xx

这里要注意,N_AI其实是一个逻辑概念,它包含了CAN ID中的地址信息。而N_TA就是目标地址,N_SA是源地址。在标准中,N_AI = N_TA + N_SA + 其他控制位。

我记得有一次,客户反馈说“诊断仪发请求,ECU没反应”。我抓了CAN总线一看,发现诊断仪发的CAN ID是0x18DAF100,但ECU监听的是0x18DAF101。说白了,就是N_TA对不上。这种问题在项目集成时特别常见,尤其是当多个团队各自定义地址时。

个人经验:我建议在项目初期就定义好一份“网络地址分配表”,明确每个ECU的物理地址和功能地址。另外,调试时多用CAN工具(比如CANoe或PCAN)的“过滤”功能,只关注目标ID,能省不少时间。

3.4 时间参数与超时处理

CAN TP协议里定义了好几个时间参数,搞不清楚的话,通信随时可能中断。常用的有:

  • N_As:发送方从开始发送到完成发送的最大时间。一般50ms~100ms。
  • N_Ar:接收方从收到FF到发出FC的最大时间。典型值50ms。
  • N_Bs:发送方从发出FF到收到FC的最大等待时间。一般100ms。
  • N_Cr:发送方从发出CF到收到下一个FC的最大等待时间。典型值50ms。

这些时间参数在ISO 15765-2的附录里有推荐值,但实际项目中要根据总线波特率和ECU性能调整。比如在500kbps的CAN网络上,N_As设成50ms绰绰有余;但在125kbps的网络上,可能得放宽到100ms。

嗯,这里要特别提醒:超时处理一定要有重试机制。我曾经见过一个设计,超时后直接报错退出,结果在电磁干扰强的环境下,诊断成功率只有60%。后来加了3次重试,成功率就提到了99%以上。

总结一下:ISO 15765-2是UDS诊断和刷写的基石。单帧处理小数据,多帧处理大数据,流控制保证不丢包,寻址确保消息送达。时间参数是通信的“心跳”,调好了万事大吉,调不好寸步难行。

下一章我们会讲ISO 15765-3(应用层),也就是UDS协议本身。到时候你会看到,今天学的这些传输层知识,是如何被上层协议调用的。好了,今天就到这里,有问题随时交流。