网易首页 > 网易号 > 正文 申请入驻

UDS 0x3E 服务(Tester Present)详解及 C++ 代码示例

0
分享至


一、服务概述

在 UDS(ISO 14229-1)协议中,0x3E 服务(Tester Present)用于让诊断测试工具(Tester)告知 ECU:“我还在线,请不要自动切回默认会话状态”。
ECU 通常有一个会话超时定时器(S3 Server 定时器),如果在规定时间内未收到任何诊断请求,它会自动从非默认会话(如编程会话、扩展诊断会话)返回到默认会话(Default Session)。
0x3E 服务正是用来重置这个定时器,维持当前会话状态,防止因超时而丢失非默认会话中的功能(如解锁安全访问、写入数据等)。

简单来说:Tester 定期发送 0x3E 请求,ECU 收到后刷新会话保持计时器,从而保持在当前会话。

二、报文格式 2.1 请求报文

字节位置

参数名称

值(例)

0

SID

0x3E

服务标识符

1

SubFunction

0x00 或 0x80

子功能,决定 ECU 是否需要发送肯定响应


  • 子功能(SubFunction)

    • 0x00suppressResponse= true,ECU不应发送肯定响应。

    • 0x80suppressResponse= false,ECU必须发送肯定响应。

实际应用中,为了保证通信可靠性并确认 ECU 仍在线,通常使用 0x80(请求响应)。但很多简单实现也直接发送 3E 00,并不期待响应。ISO 14229-1 规定:若子功能为 0x00,ECU 不得发送任何肯定响应;若为 0x80,ECU 应回复 7E 80。

常见报文示例:

  • 3E 00—— 仅刷新定时器,ECU 不回复响应。

  • 3E 80—— 刷新定时器,并要求 ECU 回复肯定响应。

2.2 肯定响应报文

字节位置

参数名称

值(例)

0

SID

0x7E

肯定响应标识符(0x3E+0x40)

1

SubFunction

0x80

与请求中的子功能相同


  • 若请求为3E 80,则肯定响应为7E 80

  • 若请求为3E 00,ECU不会发送肯定响应。

2.3 否定响应

当 ECU 无法处理该请求时,返回否定响应(格式:7F SID NRC)。常见的否定响应码(NRC)包括:

NRC

含义

原因

0x12

子功能不支持

子功能参数不是 0x00 或 0x80

0x13

请求报文长度错误

报文长度不为 2 字节

0x22

条件不满足

当前会话不允许执行该服务

0x78

请求正确,但响应延迟

ECU 忙,稍后重新请求


三、使用场景

  • 诊断会话保持:当 ECU 处于扩展诊断会话(0x03)或编程会话(0x02)时,Tester 需每隔 ≤ S3_Server 时间(通常为 5 秒)发送一次 0x3E 服务,否则 ECU 会自动切回默认会话(0x01)。

  • 安全访问保持:解锁安全访问后,若长时间无活动,ECU 会重新锁定,此时可通过 0x3E 维持解锁状态。

  • 写入操作保护:在进行多帧写入(如 0x34/0x36 服务)过程中,可穿插 0x3E 防止会话超时导致写入中断。

四、C++ 代码示例

下面提供一个简单的 C++ 类UdsClient,封装了发送 Tester Present 请求(支持响应)的功能。
假设:底层已实现 CAN 通信接口(例如 Linux SocketCAN),提供了CanSend()CanReceive()函数。实际使用时需替换为真实的 CAN 驱动代码。

4.1 辅助函数定义(伪实现)

#include  

#include
#include
#include
#include

// 模拟 CAN 发送(实际应调用 SocketCAN 等接口)
bool CanSend(const std::vector& data, uint32_t can_id) {
std::cout << "[CAN TX] ID=0x" << std::hex << can_id << " Data: ";
for (auto byte : data) printf("%02X ", byte);
std::cout << std::dec << std::endl;
// 这里替换为真实的 write() 调用
return true;
}

// 模拟 CAN 接收(非阻塞,带超时)
bool CanReceive(std::vector& data, uint32_t& can_id, int timeout_ms) {
// 模拟接收数据(实际应从 socket 读取)
// 此示例中直接返回 false,演示超时场景
std::this_thread::sleep_for(std::chrono::milliseconds(timeout_ms));
return false; // 无数据
}
4.2 UdsClient 类实现

class UdsClient {
public:
UdsClient(uint32_t req_id, uint32_t resp_id)
: req_can_id_(req_id), resp_can_id_(resp_id) {}

// 发送 Tester Present 请求
// sub_func: 0x00(无响应) 或 0x80(期望响应)
// timeout_ms: 等待响应的超时时间(毫秒),仅当 sub_func==0x80 时有效
bool SendTesterPresent(uint8_t sub_func, int timeout_ms = 100) {
// 构造请求报文:2 字节
std::vector request = { 0x3E, sub_func };
if (!CanSend(request, req_can_id_)) {
std::cerr << "Send TesterPresent request failed" << std::endl;
return false;
}

// 如果不需要响应,直接返回成功
if (sub_func == 0x00) {
std::cout << "TesterPresent with suppressResponse, no ack expected." << std::endl;
return true;
}

// 等待肯定响应
std::vector response;
uint32_t rx_id;
if (!CanReceive(response, rx_id, timeout_ms)) {
std::cerr << "Timeout waiting for TesterPresent response" << std::endl;
return false;
}

// 检查 CAN ID 是否正确
if (rx_id != resp_can_id_) {
std::cerr << "Unexpected response CAN ID" << std::endl;
return false;
}

// 检查响应长度
if (response.size() < 2) {
std::cerr << "Response too short" << std::endl;
return false;
}

// 检查肯定响应 SID (0x7E)
if (response[0] == 0x7E && response[1] == sub_func) {
std::cout << "Received positive response: 7E " << std::hex << (int)sub_func << std::dec << std::endl;
return true;
}
// 检查否定响应 (0x7F)
else if (response[0] == 0x7F && response[1] == 0x3E) {
uint8_t nrc = response[2];
std::cerr << "Negative response, NRC = 0x" << std::hex << (int)nrc << std::dec << std::endl;
return false;
}
else {
std::cerr << "Unexpected response format" << std::endl;
return false;
}
}

private:
uint32_t req_can_id_; // 请求使用的 CAN ID(通常为 0x7DF 或物理寻址 ID)
uint32_t resp_can_id_; // 响应使用的 CAN ID(通常为 ECU 的物理响应 ID)
};
4.3 使用示例

int main() {
// 假设 ECU 物理请求 ID 为 0x701,响应 ID 为 0x702
UdsClient client(0x701, 0x702);

// 场景1:要求 ECU 回复肯定响应(推荐)
std::cout << "=== Send TesterPresent with response (subfunc=0x80) ===" << std::endl;
bool ok = client.SendTesterPresent(0x80, 200);
if (ok) {
std::cout << "ECU stays in current session." << std::endl;
} else {
std::cout << "Failed to refresh session timer." << std::endl;
}

// 场景2:不要求响应(仅刷新定时器)
std::cout << "\n=== Send TesterPresent without response (subfunc=0x00) ===" << std::endl;
ok = client.SendTesterPresent(0x00);
if (ok) {
std::cout << "TesterPresent sent (no response needed)." << std::endl;
}

// 模拟周期性发送(每 3 秒一次,假设会话超时为 5 秒)
std::cout << "\n=== Start periodic TesterPresent (every 3s) ===" << std::endl;
for (int i = 0; i < 5; ++i) {
std::this_thread::sleep_for(std::chrono::seconds(3));
if (!client.SendTesterPresent(0x80, 200)) {
std::cerr << "Periodic TesterPresent failed at iteration " << i << std::endl;
break;
}
}

return 0;
}
五、注意事项
  1. 发送周期:应小于 ECU 的 S3_Server 超时时间(通常为 5 秒)。建议周期为 2~3 秒,留有余量。

  2. 子功能选择

  • 如果诊断流程需要确认 ECU 仍然在线,使用0x80并等待响应。

  • 如果仅需保持会话且不希望增加总线负载,可使用0x00(无响应)。

会话切换影响:如果 ECU 已经返回默认会话(例如因超时),则 0x3E 服务依然可以执行,但不会自动切换回之前的会话。此时应重新请求需要的会话(如 0x10 服务)。

错误处理:若收到 NRC 0x78(响应延迟),Tester 应稍后重发请求(但注意不要过于频繁)。

CAN ID 设置:示例中使用了物理寻址(点对点)。也可使用功能寻址(如 0x7DF),但需注意 ECU 是否支持功能寻址响应。

六、总结

UDS 0x3E 服务(Tester Present)是一个简单但至关重要的诊断服务,用于维持 ECU 的非默认会话状态。其报文格式简洁(仅 2 字节),通过子功能控制是否需要响应。
在实际嵌入式开发中,正确实现该服务可以避免因会话超时导致的诊断流程中断。本文提供的 C++ 代码演示了如何在客户端侧封装该服务,并可根据需要集成到真实的诊断工具中。

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
欧盟27国抱团卡中国脖子,中方公告一出,法国空客的百亿大单悬了

欧盟27国抱团卡中国脖子,中方公告一出,法国空客的百亿大单悬了

今日搞笑分享
2026-05-28 00:07:38
央企会大批量疏解到雄安吗?知乎网友:有央企“雄安总部”只有边缘部门

央企会大批量疏解到雄安吗?知乎网友:有央企“雄安总部”只有边缘部门

六子吃凉粉
2026-05-27 17:19:22
工厂罢工情绪严重,公司鼓励员工离职,网友:再闹螺丝都没得打!

工厂罢工情绪严重,公司鼓励员工离职,网友:再闹螺丝都没得打!

灯锦年
2026-05-28 13:08:17
NBA票选历史第一人:科比得票率6.8%,詹姆斯排名暴涨

NBA票选历史第一人:科比得票率6.8%,詹姆斯排名暴涨

钱说体育
2026-05-28 12:45:04
71岁张国立喜讯刚至,43岁巨婴儿子惹新事

71岁张国立喜讯刚至,43岁巨婴儿子惹新事

梦在深巷qw
2026-05-28 09:28:02
10年前,在自家挖出鱼泉的李常权,靠卖鱼发家致富,如今怎么样了

10年前,在自家挖出鱼泉的李常权,靠卖鱼发家致富,如今怎么样了

萧竹轻语
2025-01-11 17:14:16
猪大肠被关注!研究发现:糖尿病患者常吃猪大肠,或有5种变化

猪大肠被关注!研究发现:糖尿病患者常吃猪大肠,或有5种变化

芹姐说生活
2026-05-01 14:34:43
大瓜!广发百亿基金经理遭实名举报,网友:张雪峰的话含金量上升

大瓜!广发百亿基金经理遭实名举报,网友:张雪峰的话含金量上升

火山詩话
2026-05-27 14:48:31
景甜代孕和我们理解的“借腹生子”完全不是一回事。

景甜代孕和我们理解的“借腹生子”完全不是一回事。

岁月有情1314
2026-05-25 16:18:34
中国工程院撤销张尧学院士称号

中国工程院撤销张尧学院士称号

界面新闻
2026-05-25 21:36:51
抗战时有干部不满意毛主席每天能有一个肉菜,陈云如何给他解释?

抗战时有干部不满意毛主席每天能有一个肉菜,陈云如何给他解释?

阿器谈史
2026-05-28 11:03:11
35死40伤!以色列发起斩首行动,美军连夜开火,普京:伊朗或上当

35死40伤!以色列发起斩首行动,美军连夜开火,普京:伊朗或上当

共工之锚
2026-05-28 12:20:29
欧协联+欧联杯已到手,阿森纳若夺欧冠,英超将称霸欧洲足坛

欧协联+欧联杯已到手,阿森纳若夺欧冠,英超将称霸欧洲足坛

呀古铜
2026-05-28 12:45:20
爱比胭脂薄!封潇潇死的那晚,楚嘉禾忙着用身体换“楚主任”头衔

爱比胭脂薄!封潇潇死的那晚,楚嘉禾忙着用身体换“楚主任”头衔

阿握聊事
2026-05-21 17:28:44
承诺“不限次数”,就该接住顾客的“天天来”

承诺“不限次数”,就该接住顾客的“天天来”

南风不及你温柔
2026-05-16 01:02:57
不击沉就是生窝囊气?荷兰军舰闯西沙根本不是孤狼行为

不击沉就是生窝囊气?荷兰军舰闯西沙根本不是孤狼行为

阿龙聊军事
2026-05-28 10:32:40
原版身材就是顶!伊芙体模亲自下场cos

原版身材就是顶!伊芙体模亲自下场cos

奶凶的小霸王
2026-05-26 15:47:03
4类肥皂被列入致癌黑名单,长期用或有致癌风险?告诉你真相

4类肥皂被列入致癌黑名单,长期用或有致癌风险?告诉你真相

叙说医疗健康
2026-05-28 10:00:24
在西藏遇到白色帐篷,为啥要躲着?老牧民直言:进去谁也帮不了你

在西藏遇到白色帐篷,为啥要躲着?老牧民直言:进去谁也帮不了你

抽象派大师
2026-05-07 00:28:27
《阿嬷》票房破10亿只是开始,吴京、沈腾、谢霆锋要掀起新高潮了

《阿嬷》票房破10亿只是开始,吴京、沈腾、谢霆锋要掀起新高潮了

皮皮电影
2026-05-27 14:00:19
2026-05-28 13:44:50
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
986文章数 348关注度
往期回顾 全部

科技要闻

台积电3纳米下半年涨价15% 明年或再涨10%

头条要闻

民进党发言人称受不了国台办 陈斌华回应时战术性喝水

头条要闻

民进党发言人称受不了国台办 陈斌华回应时战术性喝水

体育要闻

如果雷霆拼图是这水平 马刺确实打不过

娱乐要闻

曝大嫂冒充七七同学,林俊杰删掉合照

财经要闻

长鑫科技IPO过会,市值会到几万亿?

汽车要闻

限时补贴价9.28-10.98万 MG 4X正式上市

态度原创

本地
游戏
教育
家居
艺术

本地新闻

用剪纸的方式,打开江苏扬州

V社官宣掌机涨价1千6!黑心商人割韭菜还是心里苦?

教育要闻

五年级,不少人却无从下手,学会方法直接心算

家居要闻

蜂鸟餐椅 线面交错

艺术要闻

蚂蚁新总部封顶了!大圆环到底有啥魔力

无障碍浏览 进入关怀版