大家好,我是嵌入式老林,从事嵌入式软件开发多年,今天分享的内容是UDS诊断例程控制0X31服务介绍,希望能对你有所帮助
一、例程控制服务介绍
主要功能就是由客户端请求启动,停止ECU中的例程或请求例程结果
简单介绍一下例程,就是一段写好的代码,可通过例程控制服务,去执行这段代码。
例程有两种:
1) 例程的开始和结束进行,由客户端对其进行控制,服务端仅负责接受和执行请求;
2) 另一种是由客户端请求例程开始执行,但例程结束由服务端控制,可以是在诊断响应之前就结束,也可以在诊断响应之后再结束
例程控制的应用场景:擦除内存,重置或学习自适应数据,自检,覆盖正常服务器控制策略,控制服务器值随时间变化等功能,包括预定义的序列(如关闭敞篷车顶)等。
二、数据格式
2.1 请求报文
格式:
[SID] + [sub-function] + [routineID] + [routineControlOptionRecord]
2.1.1 子功能
sub-function常用的类型有3个:启动例程,停止例程,请求例程结果
启动例程:服务端收到开始例程的请求后,应立即开始执行指定的例程,由于例程的不同,有些例程如擦除寄存器、数据校验等,需要立即执行并且在执行完给出结果的,则需要在执行完给出肯定或者否定响应;而有些如钥匙学习、车胎胎压等,需要由客户端发送请求来控制,则在正常开始例程之后给出肯定响应,如不正常则给出否定响应。
停止例程:服务端在接收到停止例程的请求后,应立即停止例程,如果例程停止成功,服务端需给出肯定响应;如果例程停止失败,则需要给出否定响应。
请求例程结果:一般的例程,在前面的两个指令的响应里,就会带有例程执行的结果。但是有一些由于例程的特殊性无法在响应里给出结果,所以需要单独请求例程执行的结果
2.1.2 例程ID(RID)
routineID也简称RID,用来表示例程的功能,这个一般会在客户的诊断调查表中定义,一般由车厂提供。ISO14229中RID的定义如下
0XFF00:擦除内存
0XFF01:检查编程依赖关系
0XFF02:擦除镜像内存DTC
0X0200~0XDFFF:汽车厂商定义
2.1.3 例程控制可选参数
一般用来携带其他信息,如程序的启动条件、停止条件等。如数据校验需要把校验标准发送给服务端,这样服务端可根据自身计算结果和接收到的校验数据进行校验比对,来判断校验结果。很少用到,目前在项目中没用到过
2.2 响应报文
2.2.1 肯定响应
报文格式:
[SID + 0X40] + [sub-function] + [routineID] + [routineInfo] + [routineStatusRecord]
子功能和RID和请求报文的保持一致即可
RoutineInfo字节是用于车辆制造商的,并根据此返回值为车辆制造商提供了一种机制,以支持所有实现例程的通用外部测试设备处理(例如,如果需要停止例程或请求例程结果)。
routineStatusRecord是可选参数,主要用来:
1) 在例程开始之后关于服务器状态的附加信息
2)用于在执行相应程序动作后,返回ECU相关的信息(如请求31 02服务请求停止时,ECU可以通过该参数返回该程序总运行时间,停止前例程产生的结果等信息)
3)先前在服务器中停止的例程的结果(退出状态信息)
2.2.2 否定响应
格式:[0X7F] + [SID] + [NRC]
支持的NRC如:
0X12:子功能不支持,也就是例程控制类型不对
0X13:请求的消息长度不正确,或格式错误
0X22:条件不正确,就是不满足服务端的运行条件
0X24:请求顺序错误;停止例程的请求必须在开始例程的后请求才可以,请求例程的执行结果也必须在开始例程之后才被允许,否则回复此NRC
0X31:不支持当前请求的RID,或例程控制的可选参数包含了一个无效的数据
0X33:没有过安全访问,需要先执行27服务解密后,才能执行22服务
0X72:在写入时,内存出错
三、举例子
请求开始执行例程,请求里的子功能是01,RID为02 01。这个请求是不带数据的,因此到RID就结束了。而有些例程是需要请求带数据的,如进行CRC校验时,需要客户端发送CRC结果给服务端,然后服务端才能跟自己计算的结果进行比较,此时就需要将CRC结果放到RID后面的routineStatusRecord发送出去。
实际项目中升级时的例子
在执行31服务前,要先切到扩展会话模式,然后再过安全访问,最后再执行31服务,子功能为启动例程,RID为检查编程条件
最后,如果觉得有帮助,希望你能一键三连(分享,点赞,在看),你们的认可是我持续输出的动力,感激不尽