![]()
目录
- $84 SecuredDataTransmission
- $86 ResponseOnEvent
- $87 LinkControl
- $23 ReadMemoryByAddress
- $24 ReadScalingDataByIdentifier
- $2A ReadDataByPeriodicIdentifier
- $2C DynamicallyDefineDataIdentifier
- $3D WriteMemoryByAddress
- $19 ReadDTCInformation
- $2F InputOutputControlbyIdentifier
- $31 RoutineControl
- $34 RequestDownload
- $35 RequestUpload
- $36 TransferData
- $37 RequestTransferExit
- $38 RequestFileTransfer
$84 SecuredDataTransmission
1 Service description
$84服务用于保护受到第三方攻击的数据传输,避免危及数据安全。
$84 SecuredDataTransmission服务适用于client以安全模式使用诊断服务。其还可以用于client和ECU之间以安全模式传输符合其他应用层协议的数据,在这种情况下,安全模式意味着传输的数据受到加密方法的保护。
为了在安全模式下执行诊断服务,必须增添一个安全子层在ECU和client应用程序和应用层之间。下图说明了安全子层的实现概念:

有两种方法可以实现诊断服务数据传输在客户端和服务器之间:
不安全数据传输模式
诊断服务数据通过应用层服务原语在client和ECU之间传递,安全子层在ECU和client应用程序和应用层之间透传数据。
安全数据传输模式:
诊断服务数据通过安全子层服务原语在client和ECU之间传递,安全子层使用$84 SecuredDataTransmission服务来接收和发送安全数据。由于安全链路必须是点对点通信,所以安全数据传输模式只允许物理寻址。
根据ISO/OSI模型约定,ISO 14229标准提供了以下四个安全子层服务原语作为安全子层与应用程序的接口(安全子层服务原语中包含的寻址信息直接映射到应用层的寻址信息上,反之亦然):
SS_SecuredMode.req: 安全子层服务请求原语
SS_SecuredMode.request (
SA,
TA,
TA_type
[,RA]
[,parameter 1, …]
)
SS_SecuredMode.ind:安全子层服务指示原语
SS_SecuredMode.indication (
SA,
TA,
TA_type
[,RA]
[,parameter 1, …]
)
SS_SecuredMode.resp:安全子层服务响应原语
SS_SecuredMode.response (
SA,
TA,
TA_type
[,RA,]
Result
[,parameter 1, …]
)
SS_SecuredMode.conf:安全子层服务确认原语
SS_SecuredMode.confirm (
SA,
TA,
TA_type,
[RA,]
Result
[,parameter 1, …]
)
只有需要确认服务(即suppressPosRspMsgIndicationBit = FALSE)允许在安全模式运行,因此,以下服务不允许在安全模式下运行:$86 ResponseOnEvent$2A ReadDataByPeriodicIdentifier$3E TesterPresent
在安全模式下执行诊断服务时,安全子层的任务是加密应用程序提供的数据和解密应用层提供的数据,以及添加、检查和删除特定于安全性的数据元素。安全子层使用$84 SecuredDataTransmission服务,根据外部应用层协议的请求和响应,发送和接收诊断服务数据。
下图展示了在安全模式下执行需要确认服务时,安全子层、应用层和应用程序的交互逻辑:

- 在安全模式下,
client应用程序使用安全子层服务请求原语执行诊断服务请求。安全子层首先与ECU建立连接,然后给诊断数据添加安全特定参数,最后为诊断服务的诊断请求数据加密,并利用$84服务将诊断请求的安全数据传输到ECU。 ECU的安全子层在接收到$84服务传递的诊断请求安全数据后,首先检查安全特定参数,然后解密数据,并通过安全子层服务指示原语将要在安全模式下执行的诊断服务请求数据传递给ECU应用程序。应用程序执行诊断请求后,在安全模式下,通过安全子层服务响应原语将响应数据传递到安全子层,然后在安全子层添加安全特定参数,并加密响应数据,最后利用$84服务将诊断响应的安全数据传输到client。client的安全子层在接收到$84服务传递的诊断响应安全数据后,首先检查安全特定参数,然后解密响应数据,并通过安全子层服务确认原语将要在安全模式下执行的诊断服务响应数据传递给client应用程序。
2 Request message
以下是$84服务的请求消息定义:

securityDataRequestRecord:
该record包含由安全子层处理生成的$84 SecuredDataTransmission服务请求数据
3 Positive response message
以下是$84服务的正响应消息定义:

securityDataResponseRecord:
该record包含由安全子层处理生成的$84 SecuredDataTransmission服务响应数据
4 Supported NRC
以下是$84服务支持的NRC:

$86 ResponseOnEvent
1 Service description
$86服务用于请求ECU开始或停止传输响应当一个特定事件发生时。
当ECU中某特定事件发生时,$86服务提供了其能自动执行诊断服务的可能。client可以指定特定事件(包括该事件的可选参数)以及当特定事件发生时,要执行的诊断服务(包括服务参数)。下图简要说明了$86服务中client和server之间的关系(假设事件窗口计时器被配置为在ECU下电之前超时):

ECU应在接收到$86服务诊断请求消息时评估其附带的子功能和参数,具体包含如下:
- eventType
- eventWindowTime
- eventTypeRecord (eventTypeParameter #1-#m)
- serviceToRespondToRecord (serviceId serviceParameter #1-#r)
当ECU收到$86服务诊断请求消息包含无效数据时,应发送包含NRC 0x31的负响应给client。ECU不会在收到$86服务诊断请求消息时就评估serviceToRespondToRecord参数,只有当指定的特定事件发生,触发serviceToRespondToRecord参数所包含的诊断服务执行时,才回去评估该参数。若无法执行,或执行条件不正确,则ECU应发生包含合理的NRC的负响应给client。ECU应按照多个特定事件的发生顺序,发出$86服务的响应数据。
关键点:
$86 ResponseOnEvent服务可以在ECU的任何诊断会话中设置和激活,且不需要$3E TesterPresent服务保持$86服务激活。- 当特定事件发生时,
ECU正在执行某诊断服务,则serviceToRespondToRecord参数中所包含的诊断服务应延迟执行,直到当前的诊断服务执行完毕。注意,由于诊断服务被延迟执行,$86服务对于特定事件的响应数据可能不匹配。 - 当有多个特定事件同时发生时,这种对于多事件的处理逻辑,应有车辆制造商去定义。
- 当有特定事件触发,且在
$86服务设置的事件时间窗口内发生,则ECU应执行serviceToRespondToRecord参数中包含的诊断服务。 - 当
ECU被$10 DiagnosticSessionControl服务控制切换到任何非默认的诊断会话时(无论是不同的非默认诊断会话或相同的非默认诊断会话),$86 ResponseOnEvent服务都应被停止。当ECU返回到默认诊断会话时,之前在默认诊断会话中激活的所有$86 ResponseOnEvent服务都应被重新激活。 - 带有不同需求(不同的
EventTypes,serviceToRespondToRecords等参数)的多个$86 ResponseOnEvent服务可能会并发的启动或停止诊断服务,不过控制启动和停止的子功能应始终控制所有的$86 ResponseOnEvent服务。 - 若设置了
$86 ResponseOnEvent服务,则还有以下关键点:- 若
eventType子功能参数的第六位设置为0(不存储特定事件),则$86 ResponseOnEvent服务将在ECU下电时终止。 - 若
eventType子功能参数的第六位设置为1(要存储特定事件),则$86 ResponseOnEvent服务将在ECU上电后恢复,因此,该设置只允许与eventWindowTime不设限的设置同时使用。
- 若
- 只有当
client发送的$86服务诊断请求的eventType参数为stopResponseOnEvent或startResponseOnEvent或clearResponseOnEvent时,才能设置诊断请求消息的suppressPosResponseMessageIndicattionBit = 1。当指定的特定事件发生时,ECU总能对事件触发的响应给出应答。 - 只有当
$86服务的eventWindowTime被设置为有限值,且eventWindowTime已过去时,ECU才能返回final响应,以指示$86服务的事件窗口时间已过去。 - 为了避免干扰正常的诊断操作,建议将
$86服务只应用于瞬态发生的事件。对于事件发生需要持续一段时间的情况,对应的诊断服务应在事件初始发生时只执行一次。当设置的特定事件高频发生时,为防止出现反复来回的触发,可以通过eventTypeRecord参数设置两次事件诊断响应之间的最小间隔时间,其可由车辆制造商定义。
建议仅使用下表中列出的诊断服务,以便在发生指定事件时能够执行:
| Recommended services | Request SID | Response SID |
|---|---|---|
| ReadDataByIdentifier | 0x22 | 0x62 |
| ReadDTCInformation | 0x19 | 0x59 |
| RoutineControl | 0x31 | 0x71 |
| InputOutputControlByIdentifier | 0x2F | 0x6F |
2 Request message
以下是$86服务的请求消息定义:

eventType:
其是$86服务的sub-function参数,用于指示要在ECU中配置的事件,并控制$86 ResponseOnEvent服务的启停。下表详细介绍了$86服务的子功能参数定义(子功能参数值不包含suppressPosRspMsgIndicationBit (bit 7))。
eventType子功能参数的第六位是storageState状态位,用于控制特定事件触发是应存储在ECU的NVM中,且在ECU下次上电后重新恢复,还是在ECU下电时终止。
| storageState | Description |
|---|---|
| 0x00 | doNotStoreEvent 此参数用于指示当ECU下电时,$86服务将终止,且上电后也不在恢复 |
| 0x01 | storeEvent 此参数用于指示 1. 当$86服务在默认会话中被启动或停止,则下次ECU上电后,$86服务仍应被启动或停止 2. 对于$86服务所有的事件逻辑设置都应被永久存储,直到其被clearResponseOnEvent显式清除,或被事件逻辑想同的新$86服务所覆盖 |
| eventType | Description |
|---|---|
| 0x00 | stopResponseOnEvent 此参数用于控制$86服务不再针对特定事件做出响应,但设置的特定事件触发逻辑不会被清除 eventTypeRecord参数长度:0字节 |
| 0x01 | onDTCStatusChange 此参数用于指示$86服务的特定事件为检查到一个新的DTC,且该DTC和指定的DTCStatusMask匹配 eventTypeRecord参数长度:1字节 在eventTypeRecord参数中指定DTCStatusMask |
| 0x02 | onTimerInterrupt 此参数用于指示$86服务的特定事件为计时器中断。 eventTypeRecord参数长度:1字节 在eventTypeRecord参数需要指定更多细节 |
| 0x03 | onChangeOfDataIdentifier 此参数用于指示$86服务的特定事件为DID有新的内部数据记录,该数据值可由车辆制造商定义 eventTypeRecord参数长度:2字节 在eventTypeRecord参数需要指定更多细节 |
| 0x04 | reportActivatedEvents 此参数用于指示$86服务在肯定响应中报告所有已在$86服务中激活的事件(并且当前处于活动状态) eventTypeRecord参数长度:0字节 |
| 0x05 | startResponseOnEvent 此参数用于控制$86服务开始针对特定事件做出响应 eventTypeRecord参数长度:0字节 |
| 0x06 | clearResponseOnEvent 此参数用于清除在ECU里设置的$86服务特定事件触发逻辑(这会让ECU停止对特定事件的响应) eventTypeRecord参数长度:0字节 |
| 0x07 | onComparisonOfValues 此参数用于指示$86服务的特定事件为DID的测量值与给定值的比较结果和指定的比较结果一致 eventTypeRecord参数长度:10字节 |
| 0x08 – 0x1F | ISOSAEReserved |
| 0x20 – 0x2F | VehicleManufacturerSpecific 车辆制造商规定 |
| 0x30 – 0x3E | SystemSupplierSpecific 系统供应商规定 |
| 0x3F | ISOSAEReserved |
子功能onTimerInterrupt参数的具体细节说明:
通过onTimerInterrupt子功能,ECU可以配置定时器的中断时间速率以触发事件。
eventTypeRecord使用以下定义:
- Slow rate,慢速
- Medium rate,中速
- Fast rate,快速
定义以上定时器时间表选项相关的时间速率是车辆制造商的具体任务,例如下表:
| eventTypeRecord | Event will be generated | Timer type |
|---|---|---|
| 0x01 | 慢速中断 | 慢速定时器,1s |
| 0x02 | 中速中断 | 中速定时器,300ms |
| 0x03 | 快速中断 | 快速定时器,25ms |
子功能onChangeOfDataIdentifier参数的具体细节说明:
通过onChangeOfDataIdentifier子功能,ECU可以在一定周期时间内去读取DID的值并与原值比较。eventTypeRecord可以设置两个字节大小的DID。
子功能onComparisonOfValues参数的具体细节说明:
通过onComparisonOfValues子功能,可以控制ECU读取指定的DID并进行比较,下表为使用onComparisonOfValues子功能时,$86服务各字节参数的定义:
| DataByte | ParameterName | ByteValue | Comment | Detailed |
|---|---|---|---|---|
| 1 | ServiceID | 0x86 | Request SID | |
| 2 | eventType | 0x07 | sub-function onComparisonOfValues | |
| 3 | eventWindowTime | 0x02 | Infinite TimeWindow specification | |
| 4 | eventTypeRecord byte1 | 0x01 | DID high byte | 用于比较的DID可以和事件触发后要执行的DID不一致 |
| 5 | eventTypeRecord byte2 | 0x04 | DID low byte | |
| 6 | eventTypeRecord byte3 | 0x01 | 比较逻辑,见下表 | 该位用于设置比较方式的逻辑 |
| 7 | eventTypeRecord byte4 | 0x00 | 原始比较值 MSB | 该位用于设置比较的参考值 |
| 8 | eventTypeRecord byte5 | 0x00 | 原始比较值 | 该位用于设置比较的参考值 |
| 9 | eventTypeRecord byte6 | 0x01 | 原始比较值 | 该位用于设置比较的参考值 |
| 10 | eventTypeRecord byte7 | 0x00 | 原始比较值 LSB | 该位用于设置比较的参考值 |
| 11 | eventTypeRecord byte8 | 0x0A | hysteresis value | 该位用于设置从0%到100%的histeresys value |
| 12 | eventTypeRecord byte9 | 0xBC | Localization byte1,MSB | 该位用于定义DID的值位置信息 |
| 13 | eventTypeRecord byte10 | 0x58 | Localization byte2,LSB | 该位用于定义DID的值位置信息 |
| 14 | serviceToRespondTo byte1 | 0x22 | SID | 设置事件触发后,要执行的诊断服务和DID。$86服务的第一条肯定响应消息中,numberOfIdentifiedEvents始终设置为0x00 |
| 15 | serviceToRespondTo byte2 | 0xA1 | DID1 | |
| 16 | serviceToRespondTo byte3 | 0x00 | DID2 |
比较逻辑参数(comparison logic)的定义:
| Comparison logic ID | Event will be generated when |
|---|---|
| 0x01 | Comparison Parameter < Measured Value |
| 0x02 | Comparison Parameter > Measured Value |
| 0x03 | Comparison Parameter = Measured Value |
| 0x04 | Comparison Parameter <> Measured Value |
16位值位置(localization of value)位域的定义:
| Bitfield bit position | Description |
|---|---|
| 15 | (MSB), bit = 0 表示以无符号格式比较, bit = 1 表示以有符号格式比较 |
| 14 – 10 | 第10位(LSB) -第14位(MSB)用于指示要比较的DID的数据长度。0x00指示要比较4个字节,其他值以位为单位设置大小。第14位-第10位共有5个位,因此最大长度为31 bit。 |
| 9 – 0 | 其用于指示提取DID值的偏移量,Bit#0(LSB) – Bit#9 (MSB)共有10个位,因此偏移量最大大小为1023 bit。 |
eventWindowTime:
该参数用于指定$86服务事件触发逻辑在ECU中被激活的窗口时间。有限的事件窗口时间不能与storageState = storeEvent同时使用。其具体定义如下:
| eventWindowTime | Description |
|---|---|
| 0x00-0x01 | ISOSAEReserved |
| 0x02 | infiniteTimeToResponse 此参数值用于指示$86服务事件触发激活的窗口时间无限制 |
| 0x03 – 0x7F | vehicleManufacturerSpecific |
| 0x80 – 0xFF | ISOSAEReserved |
eventTypeRecord:
该record包含了指定事件类型的附件参数
serviceToRespondToRecord:
该record包含了当$86服务指定的特定事件触发时,要执行的诊断服务和服务参数
3 Positive response message
以下是$86服务的正响应消息定义(子功能不为reportActivatedEvents):


以下是$86服务的正响应消息定义(子功能为reportActivatedEvents):

eventType:
该参数是$86服务的请求消息中的子功能参数的0-6位计算值回显
eventTypeOfActiveEvent:
该参数是$86服务的请求消息的子功能参数为reportActivatedEvents的回显,其值为eventType子功能参数指定的值
numberOfActivatedEvents:
该参数指示$86服务指定特定事件触发时,ECU中已激活的事件数
numberOfIdentifiedEvents:
该参数指示在激活的事件窗口时间识别的事件数量,其仅适用于在有限的事件窗口时间情况下,事件窗口时间结束时发生的响应。首次响应该参数应总是0
eventWindowTime:
该参数是$86服务的请求消息中eventWindowTime参数的回显,用于指示事件窗口的剩余时间
eventTypeRecord:
该record是$86服务的请求消息中eventTypeRecord参数的回显
serviceToRespondToRecord:
该record是$86服务的请求消息中serviceToRespondToRecord参数的回显
4 Supported NRC
以下是$86服务支持的NRC:

5 Message flow example1
以下消息流展示了$86服务的工作原理。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。同时假设存在以下条件:
eventWindowTime参数值为0x08,其表示时间窗口时间为eventWindowTime * 10 = 80s- 有一个触发信号,可以触发
client向ECU发送$86服务请求 ECU一旦接收到$86服务请求报文后,就会立即去评估该请求。若评估有效,则ECU设置触发事件逻辑,且发送初始的肯定响应报文。为了激活事件逻辑,client的请求消息的eventType子功能参数应为startResponseOnEvent。在肯定响应发送之后,事件触发逻辑被激活,且事件窗口计时器开始运行。若ECU检查到指定的事件触发,则其必须立即执行serviceToRespondToRecord中包含的诊断服务,且立即响应与诊断服务相对应的响应消息。- 推荐根据参数
eventWindowTime来关闭事件窗口。事件窗口关闭后,ECU将停止检测触发事件。通过发送$86服务请求消息(eventType子功能参数应为stopResponseOnEvent)或下电也可以实现事件窗口关闭。
诊断请求消息示例(设置事件逻辑):

诊断正响应消息示例(设置事件逻辑):

诊断请求消息示例(激活事件):

诊断正响应消息示例(激活事件):

诊断正响应消息示例(特定事件触发):

诊断请求消息示例(报告活动事件情况):

诊断正响应消息示例(报告活动事件情况):

诊断正响应消息示例(事件窗口时间超时):

6 Message flow example2
以下消息流展示了$86服务的工作原理。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。同时假设存在以下条件:
eventWindowTime参数值为0x02,其表示时间窗口时间为无限制
诊断请求消息示例(设置事件逻辑):

诊断正响应消息示例(设置事件逻辑):

诊断请求消息示例(激活事件):

诊断正响应消息示例(激活事件):

诊断正响应消息示例(特定事件触发):

7 Message flow example3
以下消息流展示了$86服务的工作原理。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。同时假设存在以下条件:
storageState (eventType sub-function bit 6)设置为1,表示storeEventeventType子功能参数为onComparisonOfValueseventWindowTime参数值为0x02,其表示时间窗口时间为无限制eventTypeRecord参数中要比较的DID值为0x0104eventTypeRecord参数中,comparison parameter为0x01,即测量值大于给定值eventTypeRecord参数中,hysteresis value为0x0A,用于指定百分比为10%,其只有在操作符为<和>时才能使用。当测量值低于给定的比较值90%至少一次之前不会触发另一事件。如果满足了此条件,并且测量值再次高于给定比较值,则会触发新事件。eventTypeRecord参数中,DID的位置信息localization of value为0xBC58eventTypeRecord参数中,给定值为0x0000147AserviceToRespondToRecord参数指定的诊断服务为ReadDataByIdentifier,诊断服务参数为0x0104
诊断请求消息示例(设置事件逻辑):

当$86服务事件窗口时间和触发事件设置成功之后,如果DID 0x0104测量值大于0x0000147A,则特定事件触发成功,ECU会发送以下报文作为响应:

$87 LinkControl
1 Service description
$87服务提供了ECU在非默认诊断会话期间重新配置其数据链路层通信参数的能力,以获得出于不同诊断目的的不同总线带宽。该诊断服务可以将数据链路层切换到某个可以允许更高诊断数据带宽的状态,例如在进行刷写时,提高CAN总线的波特率,或者重新配置FlexRay通信周期。
为了克服通信功能限制,例如波特率必须同时在多个ECU中配置,该诊断服务的执行分为两个步骤:
- 检查
ECU是否支持需要调整到的目标波特率。 - 请求
ECU切换到支持目标波特率的通信状态。在进行通信状态切换时,建议将suppressPosRspMsgIndicationBit置TRUE,以避免ECU的响应,因为可能该ECU已经切换到新的通信状态了,但其他ECU还是旧的通信状态。
2 Request message
以下是$87服务的请求消息定义(linkControlType = verifyModeTransitionWithFixedParameter):

以下是$87服务的请求消息定义(linkControlType = verifyModeTransitionWithSpecificParameter):

以下是$87服务的请求消息定义(linkControlType = transitionMode):

linkControlType:
其是$87服务的sub-function参数,用于指示要在ECU中执行的动作,下表详细介绍了$86服务的子功能参数定义(子功能参数值不包含suppressPosRspMsgIndicationBit (bit 7))。
| linkControlType | Description |
|---|---|
| 0x00 | ISOSAEReserved |
| 0x01 | verifyModeTransitionWithFixedParameter 此参数用于指示进行是否可以执行带有预定义参数转换的验证,预定义参数由linkControlModeIdentifier参数指定 |
| 0x02 | verifyModeTransitionWithSpecificParameter 此参数用于指示进行是否可以执行带有指定特定参数转换的验证,特定参数由linkRecord参数指定,例如特定的波特率 |
| 0x03 | transitionMode 此参数用于指示ECU将数据链路层状态切换到前面验证消息中所请求的模式 |
| 0x04 – 0x3F | ISOSAEReserved |
| 0x40 – 0x5F | vehicleManufacturerSpecific |
| 0x60 – 0x7E | systemSupplierSpecific |
| 0x7F | ISOSAEReserved |
linkControlModeIdentifier:
该参数用于指示需要转换的预定义参数,其具体定义见下表:
| Byte Value | Description |
|---|---|
| 0x00 | ISOSAEReserved |
| 0x01 | PC9600Baud 指定标准PC波特率为9.6 K |
| 0x02 | PC19200Baud 指定标准PC波特率为19.2 K |
| 0x03 | PC38400Baud 指定标准PC波特率为38.4 K |
| 0x04 | PC57600Baud 指定标准PC波特率为57.6 K |
| 0x05 | PC115200Baud 指定标准PC波特率为115.2 K |
| 0x06 – 0x0F | ISOSAEReserved |
| 0x10 | CAN125000Baud 指定标准CAN波特率为125 K |
| 0x11 | CAN250000Baud 指定标准CAN波特率为250 K |
| 0x12 | CAN500000Baud 指定标准CAN波特率为500 K |
| 0x13 | CAN1000000Baud 指定标准CAN波特率为1M |
| 0x14 – 0x1F | ISOSAEReserved |
| 0x20 | ProgrammingSetup 此值指定车辆网络的刷写模式设置,可根据车辆网络要求对其参数化 |
| 0x21- 0xFF | ISOSAEReserved |
linkRecord:
该record包含了需要转换的指定特定参数,其格式在单个数据链路层诊断规范(UDSonXYZ)中指定
3 Positive response message
以下是$87服务的正响应消息定义:

linkControlType:
该参数是$87服务的请求消息中的子功能参数的0-6位计算值回显
4 Supported NRC
以下是$87服务支持的NRC:

5 Message flow example1
以下消息流展示了如何通过$87服务设置ECU切换到预定义波特率PC baudrate 115200 kBit/s。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例(验证是否支持):

诊断正响应消息示例(验证是否支持):

诊断请求消息示例(请求切换):

6 Message flow example2
以下消息流展示了如何通过$87服务设置ECU切换到指定特定波特率150kBit/s。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例(验证是否支持):

诊断正响应消息示例(验证是否支持):

诊断请求消息示例(请求切换):

7 Message flow example3
以下消息流展示了如何通过$87服务设置ECU的FlexRay网络通信周期切换到优化的车辆网络刷写模式设置。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例(验证是否支持):

诊断正响应消息示例(验证是否支持):

诊断请求消息示例(请求切换):

$23 ReadMemoryByAddress
1 Service description
$23 ReadMemoryByAddress服务允许client向ECU请求内存数据通过内存起始地址和要读取的内存数据大小。
$23服务请求报文中包含三个参数,其分别是addressAndLengthFormatIdentifier、memoryAddress和memorySize。其中,addressAndLengthFormatIdentifier为地址长度标识符,其用于指示内存地址参数(memoryAddress)和内存大小参数(memorySize)的字节数。memoryAddress参数用于指示要读取的内存起始地址,memorySize参数用于指示要读取的内存数据大小。
可以使用固定的addressAndLengthFormatIdentifier参数格式,若memoryAddress参数或memorySize参数中高地址范围未使用到,则可以用0x00去填充。
ECU通过$23服务肯定响应报文发送读取到的内存数据,数据格式由车辆制造商来定义。若ECU支持,读取到的内存数据可以包括模拟输入和输出信号,数字输入和输出信号,内部数据和系统状态信息。
2 Request message
以下是$23服务的请求消息定义:

addressAndLengthFormatIdentifier:
此参数是一个单字节值,每个半字节分别编码:
- bit 7 – 4:
memorySize参数的长度占多少字节 - bit 3 – 0:
memoryAddress参数的长度占多少字节
memoryAddress:
此参数用于标识预读取内存数据的起始地址
memorySize:
此参数用于标识预读取内存数据的数据大小
3 Positive response message
以下是$23服务的正响应消息定义:

dataRecord:
该record是$23服务肯定响应报文中提供给client请求的ECU内存数据
4 Supported NRC
以下是$23服务支持的NRC:


5 Message flow example1
以下消息流展示了如何通过$23服务向ECU请求读取259个数据字节从地址0x20481392处。
诊断请求消息示例:

诊断正响应消息示例:

6 Message flow example2
以下消息流展示了如何通过$23服务向ECU请求读取5个数据字节从地址0x4813处。
诊断请求消息示例:

诊断正响应消息示例:

7 Message flow example3
以下消息流展示了如何通过$23服务向ECU请求从外部RAM读取3个数据字节从地址0x204813处。
诊断请求消息示例:

诊断正响应消息示例:

$24 ReadScalingDataByIdentifier
1 Service description
$24 ReadScalingDataByIdentifier服务允许client通过数据标识符(dataIdentifier)向ECU请求缩写数据记录信息。
$24服务的请求消息包含一个dataIdentifier(即DID),其用于标识ECU中的数据记录。不同数据记录的格式和定义应由车辆制造商或系统供应商规范,并可能包括模拟输入和输出信号,数字输入和输出信号,内部数据和系统状态信息。
一旦收到$24服务的请求,ECU应读取由DID指定的缩写数据信息,并在$24服务的肯定应答报文中去传输这些缩写信息值。
2 Request message
以下是$24服务的请求消息定义:

DataIdentifier:
该参数表示client请求ECU读取缩写数据记录信息的标识符,即DID
3 Positive response message
以下是$24服务的正响应消息定义:

dataIdentifier:
该参数是$24服务的请求报文中的DID回显
scalingByte:
该参数是$24服务的肯定响应报文中包含的对应请求DID的ECU中的缩写数据记录值,其占一个字节,由高位和低位半字节组成。scalingByte参数的高位半字节定义了用于表示DID的数据类型,低位半字节定义了在数据流中用于表示参数的字节数。
scalingByteExtension:
当scalingBytes参数的高字节被编码指示为formula、unit/format或bitmappedReportedWithOutMask时,该参数用于提供更多的额外信息
4 Supported NRC
以下是$24服务支持的NRC:

5 Message flow example1
以下消息流展示了如何通过$24服务向ECU读取DID 0xF190的缩写信息,其包含了17个字符的VIN码信息。
诊断请求消息示例:

诊断正响应消息示例:

6 Message flow example2
以下消息流展示了如何通过$24服务向ECU读取DID 0x0105 (车辆速度)的缩写信息,并利用公式换算出数据变量。
诊断请求消息示例:

诊断正响应消息示例:
车辆速度数据变量采用下式计算: Vehicle Speed = (0.75 * x + 30) km/h. 其中“x”是存储在ECU中的实际数据,由DID 0x0105标识。
7 Message flow example3
以下消息流展示了如何通过$24服务向ECU读取DID 0x0967的有效掩码(支持的位)。
DID 0x0967的定义如下表所示:

诊断请求消息示例:

诊断正响应消息示例:

因此,通过上面ECU的正响应可知DID 0x0967支持的位(即包含信息的位)是第一个字节的位1和位0,以及第二个字节的位6、位1和位0。
$2A ReadDataByPeriodicIdentifier
1 Service description
$2A ReadDataByPeriodicIdentifier服务允许client通过周期数据标识符(periodicDataIdentifiers)向ECU请求周期性的传输数据记录值。
关键点:
$2A服务的请求报文可包含一个或多个periodic DID,其大小占一字节。- 在
0xF200 - 0xF2FF范围内的DID被用于$2A服务,此类DID高字节是固定的0xF2,低字节是periodic DID。 - 当
ECU收到子功能不为stopSending的$2A服务请求报文后,应检查执行诊断服务的条件是否满足。 - 一个
periodic DID只支持单一的transmissionMode参数。在收到$2A服务请求报文要求给同一个periodic DID设置不同的周期时,ECU应执行对transmissionMode参数的修改。按车辆制造商的要求,一个ECU可以支持不同的periodic DID对应多个周期。 - 发送初始的肯定响应报文之后,
ECU应周期性的去访问由周期数据标识符(periodic DID)指定的数据记录,并将值作为响应报文传输。周期性的响应报文会包含periodic DID和periodic DID值,但不包含肯定响应的SID。 - 当
ECU收到子功能为stopSending的$2A服务请求报文后,ECU应停止周期性传输请求报文中所包含的periodic DID,且其肯定响应应仅包含SID。若请求报文中没有指定特定的periodic DID,则应停止周期性传输所有periodic DID。
2 Request message
以下是$2A服务的请求消息定义:

transmissionMode:
该参数用于指示ECU请求periodic DID的传输速率,详细定义见下表:
| ByteValue | Description |
|---|---|
| 0x00 | ISOSAEReserved |
| 0x01 | sendAtSlowRate 此参数指示ECU以慢速周期请求periodic DID并发送响应。slow rate由车辆制造商在ECU中预定义。 |
| 0x02 | sendAtMediumRate 此参数指示ECU以中速周期请求periodic DID并发送响应。medium rate由车辆制造商在ECU中预定义。 |
| 0x03 | sendAtFastRate 此参数指示ECU以快速周期请求periodic DID并发送响应。fast rate由车辆制造商在ECU中预定义。 |
| 0x04 | stopSending 此参数指示ECU停止周期性的请求periodic DID并发送响应。 |
| 0x05 – 0xFF | ISOSAEReserved |
periodicDataIdentifier:
该参数用于指示client向ECU请求的periodic DID,单个请求报文中可以包含多个periodic DID。
3 Positive response message
以下是$2A服务的正响应消息定义(初始):

以下是$2A服务的正响应消息定义(周期性):

periodicDataIdentifier:
$2A服务请求报文中的periodic DID
dataRecord:
对应periodic DID的值
4 Supported NRC
以下是$2A服务支持的NRC:

5 Message flow example
以下消息流展示了如何通过$2A服务向ECU请求以中速周期读取periodic DID 0xE3和periodic DID 0x24的值,并在一段时间后,请求停止读取periodic DID 0xE3。
诊断请求消息示例(开始):

诊断正响应消息示例(初始):

诊断正响应消息示例(周期性):


诊断请求消息示例(停止):

诊断正响应消息示例:

$2C DynamicallyDefineDataIdentifier
1 Service description
$2C DynamicallyDefineDataIdentifier服务允许client在ECU动态地定义一个数据标识符(DID),使得client可以在之后的一段时间内,通过$22 ReadDataByIdentifier服务获取该DID的值。
$2C服务用于给client提供将一个或多个数据元素分组到一个数据超集的能力,该超集可以通过$22或$2A服务请求。要分组的数据元素可以参考以下方式:
- 源
DID,DID值起始位和DID值长度 - 内存地址和内存长度
- 以上两种方式的组合,可以使用多个请求来定义单个动态
DID
关键点:
- 在处理诊断应用程序的临时数据需求,且这些数据需求超出了通过静态
DID可以读取的信息时,使用该服务可具有较大的灵活性。 - 该服务可以避免频繁的请求/响应诊断任务,从而降低带宽使用率。
- 动态
DID的定义可以通过单个$2C服务或多个$2C服务请求报文完成。 - 通过
$2C服务,可以清除当前定义的动态DID,亦可以实现动态DID的重新定义。 - 当使用多个
$2C服务来定义单个动态DID时,若ECU在后续请求此动态DID时,检测到最大字节数超限,则ECU应保留该DID之前的定义。 - 尽管
$2C服务不禁止client用一个动态DID去定义另外一个动态DID,但标准不建议此行为,因为删除被引用的动态DID可能会导致数据一致性问题。 - 当用
$2C服务请求现有定义的动态DID时,若指定的DID在ECU支持的有效动态DID范围内,则ECU应对清除动态DID的请求报文作出肯定响应。 ECU应保持动态DID的定义,直到其被$2C服务清除,或者达到车辆制造商指定的清除条件,例如会话切换或ECU下电。
2 Request message
以下是$2C服务的请求消息定义:
- sub-function = defineByIdentifier

- sub-function = defineByMemoryAddress

- sub-function = clearDynamicallyDefinedDataIdentifier

definitionType:
其是$2C服务的sub-function参数,用于指示通过哪种方式定义动态DID或清除动态DID。下表详细介绍了$2C服务的子功能参数定义(子功能参数值不包含suppressPosRspMsgIndicationBit (bit 7))。
| definitionType | Description |
|---|---|
| 00 | ISOSAEReserved |
| 01 | defineByIdentifier 该参数值用于指示通过引用DID来定义动态DID |
| 02 | defineByMemoryAddress 该参数值用于指示通过引用内存地址来定义动态DID |
| 03 | clearDynamicallyDefinedDataIdentifier 该参数值用于指示清除指定的动态DID。需要注意的是,即使请求的指定动态DID不存在,ECU也需要向client做出肯定相应。若在请求清除指定动态DID时,该DID正在处于诊断中,则应先停止该动态DID的诊断服务,然后清除 |
| 04-7F | ISOSAEReserved |
dynamicallyDefinedDataIdentifier:
该参数用于指示要定义的动态DID。当其被$22服务引用时,其被视作DID,当其被$2A服务引用时,其被视作periodic DID。
sourceDataIdentifier:
此参数只有在子功能参数definitionType = defineByIdentifier时才能使用,其指定了包含在动态DID中定义的DID信息。
positionInSourceDataRecord:
此参数只有在子功能参数definitionType = defineByIdentifier时才能使用。此单字节参数指定了包含在动态DID值中对应的DID值的起始位。
addressAndLengthFormatIdentifier:
此参数是一个单字节值,每个半字节分别编码:
- bit 7 – 4:
memorySize参数的长度占多少字节 - bit 3 – 0:
memoryAddress参数的长度占多少字节
memoryAddress:
此参数只有在子功能参数definitionType = defineByMemoryAddress时才能使用,其指定了包含在动态DID中定义的内存地址信息。
memorySize:
在子功能参数definitionType = defineByIdentifier时,此参数大小为一个字节,用于指定包含在动态DID值中对应的DID值的总字节数。
在子功能参数definitionType = defineByMemoryAddress时,此参数大小由addressAndLengthFormatIdentifier参数的高半字节位定义,用于指定包含在动态DID中定义的内存地址数据总字节数。
3 Positive response message
以下是$2C服务的正响应消息定义:

definitionType:
该参数是$2C服务的请求报文中的子功能参数definitionType回显
dynamicallyDefinedDataIdentifier:
该参数是$2C服务的请求报文中的dynamicallyDefinedDataIdentifier参数回显
4 Supported NRC
以下是$2C服务支持的NRC:

5 Message flow example1
以下消息流展示了如何通过$2C服务定义动态DID 0xF301,其包含了三个DID 0x1234 0x5678 0x9ABC。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例:

诊断正响应消息示例:

6 Message flow example2
以下消息流展示了如何通过$2C服务定义动态DID 0xF302,其包含了DID 0x010A的多个数据块和DID 0x050B。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例:

诊断正响应消息示例:

诊断请求消息示例(读取DID 0xF302):

诊断正响应消息示例(读取DID 0xF302):

7 Message flow example3
以下消息流展示了如何通过$2C服务定义动态DID 0xF302,其包含了三块内存地址数据:0x21091969 0x2109196B 0x13101995。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例:


诊断正响应消息示例:

8 Message flow example4
以下消息流展示了如何通过$2C服务清除动态DID 0xF303。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例:

诊断正响应消息示例:

9 Message flow example5
以下消息流展示了如何通过$2C服务的两种不同定义方式共同定义动态DID 0xF301。client通过设置诊断请求消息的子功能参数的第7位suppressPosRspMsgIndicationBit为FALSE以获得诊断正响应消息。
诊断请求消息示例(defineByIdentifier):


诊断正响应消息示例:

诊断请求消息示例(defineByMemoryAddress):

诊断正响应消息示例:

诊断请求消息示例(defineByIdentifier):

诊断正响应消息示例:

诊断请求消息示例(读取DID 0xF301):

诊断正响应消息示例(读取DID 0xF301):

$3D WriteMemoryByAddress
1 Service description
$3D WriteMemoryByAddress服务允许client向ECU写入数据到指定的一个或多个连续的内存位置。
$3D服务请求报文用于请求ECU将dataRecord参数指定的数据信息写入由memoryAddress参数和memorySize参数指定的内存位置中。内存地址参数(memoryAddress)和内存大小参数(memorySize)的字节数分别由地址长度标识符参数(addressAndLengthFormatIdentifier)的低半字节和高半字节指定。可以使用固定的addressAndLengthFormatIdentifier参数格式,若memoryAddress参数或memorySize参数中高地址范围未使用到,则可以用0x00去填充。
要写入的数据信息格式和定义由车辆制造商规定,其可以是保密数据,也可以是非保密数据。以下情况可能会用到该服务:
- 清除
NVM - 改变标定值
2 Request message
以下是$3D服务的请求消息定义:

addressAndLengthFormatIdentifier:
此参数是一个单字节值,每个半字节分别编码:
- bit 7 – 4:
memorySize参数的长度占多少字节 - bit 3 – 0:
memoryAddress参数的长度占多少字节
memoryAddress:
此参数用于标识ECU要写入数据的内存起始地址
memorySize:
此参数用于标识ECU要写入数据的长度
dataRecord:
此参数用于标识ECU要写入的数据
3 Positive response message
以下是$3D服务的正响应消息定义:

addressAndLengthFormatIdentifier:
$3D服务请求报文中的addressAndLengthFormatIdentifier参数回显
memoryAddress:
$3D服务请求报文中的memoryAddress参数回显
memorySize:
$3D服务请求报文中的memorySize参数回显
4 Supported NRC
以下是$3D服务支持的NRC:

5 Message flow example1
以下消息流展示了如何通过$3D服务向ECU指定地址写入两字节的值。
诊断请求消息示例:

诊断正响应消息示例:

6 Message flow example2
以下消息流展示了如何通过$3D服务向ECU指定地址写入三字节的值。
诊断请求消息示例:

诊断正响应消息示例:

7 Message flow example3
以下消息流展示了如何通过$3D服务向ECU指定地址写入四字节的值。
诊断请求消息示例:

诊断正响应消息示例:

$19 ReadDTCInformation
1 Service description
$19 ReadDTCInformation服务是UDS协议中的重中之重,其在ISO 14229中介绍的篇幅长达63页,通信举例达到18个。可以说,没有$19服务,就没有完整的UDS。
$19服务允许client读取ECU中存储的DTC信息状态。除非特定子功能另有要求,否则ECU应返回与排放有关和非排放相关的所有DTC。该诊断服务允许client执行以下操作:
- 向
ECU检索与client定义的DTC状态掩码匹配的DTC数量 - 向
ECU检索与client定义的DTC状态掩码匹配的DTC列表 - 向
ECU检索与client定义的DTC状态掩码匹配的特定功能组的DTC列表 - 向
ECU检索所有具有permanent DTC状态的DTC - 向
ECU检索与client定义的DTC关联的DTCSnapshot数据(DTC快照数据,又称冻结帧)DTCSnapshot是与DTC相关的具体数据记录,其被存储于ECU内存中。一旦ECU检测到系统故障发生或有DTC出现时,会将车辆当前状态的一系列数据值快照(冻结)下来,快照哪些数据与具体的DTC有关,其指定的快照信息可以帮助技术人员快速分析问题。 - 向
ECU检索与client定义的DTC和DTC状态掩码组合相关的DTCExtendedData(DTC拓展数据)DTCExtendedData由与DTC相关的扩展状态信息组成,其包含在请求时已确定的DTC参数值,以及与DTC相关的动态数据,例如:DTC B1故障指示灯计数器,显示故障发生时OBD系统运行的时间量(发动机运行小时数)DTC发生次数,统计在一个驾驶循环中,DTC状态位Bit1 TestFailed被上报的次数DTC老化次数,统计自故障码最近一次失效以来的驾驶循环次数,排除未报出testPassed或者testFailed的驾驶循环DTC上次发生时间DTC测试失效testFailed汇报测试DTC上次上报testFailed或testPassed后的驾驶循环次数
- 向
ECU检索与client定义的严重等级DTC状态掩码匹配的DTC数量 - 向
ECU检索与client定义的严重等级DTC状态掩码匹配的DTC列表 - 向
ECU检索与client定义的严重等级DTC信息 - 向
ECU检索其支持的所有DTC状态 - 向
ECU检索其第一个失效的DTC - 向
ECU检索其最近一个失效的DTC - 向
ECU检索其第一个确认的DTC - 向
ECU检索其最近一个确认的DTC - ……
2 Request message
以下是$19服务的请求消息定义,不同的子功能的请求消息定义可能不一致:
| 字节序 | 参数 | 约定 | 字节值 |
|---|---|---|---|
| #1 | ReadDTCInformation Request SID | M | 0x19 |
| #2 | sub-function = [ reportType = reportNumberOfDTCByStatusMask, reportDTCByStatusMask, reportMirrorMemoryDTCByStatusMask, reportNumberOfMirrorMemoryDTCByStatusMask reportNumberOfEmissionsOBDDTCByStatusMask reportEmissionsOBDDTCByStatusMask ] | M | 0x01 0x02 0x0F 0x11 0x12 0x13 |
| #3 | DTCStatusMask | M |
19服务是一套诊断服务中的重中之重。协议中篇幅长达63页,通信举例达到了18个。可以说没有19服务,就没有完整的UDS。
DTC(diagnostic trouble code):如果系统检测到了一个错误,它将存储为DTC。DTC可表现为:一个显而易见的故障;通讯信号的丢失(不会使故障灯亮起);排放相关的故障;安全相关的错误等。DTC可以揭示错误的位置和错误类型。通常DTC占用3个字节,OBD II占用两个字节。图中FTB为Fault Type Byte。

故障码包括四个大类,分别是PCBU,P是powertrain动力系统,C是Chassis底盘,B是Body车身,U是network通信系统。一个DTC信息占用4个字节。最后一个字节是DTC的状态。前两个字节是我们熟知的类似0047的故障码。第一个字节在乘用车中,前两个bit代表P/C/B/U(动力/底盘/车身/网络)中的一个,之后六个bit是数字,合在一起的样子形如“C01”。第一个字节的前2个bit中,用00/01/10/11分别表示P/C/B/U。
例:U31 23 45这个故障码,它的状态是Test failed叠加Confirmed,那么DTC信息这四个字节就应该是0xF1(二进制11110001),0x23,0x45,0x09

一个DTC除了它自己的3个字节,还有一个字节专门用于表达DTC的状态,这个字节我们叫它DTC状态掩码。这个状态字节每个位的含义下面列举出来。注意,在实际项目中,并不是所有的DTC状态都是支持的。默认值0x50。

$19拥有28个子服务(Sub-Function)。常用的子服务有:
01 (读取符合掩码条件的DTC数量)(必须支持),后面的参数是DTC状态掩码,若为01表示我想读当前故障,若为08表示我想读历史故障,若为09表示当前故障和历史故障都想读。
在肯定回复时,组合应该是59(19+40) – 01 (子功能) – 09 (本ECU所支持的掩码条件)-01 DTC的格式(ISO14229-1为01) – 00 01 (目前满足条件的DTC有一个)
sub-function = 0x01用于读取符合特定条件的DTC数量,此时parameter为一个byte的Mask,用于与DTC的Status进行“与”运算,而ECU返回的则是”与”运算之后结果不为0的DTC的数量。DTC的Status用一个byte表示,其中的8个bit分别代表DTC的不同状态,比如,bit 0 表示这个DTC是active的还是passive的,bit 4表示这个DTC是否已经被confirm了,如果DTC的状态是confirm,则说明该DTC已经被ECU存储下来了。
比如:19 01 08这个命令的用途,就是读取所有状态为confirm的DTC的数量。
02(读取符合掩码条件的DTC列表及其状态)(必须支持),后面的参数是DTC状态掩码,解读同上。
在肯定回复是,59 – 02(子功能)- 09(本ECU所支持的掩码条件) – XX XX XX ( DTC,车厂定义 ) – 01 (这个故障码怎么了,01表示当前故障)
sub-function = 0x02用于读取符合特定条件的DTC列表,此时parameter仍然为一个byte的Mask,用于与DTC的Status进行“与”运算,而ECU返回的则是”与”运算之后结果不为0的DTC列表。
比如19 02 01这个命令的用途,就是读取所有状态为active的DTC的数量。此时ECU返回的格式应该是59 02 01 XX XX XX 01 YY YY YY 09……。返回的DTC列表中的每个条目为4个字节,前三个字节用于标识DTC,比如 XX XX XX,最后一个字节用于标识DTC状态,比如01,表示DTC是active的,09表示DTC是active且confirm的。
04(读取快照信息)
也叫冻结帧。
06(读取扩展信息)
sub-function = 0x06用于读取某个DTC及其相关的环境数据,此时parameter为4个byte,前三个byte用于标识我们要读取的DTC,第四个byte用于标识要读取的环境数据的范围,UDS规定使用FF来表示读取所有的环境数据,各厂家可以要根据自己的需求定义其他的值来代表要读取的环境数据的范围。环境数据包括DTC状态,优先级,发生次数,老化计数器,时间戳,里程等,厂家还可以根据自己的需求定义一些此DTC产生时的测量数据。
比如 19 06 XX XX XX FF就表示读取 XX XX XX这个DTC的所有环境数据,ECU的返回值应该是59 06 XX XX XX AA BB CC DD…..,其中AA BB CC DD…代表的就是XX XX XX这个DTC产生时所一起存储的环境数据。
0A(读取ECU支持的所有DTC列表及其状态)(必须支持)
这个就不必发DTC状态掩码了。所有支持的DTC列表及其状态都会打印出来。
0E
sub-function = 0x0E时,不需要parameter。0x0E表示,要求ECU上报最近的一条被置为confirm的DTC。在0x86服务,sub-function = 0x0E的19服务通常被作为参数传递给86指令,要求ECU在发生DTC存储的时候进行自动上报,即19 0E这两个字节的指令被嵌入到86服务的命令中。这条命令在开发阶段会用到,比如验证某个故障路径是否生效。
$2F InputOutputControlbyIdentifier
该服务可以通过DID(数据标识符)来进行输入信号的替换和控制零部件负载输出。这是一个用在产线上较多的服务。该报文的请求至少由4个字节组成。第一个字节是2F,第二第三字节是DID,其中第二字节是高位。第四字节是input Output Control Parameter(并不算一个子功能),可以看做IO控制类型。
IO控制类型分为4类,
00是控制权还给ECU,Return Control To ECU。
01是复位为默认值,Reset to Default。
02是冻结当前的状态,Freeze Current State。
03是短暂接管控制权,Short Term Adjustment。
若控制类型是00-02这三种,请求报文是4个字节。
若控制类型是03,请求报文的第五字节是控制代码,可以是数字量,比如01是开,00是关;也可以是模拟量,比如空调风门的开度。

2F服务,黄色区域为2个字节的DID
上面这个图可以理解为,关闭开关,之后打开开关,之后控制权还给ECU,之后想复位回默认值,但是发现ECU不支持。这里NRC用0x22是否准确?
例:使用2F控制Air Inlet Door Position (进气口门位置),用标识符0x9B00来标识进气口门的位置。Air Inlet Door Position [%] = decimal(Hex) * 1 [%] ,即用一个百分比来表示这个位置。
step1:
tester 发送22 9B 00读取当前进气口门的位置
ECU返回62 9B 00 0A , 0x0A = 10(dec),表示当前位置是10%
step2:
tester 发送2F 9B 00 03 3C ,表示要将进气口门的位置调整到60%,0x3C = 60(dec)
ECU返回6F 9B 00 03 0C,表示接受控制,当前进气口门的位置为12%。因为ECU收到请求后是立刻响应的,而门的位置调节需要时间,所以还没有达到60%。
step3:
过一段时间后tester 发送22 9B 00读取当前进气口门的位置
ECU返回62 9B 00 3C , 0x3C = 60(dec),表示当前位置已经到了60%
step4:
tester 发送2F 9B 00 00,将控制权交还给ECU
ECU返回6F 9B 00 00 3A,表示接受请求,当前位置为58%
step5:
tester 发送2F 9B 00 02,冻结9B 00这个ID所代表的进气口门位置这个状态
ECU返回6F 9B 00 02 32,表示接受请求,当前位置保持在50%
$31 RoutineControl
31服务是调用ECU内置的一些操作序列的接口,这个服务的应用很灵活,因为厂家可以根据自己的需要为ECU定义各种各样的内部操作,而要执行这些操作只需要调用31服务就好了。典型的用途包括检查边界条件、清除闪存、对数据进行较验、对软硬件依赖性进行校验等,甚至有需要的话可以进行恢复出厂设置的操作,还有很多与ECU自身逻辑功能相关的操作也可以定义。

RID:与DID一样是UDS指令中的一种类型。DID用于向ECU请求某些信息,数据,RID用于向ECU请求执行某些程序。 routine即例程,所谓例程,就是ECU中的一个函数或一段代码,所以又被称为例程程序。例程控制服务(0x31)就是客户端利用诊断仪向ECU发送诊断命令来开始或停止一段程序的执行,还可以请求例程执行的结果。
- SID
- sub-function,用于标识要执行什么动作,启动(0x01)、停止(0x02)、查询结果(0x03)?
- routineIdentifier,用于标识要执行的routine
- routineControlOptionRecord,这是一个可选参数,用于标识routine执行时所需要的参数,由各家自定义它的内容
举个例子,假设用0x0809这个ID来代表检查ECU是否满足软件刷写条件(比如车速、转速为0,KL15接通等)的routine。
tester发送31 01 08 09来启动0x0809这个routine
如果所有条件都满足,则ECU返回71 01 08 09作为echo即可,如果条件不满足,则ECU返回71 01 08 09 XX YY ZZ,后边的XX YY ZZ则表明哪些条件不满足,具体的内容就由厂家自己定义了。
$34 RequestDownload
从成本等角度考虑,汽车ECU中用于缓存诊断服务数据的buffer大小有限,所以当我们需要读取或写入超过buffer大小的数据时,就无法简单地使用2E和22服务了,UDS据此定义了几个将大块数据写入或读出的服务,即数据下载和上传。
下图是数据下载的简略过程,用到了34,36,37这三个服务,如果是上传的话,34服务被35服务替换,数据传输方向变一下,就可以了。Tester向ECU刷写数据的大概过程:

0x34服务用于启动下载传输,作用是告知ECU准备接受数据,ECU则通过0x74 response告诉诊断仪自己是否允许传输,以及自己的接受能力是多大。

0x34服务的请求格式包括5个部分
第一部分:1个byte的SID
第二部分:1个byte的dataFormatIdentifier,这里面标识了数据格式相关的信息,比如数据是否有压缩,是否有加密,用的什么算法加密等,应该由主机厂与供应商约定好,用哪个bit来表示压缩、加密等信息。
第三部分:1个字节的addressAndLengthFormatIdentifier,用于指示后面两个部分所占用的字节,高4bit表示memorySize所占的字节长度,低4bit表示memoryAddress
所占的字节长度。在这个例子中我将这两个值分别设置为n和m。
第四部分:m个字节的memoryAddress,由addressAndLengthFormatIdentifier中的低4bit指示。含义是要写入数据在ECU中的逻辑地址。
第五部分:n个字节的memorySize,由addressAndLengthFormatIdentifier中的高4bit指示。含义是要写入数据的字节数。
ECU收到请求之后,如果允许传输的话,会给出如下response

第一部分:1个byte的 Response SID
第二部分:1个byte的dataFormatIdentifier作为echo
第三部分:maxNumberOfBlockLength,长度不定,表示可以通过0x36服务一次传输的最大数据量。
$35 RequestUpload
Tester向ECU请求上传数据
$36 TransferData
Tester向ECU传数据(下载)或ECU向Tester传数据(上传)
如果34服务得到了正确响应,tester就要启动数据传输过程了,使用的就是36服务。36服务的格式如下。

第一部分:1个byte的 SID
第二部分:1个byte的blockSequenceCounter,标识当前传输的是第几个数据块,或者简单地说就是第几次调用36服务。
第三部分:transferRequestParameterRecord,传输的数据。第几次传输数据量的上限就是34服务响应中的maxNumberOfBlockLength。
举例:如果ECU告知tester,maxNumberOfBlockLength = 20,也就是说tester每次通过36服务只能发送最多20个字节,其中还包括了SID和blockSequenceCounter,所以实际上每次可传的数据信息只有18个字节。如果tester要传的数据为50个字节,则需要传输三次,每次分别传输18,18,14个字节,即调用3次36服务。
36的响应很简单,就是一个字节的Response SID再加一个字节的blockSequenceCounter作为echo。
$37 RequestTransferExit
37服务用于退出上传下载,如果之前的34和36服务都顺利执行完成,那么37服务就可以得到ECU的positive response。
格式很简单,请求就是37,正确响应就是77,都是一个字节。
如果前面的36服务没有执行完成,以我前面举的例子来说,比如这个数据块有50个字节,但是tester只发了两次36服务传了36个字节,那么这次传输对于ECU来说是失败的,所以ECU应该给出0x7F 37 24,表示诊断序列执行有错误。
$38 RequestFileTransfer
传输文件的操作,可以用于代替上传下载的服务