CAN是控制器局域网络(Controller Area Network, CAN)的简称,是由以研发和生产汽车电子产品著称的德国BOSCH公司开发的,并最终成为国际标准(ISO 11898),是国际上应用最广泛的现场总线之一。 在北美和西欧,CAN总线协议已经成为汽车计算机控制系统和嵌入式工业控制局域网的标准总线,并且拥有以CAN为底层协议专为大型货车和重工机械车辆设计的J1939协议。
现代汽车可能有多达70个电子控制单元(ECU)用于各种子系统。传统上,最大的处理器是发动机控制单元。其他用于自动驾驶、高级驾驶辅助系统(ADAS)、变速器、安全气囊、防抱死制动/ABS、巡航控制、电动助力转向、音响系统、电动车窗、车门、后视镜调节、混合动力/电动汽车的电池和充电系统等。其中一些形成独立的子系统,但通信等是必不可少的。子系统可能需要控制执行器或接收来自传感器的反馈。CAN标准就是为了满足这一需求而设计的。一个关键的优势是,不同车辆系统之间的互连可以允许仅使用软件实现广泛的安全,经济和便利功能 - 如果使用传统汽车电气“硬连线”这些功能,这将增加成本和复杂性。

CAN数据包

正常数据包

在应用层,CAN 数据包包含标识符和数据。标识符的长度可能是 11 位或 29 位,但对于我们的汽车来说,只能看到 11 位的标识符。在标识符之后,有 0 到 8 个字节的数据。协议栈的底层有长度字段和校验和等组件,但我们只关心应用层。数据可能在 8 个字节的应用级数据中包含校验和或其他机制,但这不是 CAN 规范的一部分。
在福特,几乎所有的 CAN 数据包都包含 8 个字节的数据。在 Toyota 中,字节数变化很大,通常最后一个字节包含数据的校验和。正如我们稍后将看到的,有一种标准方法可以使用 CAN 数据包一次传输超过 8 个字节的数据。标识符用作优先级字段,值越小优先级越高。它还用作帮助 ECU 确定是否应该处理它的标识符。这是必要的,因为 CAN 流量本质上是广播的。所有 ECU 都接收所有 CAN 数据包,并且必须决定是否处理该数据包。这是在 CAN 数据包标识符(CAN ID)的帮助下完成的。
在 CAN 汽车网络中,有两种主要类型的 CAN 数据包,正常数据包和诊断数据包。正常数据包从 ECU 发送,并且可以在任何给定时间在网络上看到。它们可能是与其他 ECU 使用的信息一起发送的广播消息,也可能被解释为其他 ECU 采取行动的命令。在任何给定时间,通常每隔几毫秒就会发送许多这样的数据包。来自福特 Escape MS 总线的标识符(CAN ID)为 03B1 的此类数据包的示例如下所示:
IDH: 03, IDL: B1, Len: 08, Data: 80 00 00 00 00 00 00 00
Toyota 发送的标识符为 00B6 的数据包示例,广播当前速度,最后一个数据字节带有校验和,如下所示:
IDH: 00, IDL: B6, Len: 04, Data: 33 A8 00 95
11 位帧的 CAN ID 可以分为高位和低位(IDH 和 IDL)或组合成一个 ID。例如,以上示例的 IDH 为 03,IDL 为 B1。因此它的 CAN ID 为 03B1。

诊断数据包

在汽车系统中看到的另一种 CAN 数据包是诊断数据包。这些数据包由工程师用来与 ECU 通信的诊断工具发送。这些数据包在车辆正常运行期间通常不会被看到。例如,以下是诊断工具和防抱死制动 (ABS) ECU 之间故障代码的交换:
IDH: 07, IDL: 60, Len: 08, Data: 03 14 FF 00 00 00 00 00
IDH: 07, IDL: 68, Len: 08, Data: 03 7F 14 78 00 00 00 00
IDH: 07, IDL: 68, Len: 08, Data: 03 54 FF 00 00 00 00 00
在诊断数据包的情况下,每个 ECU 都有一个特定的 ID 分配给它。如上例所示,0760 是许多福特汽车中的 ABS ECU的标识符。

CAN协议

ISO-TP

ISO-TP 或 ISO 15765-2 是通过 CAN 总线发送数据包的国际标准。它定义了一种通过总线发送任意长度数据的方法。 ISO-TP 在每个 CAN 数据包的开头添加一个或多个元数据字节。这些附加字节称为协议控制信息 (PCI)。第一个字节的第一个半字节表示 PCI 类型。有 4 个可能的值。

  • 0 - 单帧。包含整个有效负载。下一个半字节(4 bits)是数据包中有多少数据。
  • 1 - 第一帧。多包有效载荷的第一帧。接下来的 3 个半字节表示有效负载的大小。
  • 2 - 连续帧。这包含多包有效负载的其余部分。下一个半字节作为索引来整理接收到的数据包的顺序。如果传输的内容长于 112 字节,则索引可以换行。
  • 3 - 流量控制帧。用作对第一帧数据包的确认。指定传输附加数据包的参数,例如它们的传输速率。

举个例子,最后一节的第一个数据包,包含具有 3 个字节数据的单个帧。数据为“14 FF 00”。
IDH: 07, IDL: 60, Len: 08, Data: 03 14 FF 00 00 00 00 00
另一个例子如下:
IDH: 07, IDL: E0, Len: 08, Data: 10 82 36 01 31 46 4D 43
IDH: 07, IDL: E8, Len: 08, Data: 30 00 00 00 00 00 00 00
IDH: 07, IDL: E0, Len: 08, Data: 21 55 30 45 37 38 41 4B
IDH: 07, IDL: E0, Len: 08, Data: 22 42 33 30 34 36 39 FF
IDH: 07, IDL: E0, Len: 08, Data: 23 FF FF FF 2A FF FF FF
第一个数据包,发送到 ECU 的 ID 为 07E0 是 0x082 字节数据的第一帧。然后下一帧是确认。接下来的三帧是索引为 1、2、3 的连续帧(注意,索引从 1 开始,而不是 0)。有效载荷的实际数据是“36 01 31 46 4D 43 55 30…”

ISO 14229, 14230

ISO-TP 描述了如何发送数据。两个密切相关的规范 ISO 14229 和 14230 描述了发送的实际数据的格式。粗略地说,有许多可用的服务,每个数据传输声明发送方正在与之通话的服务,尽管制造商可以决定给定的ECU将实现哪些服务。仅以诊断会话控制为例。

服务:诊断会话控制(0x10)

以下code会建立与 ECU 的诊断会话,通常在发送任何其他命令之前是必需的。
IDH: 07, IDL: E0, Len: 08, Data: 02 10 03 00 00 00 00 00
IDH: 07, IDL: E8, Len: 08, Data: 06 50 03 00 32 01 F4 00
提取ISO-TP头后,发送的数据是“10 03”。 10 表示它是一个诊断会话控制,ISO 声明 03 表示一个扩展诊断会话。 ECU 回复六个字节的数据。第一个字节 50 表示成功,因为它比发送的代码多 40。下一个字节确认发送的代码。其余数据与已建立会话的详细信息有关。
以下是调用失败的示例:
IDH: 07, IDL: 26, Len: 08, Data: 02 10 02 00 00 00 00 00
IDH: 07, IDL: 2E, Len: 08, Data: 03 7F 10 12 00 00 00 00
此处响应为 7F,表示出现错误。 ID 与错误代码一起再次重复,0x12 表示 subFunctionNotSupported。
这是成功建立会话的同一个 ECU。
IDH: 07, IDL: 26, Len: 08, Data: 02 10 85 00 00 00 00 00
IDH: 07, IDL: 2E, Len: 08, Data: 02 50 85 00 00 00 00 00

参考

【1】https://en.wikipedia.org/wiki/CAN_bus
【2】Miller C, Valasek C. Adventures in automotive networks and control units[J]. Def Con, 2013, 21(260-264): 15-31.