4、UDS应用层核心服务:诊断会话控制服务、ECU复位服务、安全访问服务、通信控制服务
UDS协议的应用层,说白了就是一堆定义好的“服务”。每个服务都有一个唯一的SID(服务标识符)。你发一个请求,ECU回一个响应,就这么简单。
但简单归简单,这4个服务是诊断的基石。我做了这么多年,几乎每个项目都会跟它们打交道。今天咱们就把它们彻底讲透。
核心要点: 这4个服务分别控制ECU的“工作模式”、“重启行为”、“安全锁”和“通信开关”。它们是所有上层诊断功能的基础。
4.1 诊断会话控制服务 (0x10)
这个服务,我习惯叫它“换挡”。ECU上电后默认在默认会话(Default Session)里。你想干点“高级”的事,比如刷写软件、读一些敏感数据,就得先切换到对应的会话。
| 会话类型 | SID + Sub | 典型用途 |
|---|---|---|
| 默认会话 | 0x10 0x01 | 上电后的基础状态,只支持基本诊断服务 |
| 编程会话 | 0x10 0x02 | 刷写软件、配置参数 |
| 扩展会话 | 0x10 0x03 | 高级标定、特殊功能测试 |
我的经验: 切换会话时,ECU可能会退出之前的会话。比如你在扩展会话里做标定,一切换到编程会话,标定数据可能就丢了。所以,切换前一定要确认当前工作状态。
请求格式很简单:0x10 + sub-function。比如切换到编程会话,就发 02 10 02(假设CAN ID是0x7DF)。
// 请求示例:切换到编程会话
// CAN ID: 0x7DF
// 数据: 02 10 02
// 解释: 02表示后面有2个字节,10是SID,02是编程会话子功能
// 肯定响应示例
// CAN ID: 0x7E8
// 数据: 02 50 02
// 解释: 50 = 10 + 0x40,表示肯定响应,02表示当前在编程会话
注意: 如果ECU不支持你请求的会话,会返回否定响应码
0x12(子功能不支持)或 0x22(条件不满足)。我曾经遇到过,ECU必须在特定条件下才能进入编程会话,比如车速为0、点火开关打开等。
4.2 ECU复位服务 (0x11)
这个服务,说白了就是让ECU“重启”。你想想看,刷完软件后,总得让ECU重新跑一遍新代码吧?
| 复位类型 | 子功能 | 行为 |
|---|---|---|
| 硬复位 | 0x01 | 模拟断电再上电,ECU完全重启 |
| 钥匙通断复位 | 0x02 | 模拟点火开关OFF再ON,部分ECU会保持一些RAM数据 |
| 软复位 | 0x03 | 仅复位软件,不涉及硬件电源 |
| 使能快速路由 | 0x04 | 用于网关快速转发诊断请求,不常用 |
请求格式:0x11 + sub-function。比如硬复位,就发 02 11 01。
// 请求示例:硬复位
// CAN ID: 0x7DF
// 数据: 02 11 01
// 肯定响应示例
// CAN ID: 0x7E8
// 数据: 02 51 01
// 解释: 51 = 11 + 0x40,表示肯定响应
关键点: ECU收到复位请求后,会先发肯定响应,然后才执行复位。但复位后,ECU会回到默认会话。所以,如果你在编程会话里复位,复位后需要重新切换会话。
避坑指南: 我曾经在项目中遇到一个问题:ECU复位后,CAN控制器初始化需要时间。如果诊断仪在复位后立即发送请求,ECU可能还没准备好,导致通信失败。所以,复位后建议等待至少100ms再发下一个请求。
4.3 安全访问服务 (0x27)
这个服务,我习惯叫它“开锁”。ECU里有些敏感数据,比如刷写密钥、标定参数,不能随便让人读或写。你得先通过“安全访问”验证身份。
流程是这样的:
- 请求种子: 诊断仪发
0x27 0x01(请求种子),ECU返回一个随机数(种子)。 - 发送密钥: 诊断仪用种子和算法计算出一个密钥,发
0x27 0x02+ 密钥。 - 验证: ECU用同样的算法计算,如果密钥匹配,就解锁成功。
| 步骤 | 方向 | 数据示例 | 说明 |
|---|---|---|---|
| 1. 请求种子 | 诊断仪 → ECU | 02 27 01 | 请求种子(level 1) |
| 2. 发送种子 | ECU → 诊断仪 | 04 67 01 AA BB CC DD | 种子是 0xAABBCCDD |
| 3. 发送密钥 | 诊断仪 → ECU | 06 27 02 11 22 33 44 | 密钥是 0x11223344 |
| 4. 验证结果 | ECU → 诊断仪 | 02 67 02 | 肯定响应,解锁成功 |
我的经验: 安全访问算法通常是保密的,由OEM定义。我见过用简单的异或,也见过用AES加密的。但不管算法多复杂,流程都一样。另外,解锁后通常有超时机制,比如5秒内没操作,ECU会自动上锁。
注意: 如果密钥错误,ECU会返回否定响应码
0x35(无效密钥)。连续错误次数过多,ECU可能会锁定安全访问功能一段时间(比如30秒)。这是为了防止暴力破解。
4.4 通信控制服务 (0x28)
这个服务,说白了就是“开关”。你可以控制ECU的某些通信通道,比如关闭应用报文、只保留诊断报文。这在刷写时特别有用——你不想让ECU在刷写过程中还忙着发CAN报文吧?
| 控制类型 | 子功能 | 效果 |
|---|---|---|
| 启用Rx和Tx | 0x00 | 恢复正常通信 |
| 禁用Rx和Tx | 0x01 | 完全静默,只响应诊断请求 |
| 禁用Tx | 0x02 | ECU不发任何报文,但能收 |
| 禁用Rx | 0x03 | ECU不收任何报文,但能发 |
| 禁用特定网络Tx | 0x04 | 只禁用某个CAN网络的发送 |
请求格式:0x28 + sub-function + [通信类型]。比如禁用所有应用报文,只保留诊断报文,就发 03 28 01 03(03表示后面有3个字节,28是SID,01是禁用Rx和Tx,03是应用报文)。
// 请求示例:禁用应用报文(Rx和Tx)
// CAN ID: 0x7DF
// 数据: 03 28 01 03
// 解释: 01 = 禁用Rx和Tx,03 = 应用报文
// 肯定响应示例
// CAN ID: 0x7E8
// 数据: 02 68 01
// 解释: 68 = 28 + 0x40,表示肯定响应
关键点: 通信控制服务通常配合编程会话使用。刷写前,先切换到编程会话,然后禁用应用报文,这样刷写过程中就不会被其他报文干扰。刷写完成后,再启用通信,恢复ECU的正常工作。
我的经验: 有些ECU在禁用通信后,会进入一种“半休眠”状态。如果你在禁用通信后发送诊断请求,ECU可能响应很慢。所以,我建议在禁用通信后,先发一个“Tester Present”请求,确认ECU还活着。