2、UDS服务基础:服务ID(SID)分类、请求与响应机制、物理寻址与功能寻址
好,咱们进入正题。这一章讲的是UDS最底层的骨架——服务ID怎么分类、请求响应怎么玩、寻址方式怎么选。这些东西看着基础,但我在OTA刷写项目里踩过的坑,十有八九都跟这些基础概念没吃透有关。你想想看,刷写过程中一个SID发错了,ECU直接给你拒掉,整包数据都得重来,那叫一个酸爽。
2.1 服务ID(SID)分类:从0x10到0x3E
UDS的服务ID,说白了就是一个字节的命令码。范围从0x00到0x3E,但实际常用的也就二十来个。我个人习惯把它们分成三大类:
- 诊断管理类:比如0x10(诊断会话控制)、0x11(ECU复位)、0x3E(Tester Present)。这类服务负责“能不能干活”的问题。
- 数据类:比如0x22(读取数据)、0x2E(写入数据)、0x23(读取内存)。这类服务负责“数据怎么拿怎么放”。
- 程序类:比如0x34(请求下载)、0x36(传输数据)、0x37(请求退出传输)。OTA刷写主要跟这群兄弟打交道。
重要提醒:每个SID的请求和响应格式是严格对应的。比如0x34请求下载,响应里必须带地址和长度信息。我曾经见过一个供应商把响应格式搞反了,结果刷写时ECU一直报错,排查了两天才发现是SID响应字节顺序错了。
这里有个小规律:SID的bit6决定了这是请求还是响应。请求的bit6=0,响应的bit6=1。举个例子,0x22是读取数据请求,那它的响应SID就是0x62。嗯,这个规律在调试时特别有用,你抓个报文一看SID就知道是发出去的还是回来的。
2.2 请求与响应机制:一问一答的规矩
UDS的通信模式,说白了就是“你问我答”。Tester发一个请求,ECU必须回一个响应。但这个响应分两种:肯定响应和否定响应。
肯定响应很简单:响应SID = 请求SID + 0x40。比如你发0x22,ECU回0x62,后面跟着你要的数据。
否定响应就有点意思了。ECU会回0x7F,后面跟着两个字节:第一个是你发的请求SID,第二个是错误码。常见的错误码有:
| 错误码 | 含义 | 我遇到的场景 |
|---|---|---|
| 0x11 | 服务不支持 | ECU没烧录这个SID的处理代码 |
| 0x12 | 子功能不支持 | 比如0x10的某些子功能没实现 |
| 0x13 | 报文长度错误 | 多发了或少发了字节,我常犯这错 |
| 0x22 | 条件不满足 | 没进入编程会话就想刷写,门儿都没有 |
| 0x31 | 请求超出范围 | 地址或数据长度不对 |
| 0x78 | 正在处理,请稍候 | 刷写大数据块时ECU说“我忙着呢” |
我的经验:0x78这个错误码在OTA刷写中特别常见。ECU收到一包数据后需要时间擦写Flash,这时候就会回0x78。Tester收到后要等一会儿再发下一包,别傻乎乎地一直重试。我一般设置500ms的超时重试,效果不错。
还有一个细节:请求和响应之间是有时间限制的。标准规定ECU必须在P2时间内给出响应,否则Tester就认为超时了。P2时间一般是50ms,但刷写时可以协商延长到几秒。你想想看,擦写Flash动不动就几百毫秒,不延长肯定超时。
2.3 物理寻址与功能寻址:找对人才好办事
这个知识点,我当年刚入行时觉得很简单,直到有一次在实车上把功能寻址和物理寻址搞混了,结果一个指令发出去,全车ECU都复位了……嗯,从那以后我再也不敢小看这个了。
物理寻址:一对一通信。Tester发一个报文,只有一个ECU会响应。CAN总线上通过源地址和目标地址来区分。比如你想刷写发动机ECU,就用它的物理地址发请求。
功能寻址:一对多通信。Tester发一个报文,所有支持该功能的ECU都会响应。功能地址是固定的,比如0x7DF(CAN诊断的标准功能地址)。
在OTA刷写中,这两种寻址各有用途:
- 功能寻址:适合广播指令。比如你想让所有ECU进入编程会话,发一个功能寻址的0x10 0x02,所有ECU都会响应。但要注意,如果多个ECU同时响应,总线可能会冲突。所以功能寻址一般只用于“通知类”指令,不用于数据传输。
- 物理寻址:适合一对一的数据传输。刷写时每个ECU的固件包都不一样,必须用物理寻址单独发。我习惯在刷写前先通过功能寻址让所有ECU进入编程模式,然后再用物理寻址逐个刷写。
避坑指南:我曾经在一个项目里,用功能寻址发了0x34请求下载,结果多个ECU同时回复肯定响应,CAN总线直接爆了。后来我改成先用功能寻址发0x10进入编程会话,再用物理寻址发0x34,问题就解决了。记住:功能寻址只适合“通知”,不适合“请求数据”。
还有一个容易忽略的点:ECU对功能寻址的响应是可以配置的。有些ECU在功能寻址下只回否定响应,或者干脆不回响应。这取决于OEM的需求。所以你在做OTA刷写时,一定要先确认目标ECU的功能寻址行为,不然你发个功能寻址指令,ECU没反应,你还以为它坏了。
2.4 小结:基础不牢,地动山摇
这一章的内容,说白了就是UDS通信的“交通规则”。SID决定了你要干什么,请求响应机制决定了怎么对话,寻址方式决定了找谁说话。这三个东西搞不清楚,后面做OTA刷写时肯定会碰壁。
我个人建议:刚开始接触UDS时,先拿一个CAN工具(比如PCAN或CANoe)抓抓报文,看看实际通信中SID是怎么交互的。我记得我第一次抓报文时,看到0x7F的否定响应一头雾水,后来查了标准才知道是啥意思。实践出真知,这话一点不假。
下一章我们会讲UDS的会话管理和安全访问,这两个是OTA刷写的“门禁系统”。进不去门,啥都干不了。咱们下回见。