基于图莫斯的CAN UDS升级上位机-LabVIEW版本(十):TOOMOSS_SID31_RoutineControl.vi — 例程控制

1. 引言

在UDS刷写流程中,例程控制(0x31 Service) 是用途最广泛、功能最强大的服务之一。如果说0x34-36-37负责传输数据,0x2E负责写入配置信息,那么0x31则负责执行ECU内部预定义的操作序列

在固件升级场景中,0x31服务承担着多项关键任务:

  • 擦除编程分区:在写入新固件前,擦除目标Flash区域

  • 编程条件检查:验证ECU是否满足升级条件(车速、电压等)

  • 完整性校验:下载完成后校验固件数据的正确性

  • 写入指纹信息(替代方案):部分项目使用0x31写入指纹

TOOMOSS_SID31_RoutineControl.vi封装了UDS 0x31服务的完整流程,通过调用TOOMOSS_SendAndWaitResp.vi通信基座,实现对ECU内部例程的启动、停止和结果查询。


2. 子VI功能概述

2.1 设计目标

  • 根据用户指定的子功能(启动/停止/查询结果)、例程ID和可选参数,构造0x31服务请求报文

  • 调用通信基座发送请求并等待ECU响应

  • 解析响应报文,判断例程执行是否成功

  • 返回响应数据和执行状态

2.2 UDS 0x31服务协议说明

服务名称:RoutineControl(例程控制)

功能:客户端(测试设备)能够启动、停止例程,并在例程执行后查看其生成的结果。RoutineControl服务用于执行定义的一系列步骤并获取相关结果。

2.2.1 子功能参数(routineControlType)

0x31服务使用子功能参数来区分例程的控制类型:

子功能值 名称 说明
0x01 startRoutine(启动例程) 请求ECU启动指定的例程
0x02 stopRoutine(停止例程) 请求ECU停止正在运行的例程
0x03 requestRoutineResults(请求例程结果) 请求获取例程执行的结果数据
2.2.2 请求报文格式

0x31服务的请求报文格式如下:

字节序号 参数 说明
Byte 0 SID 固定值 0x31
Byte 1 sub-function 子功能(0x01启动/0x02停止/0x03查询结果)
Byte 2 routineIdentifier(高字节) 例程标识符的高8位
Byte 3 routineIdentifier(低字节) 例程标识符的低8位
Byte 4 ~ N routineControlOptionRecord 可选的例程控制参数
2.2.3 肯定响应格式

肯定响应格式如下:

字节序号 参数 说明
Byte 0 SID 0x71(0x31 + 0x40)
Byte 1 sub-function 回声,与请求中的子功能一致
Byte 2 routineIdentifier(高字节) 例程标识符的高8位
Byte 3 routineIdentifier(低字节) 例程标识符的低8位
Byte 4 ~ N routineStatusRecord 例程执行结果/状态数据(可选)
2.2.4 否定响应格式
复制代码
Byte 0: SID = 0x7F
Byte 1: 0x31
Byte 2: NRC(负响应码)

2.3 常见例程ID(参考)

ISO 14229-1定义了一些标准的例程标识符:

例程ID 名称 说明
0xFF00 eraseMemory 擦除内存
0xFF01 checkProgrammingDependencies 检查编程依赖性
0xFF02 eraseMirrorMemoryDTCs 擦除镜像内存DTC
0x0200~0xDFFF vehicleManufacturerSpecific 车厂自定义
0xF000~0xFEFF systemSupplierSpecific 供应商自定义

注意:实际项目中,例程ID通常由车厂定义,请在诊断调查表中查阅具体定义。

2.4 输入参数

控件 类型 说明
设备句柄 U32 TOOMOSS_OpenDev(CAN).vi返回的设备句柄
通道号 枚举(CAN1/CAN2) 选择使用CAN1还是CAN2通道
物理地址 U32 请求报文ID(发送给ECU的CAN ID)
响应地址 U32 期望的响应报文ID(ECU回复的CAN ID)
子功能 枚举(启动例程/停止例程/请求结果) 例程控制类型
例程ID U16 要控制的例程标识符
其他数据 U8数组 可选的例程控制参数(由具体例程定义)
数据长度 I32 从0x31开始计算的请求数据总长度

2.5 输出参数

控件 类型 说明
响应数据 U8数组 ECU返回的完整响应数据(肯定响应或否定响应)
返回值 I32 0表示成功,-1表示失败
错误信息 字符串 失败时的错误描述

3. 前面板设计


4. 程序框图设计

4.1 整体流程

复制代码
子功能枚举 → 获取subFunction值
例程RID(U16)→ 拆分为高字节和低字节
其他数据(U8数组)→ 作为routineControlOptionRecord
                        ↓
       构造请求数据[0x31, subFunction, RID_High, RID_Low, 其他数据...]
                        ↓
            调用 TOOMOSS_SendAndWaitResp.vi
                        ↓
                判断响应类型
        ┌───────────────┼───────────────┐
        ↓               ↓               ↓
    返回<0           返回=0          返回>0
    (调用失败)      (超时)         (收到响应)
        ↓               ↓               ↓
    返回-1          返回-1       判断响应首字节
        ┌───────────────┼───────────────┐
        ↓               ↓
    0x71           0x7F
    (肯定响应)     (否定响应)
        ↓               ↓
    返回0          返回-1
                解析NRC返回错误信息

4.2 第一步:拆分例程ID

例程ID是一个2字节(U16)的标识符,需要拆分为高字节和低字节:

  • RID高字节 = (RID >> 8) & 0xFF

  • RID低字节 = RID & 0xFF

4.3 第二步:构造请求数据

使用创建数组函数按顺序组合:

复制代码
[0x31, subFunction, RID_High, RID_Low, 其他数据...]

其中其他数据routineControlOptionRecord,是可选的例程控制参数。当子功能为startRoutine或stopRoutine时,此参数可选。

4.4 第三步:调用通信基座

将上一步构造的请求数据作为输入,调用TOOMOSS_SendAndWaitResp.vi

输入参数 来源/值
设备句柄 子VI输入
通道号 子VI输入
物理地址 子VI输入
响应地址 子VI输入
请求数据 构造的[0x31, subFunction, RID_High, RID_Low, 其他数据...]
数据长度 数据长度输入(从0x31开始计算的总长度)
超时时间 根据不同例程设置(擦除类建议5000ms,查询类1000ms)

4.5 第四步:判断响应类型

从通信基座获取返回值,分三种情况处理:

情况一:返回值 < 0(通信失败)
  • 通信基座内部调用DLL失败

  • 直接透传错误信息,子VI返回 -1

情况二:返回值 = 0(无响应/超时)
  • ECU未响应

  • 设置错误信息为"ECU未响应,请检查物理地址和通信连接"

  • 子VI返回 -1

情况三:返回值 > 0(收到响应)
  • 响应数据有效,继续解析

  • 判断响应数据的首字节(Byte 0)

肯定响应判断

text

复制代码
if 响应数据[0] == 0x71 → 例程控制成功,返回0

响应数据0 = 0x71 = 0x31 + 0x40,符合UDS肯定响应规则。

否定响应判断

text

复制代码
if 响应数据[0] == 0x7F → 例程控制失败
    NRC = 响应数据[2]
    根据NRC值生成对应的错误信息
    返回-1

4.6 常见NRC错误信息映射

NRC 含义 错误信息
0x12 子功能不支持 "该ECU不支持请求的子功能或例程不存在"
0x13 报文长度错误 "请求报文长度或格式不正确"
0x22 条件不满足 "先决条件不满足,请检查当前会话状态"
0x31 参数无效 "传入的参数超出例程允许范围"
0x33 安全访问被拒绝 "安全访问未解锁,请先完成0x27服务"
0x72 故障处于活动状态 "执行例程时检测到其他故障"
0x7E 当前会话下子功能不支持 "当前会话下不支持该子功能"
0x7F 当前会话下服务不支持 "当前会话下不支持31服务"

5. 程序框图关键节点示意

5.1 例程ID拆分与请求数据构造

5.2 通信基座调用

5.3 响应解析


6. 在UDS刷写流程中的位置

在整个UDS刷写流程中,0x31服务在多个阶段被调用:

复制代码
预编程阶段:
  (2) 编程条件检查 [31 01 02 03] ← 调用本子VI(启动例程)

主编程阶段:
  (5) 擦除编程分区 [31 01 FF 00] ← 调用本子VI(启动例程)
  (7) 完整性校验 [31 01 02 02] ← 调用本子VI(启动例程或查询结果)

6.1 典型应用场景

场景 子功能 例程ID示例 参数说明
编程条件检查 启动例程(0x01) 0x0203 检查车速、电压等条件
擦除编程分区 启动例程(0x01) 0xFF00 擦除目标Flash区域
完整性校验 启动例程(0x01) 0x0202 校验固件CRC

6.2 前置条件

执行0x31服务前,通常需要满足以下条件:

  • 会话状态 :已切换到编程会话(0x02)扩展会话(0x03)

  • 安全访问:已通过0x27服务完成安全访问解锁(敏感例程)

  • 例程ID有效性:例程ID在ECU中已定义

6.3 子功能使用说明

子功能 使用场景
启动例程(0x01) 请求ECU开始执行例程,如擦除内存、条件检查等
停止例程(0x02) 请求ECU停止正在执行的例程
请求结果(0x03) 请求获取例程执行结果数据

7. 典型调用示例

7.1 启动擦除例程(0xFF00)

输入配置

  • 物理地址 = 0x700

  • 响应地址 = 0x708

  • 子功能 = 启动例程(0x01)

  • 例程ID = 0xFF00

  • 其他数据 = 擦除起始地址和长度(如[0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00]

  • 数据长度 = 11(0x31 + 子功能 + RID 2字节 + 8字节参数)

实际发送[0x31, 0x01, 0xFF, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x00]

期望响应[0x71, 0x01, 0xFF, 0x00, 0x00](肯定响应,0x00表示擦除成功)

7.2 启动编程条件检查例程

输入配置

  • 物理地址 = 0x700

  • 响应地址 = 0x708

  • 子功能 = 启动例程(0x01)

  • 例程ID = 0x0203(具体ID由车厂定义)

  • 其他数据 = 空(无参数)

  • 数据长度 = 4

实际发送[0x31, 0x01, 0x02, 0x03]

期望响应[0x71, 0x01, 0x02, 0x03, 0x00](0x00表示条件满足)

7.3 停止例程

输入配置

  • 子功能 = 停止例程(0x02)

  • 例程ID = 0xFF00

  • 其他数据 = 空

  • 数据长度 = 4

实际发送[0x31, 0x02, 0xFF, 0x00]

期望响应[0x71, 0x02, 0xFF, 0x00]

7.4 请求例程结果

输入配置

  • 子功能 = 请求结果(0x03)

  • 例程ID = 0xFF00

  • 其他数据 = 空

  • 数据长度 = 4

实际发送[0x31, 0x03, 0xFF, 0x00]

期望响应[0x71, 0x03, 0xFF, 0x00, 0x00, 0x00, 0x00](返回详细状态数据)


8. 错误处理

错误场景 返回值 错误信息
设备句柄无效 -1 "设备句柄无效,请检查设备是否已打开"
通信基座返回<0 -1 透传通信基座的错误信息
通信基座返回=0 -1 "ECU未响应,请检查物理地址和通信连接"
响应首字节为0x7F -1 根据NRC返回对应错误信息
响应首字节非0x71非0x7F -1 "收到未知响应,SID=0x%02X"

9. 注意事项

要点 说明
会话要求 敏感例程(如擦除内存)通常需要编程会话(0x02),其他例程可能需要扩展会话
安全访问 擦除内存等敏感例程必须在完成0x27安全访问解锁后执行
例程ID定义 例程ID由车厂定义,请在诊断调查表中查阅
超时时间 不同例程执行时间差异大:擦除Flash建议5000ms以上,条件检查建议2000ms
例程参数 部分例程需要携带参数(如擦除地址、长度),参数格式由具体例程定义
子功能与参数 当子功能为startRoutine或stopRoutine时,routineControlOptionRecord是可选的
权限检查 UDS对0x31服务的权限检查是在例程ID级别进行的,而非子功能级别

10. 总结

TOOMOSS_SID31_RoutineControl.vi封装了UDS 0x31例程控制服务,是UDS刷写上位机中功能最强大、用途最广泛的服务之一。

0x31服务的核心价值在于:

  • 执行复杂操作:擦除内存、运行自检、条件检查等无法通过简单读写完成的操作

  • 灵活可扩展:车厂可根据需要为ECU定义各种内部操作

  • 三种控制模式:启动、停止、查询结果,覆盖例程的完整生命周期

理解子功能(启动/停止/查询结果)和例程ID的含义,以及不同例程对会话状态和安全访问的要求,是正确使用该子VI的关键。

下一篇将介绍 Main**.vi --- 主VI**的完整实现,敬请期待。

相关推荐
kingwebo'sZone7 小时前
我写的第一个labview 展示页面程序
labview
电气_空空10 小时前
基于 LabVIEW的数据采集与信号处理系统的设计
嵌入式硬件·毕业设计·信号处理·labview
无垠的广袤1 天前
【RA-Eco-RA4M2开发板】步进电机的串口控制和 LabVIEW 数据采集
单片机·嵌入式硬件·labview
fanchenxinok1 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本(八):TOOMOSS_SID85_ControlDTCSetting.vi — DTC控制
can·labview·uds刷写·图莫斯
fanchenxinok1 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本(十一):LogManager.vi — 日志管理
can·labview·uds刷写·图莫斯
fanchenxinok1 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本(九):TOOMOSS_SID2E_WriteDataByID.vi — 写入数据
can·labview·uds刷写
fanchenxinok2 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本:从零搭建ECU刷写工具
labview·uds升级·升级上位机
fanchenxinok2 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本(一):TOOMOSS_OpenDev(CAN).vi — 设备打开与句柄管理
labview
fanchenxinok2 天前
基于图莫斯的CAN UDS升级上位机-LabVIEW版本(四):TOOMOSS_SID27_SecurityAccess.vi — 安全访问
安全·labview·uds升级·子vi