第2章:车载网络协议基础:CAN总线协议详解、CAN诊断协议(UDS on CAN)、DoIP协议入门
各位同学,咱们今天聊聊车载网络协议。说实话,搞TBOX远程诊断,网络协议就是你的“普通话”。车上的ECU(电子控制单元)们怎么交流?诊断仪怎么跟ECU对话?这些都得靠协议来约定。
我个人习惯把车载网络协议分成三层来看:底层通信(CAN总线)、诊断应用(UDS on CAN)、高速远程(DoIP)。咱们一层层剥开。
2.1 CAN总线协议详解
CAN总线,全称Controller Area Network。1980年代由Bosch发明,初衷是为了减少汽车线束。你想想看,一辆车几十个ECU,如果每个都单独拉线,那线束比发动机还重。CAN总线用两根线(CAN_H和CAN_L)就把所有节点串起来了。
2.1.1 物理层:差分信号
CAN总线用差分信号传输。说白了,就是两根线上的电压差来表示0和1。
- 显性电平(Dominant):CAN_H比CAN_L高2V左右,代表逻辑0。总线空闲时是隐性电平。
- 隐性电平(Recessive):CAN_H和CAN_L电压差接近0,代表逻辑1。
我在项目中遇到过一个问题:某次台架测试,CAN通信时不时丢帧。查了半天,发现是CAN_H和CAN_L线接反了。嗯,这种低级错误,新手最容易犯。记住:CAN_H接CAN_H,CAN_L接CAN_L,别搞混。
2.1.2 数据链路层:报文结构
CAN报文分两种格式:标准帧(11位ID)和扩展帧(29位ID)。咱们做TBOX诊断,大部分用标准帧就够了。
一个标准CAN数据帧长这样:
| SOF | 仲裁场(11位ID + RTR) | 控制场(IDE + r0 + DLC) | 数据场(0-8字节) | CRC场 | ACK场 | EOF |
| 1 | 12 | 6 | 0-64 | 16 | 2 | 7 |
这里我重点说两个东西:
- 仲裁场:ID越小,优先级越高。0x000优先级最高,0x7FF最低。所以诊断请求报文ID通常设得很小,保证优先传输。
- 数据场:最多8字节。这是CAN总线的硬伤——一次只能传8个字节。做诊断时,如果数据量大,就得分包发送。
重要提示:CAN总线的波特率常见的有125kbps、250kbps、500kbps。诊断通信一般用500kbps。波特率不匹配,ECU根本不理你。
2.1.3 总线仲裁:谁先说话?
CAN总线是“多主”架构。任何节点都可以随时发消息。那冲突了怎么办?靠仲裁。
仲裁机制很简单:谁ID小,谁先发。发送过程中,每个节点都在监听总线。如果自己发的位和总线上的位不一致(自己发隐性,但总线上是显性),说明有更高优先级的节点在发,自己就乖乖退出发送。
我曾经调试过一个现象:诊断仪发请求,ECU偶尔不响应。后来发现是总线上有个报文ID=0x000的周期性消息,优先级太高,把诊断报文挤掉了。解决办法是调整诊断请求的ID,或者等总线空闲再发。
2.2 CAN诊断协议(UDS on CAN)
UDS(Unified Diagnostic Services)是ISO 14229定义的一套诊断服务。它不依赖底层通信介质,可以跑在CAN上,也可以跑在以太网上。咱们这里重点讲UDS on CAN。
2.2.1 诊断寻址:物理请求 vs 功能请求
UDS on CAN用CAN ID来区分不同的诊断会话。标准做法是:
| 角色 | CAN ID(标准帧) | 说明 |
|---|---|---|
| 诊断仪→ECU(物理请求) | 0x7E0 | 发给特定ECU |
| ECU→诊断仪(物理响应) | 0x7E8 | 对应ECU回复 |
| 诊断仪→ECU(功能请求) | 0x7DF | 广播给所有ECU |
物理请求是一对一的。功能请求是一对多的。比如你想让所有ECU都进入扩展诊断模式,就发功能请求。
我的经验:功能请求虽然方便,但响应处理很麻烦。所有ECU同时回复,总线会瞬间爆满。我建议非必要不用功能请求,尤其是读取数据时。
2.2.2 诊断服务:常用的几个
UDS定义了26种服务(SID从0x10到0x3E)。咱们做TBOX远程诊断,最常用的是这几个:
- 0x10 诊断会话控制:切换诊断模式(默认、扩展、编程)。
- 0x22 读取数据标识符:读ECU内部数据,比如车速、水温。
- 0x2E 写入数据标识符:写数据到ECU,比如配置参数。
- 0x31 例程控制:执行特定功能,比如自检、复位。
- 0x19 读取故障码:读DTC(诊断故障码)。
- 0x14 清除故障码:清DTC。
举个例子,读取ECU的VIN码(车辆识别号):
// 诊断请求:0x22 + DID(数据标识符)
// DID = 0xF190 表示VIN码
// 发送:02 22 F1 90
// 解释:02(数据长度) 22(服务ID) F1 90(DID)
// 正常响应:0x62 + DID + 数据
// 接收:10 14 62 F1 90 4C 56 47 00 00 00 00 00 00 00 00 00 00
// 解释:10(首帧,表示后续还有数据) 14(剩余20字节) 62(响应SID) F1 90(DID) 后面是VIN数据
注意看,VIN码17个字节,CAN一次只能传8字节。所以这里用了多帧传输。首帧(0x10)告诉接收方:我还有20字节要发。后续用连续帧(0x20、0x21...)把数据发完。
避坑指南:我曾经在项目里遇到一个bug——ECU发送多帧时,连续帧的序列号从0开始还是从1开始?标准规定从1开始。但有个供应商的ECU从0开始,导致TBOX一直收不全数据。后来加了兼容逻辑才解决。
2.2.3 网络层协议:ISO 15765-2
UDS on CAN的网络层由ISO 15765-2定义。它解决了CAN单帧8字节的限制。核心概念是:
- 单帧(SF):数据≤7字节,直接发。
- 首帧(FF):数据>7字节,第一帧告诉对方总长度。
- 连续帧(CF):后续数据,每帧7字节。
- 流控帧(FC):接收方告诉发送方“慢点发”或“继续发”。
流控帧很重要。如果ECU处理不过来,它会发FC帧要求发送方暂停。我见过一个案例:TBOX连续发诊断请求,ECU来不及处理,直接丢帧。后来加了流控机制,问题解决。
2.3 DoIP协议入门
DoIP(Diagnostic over Internet Protocol),说白了就是把UDS诊断跑在以太网上。为什么需要DoIP?因为CAN太慢了。500kbps的CAN,传一个512字节的数据块,要拆成70多帧,耗时几十毫秒。而以太网一帧就能搞定。
2.3.1 DoIP的物理层
DoIP通常用100BASE-TX(百兆以太网)或1000BASE-T(千兆以太网)。车上用双绞线,和家用网线一样。但注意:车载以太网用的是单对双绞线(100BASE-T1),不是标准的四对线。别买错线缆。
2.3.2 DoIP协议栈
DoIP的协议栈长这样:
| 应用层 | UDS (ISO 14229) |
| 传输层 | TCP/UDP (DoIP封装) |
| 网络层 | IPv4/IPv6 |
| 数据链路层 | Ethernet MAC |
| 物理层 | 100BASE-T1 / 100BASE-TX |
DoIP用TCP端口13400进行诊断通信。UDP端口13400用于发现车辆(车辆发现功能)。
2.3.3 车辆发现:怎么找到ECU?
DoIP有个很酷的功能——车辆发现。诊断仪发一个UDP广播消息,车上所有支持DoIP的ECU都会回复。回复内容包括:
- VIN码
- ECU的逻辑地址
- 支持的诊断服务列表
这样诊断仪就能自动发现车上有哪些ECU,不用手动配置。我在做远程诊断时,特别喜欢这个功能。TBOX启动后,先发一个车辆发现请求,就知道车上挂了多少个ECU,省去了配置文件的麻烦。
2.3.4 DoIP vs CAN诊断:怎么选?
| 对比项 | CAN诊断 | DoIP诊断 |
|---|---|---|
| 传输速率 | 最高1Mbps | 100Mbps~1Gbps |
| 单帧数据量 | 8字节 | 1500字节(以太网MTU) |
| 传输距离 | 几十米 | 100米以上 |
| 实时性 | 高(微秒级) | 中(毫秒级) |
| 应用场景 | 车内ECU诊断 | 远程诊断、刷写 |
我的建议是:车内诊断用CAN,远程诊断用DoIP。TBOX作为网关,一边接CAN总线,一边接以太网(4G/5G)。远程诊断时,TBOX把DoIP请求转成CAN诊断请求,再把CAN响应转成DoIP响应。
核心要点:搞懂CAN和DoIP,你就掌握了TBOX远程诊断的“任督二脉”。CAN是车内通信的基石,DoIP是远程通信的桥梁。两者结合,才能实现真正的远程诊断。
好了,这一章的内容就这些。下一章咱们聊聊TBOX的硬件架构设计,包括MCU选型、通信模块、电源管理等。到时候见。