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

CAN 诊断浅谈:从协议到 C++ 实现与工具实践

0
分享至


车载诊断早已不是简单“读个故障码”那么简单。从产线下线检测、售后维修,到 ECU 刷写、功能标定,诊断贯穿了汽车电子的全生命周期。理解 CAN 诊断,核心在于理清传输层(ISO-TP)与应用层(UDS)的协作关系。下面从协议框架切入,给出可运行的 C++ 代码思路,并说明如何借助专业工具完成实际诊断任务。

一、CAN 诊断的协议栈:两层各司其职

CAN 总线单帧数据场最多 8 字节,而一条诊断请求或响应(例如带数据的正响应、故障码列表)动辄几十甚至上千字节。这就需要一个“中间人”来切分和重组数据。

ISO-TP(ISO 15765-2)正是这个中间人。它定义了四种帧类型:

帧类型

简称

作用

单帧

SF

数据长度 ≤ 7 字节时,一帧发完

首帧

FF

数据较长时,第一帧携带总长度与开头数据

连续帧

CF

后续携带剩余数据,带序列号防错序

流控帧

FC

接收方告诉发送方“继续发 / 暂停 / 缓冲满了”

UDS(ISO 14229-1)则定义在应用层,负责“说什么”。它规定了诊断服务的请求与响应格式,例如0x22读数据、0x2E写数据、0x19读故障码、0x27安全访问等。ISO-TP 负责搬运,UDS 负责语义。

诊断的典型交互是请求—响应模式:诊断仪(Tester)发送请求,ECU 要么回复正响应(SID+0x40),要么回复否定响应(0x7F+ 原SID + NRC 码)。

二、C++ 代码示例:从零封装一条 UDS 请求

直接用原生 CAN 驱动发 UDS 请求,需要自己处理 ISO-TP 的分帧、流控、超时。下面用伪代码风格展示核心逻辑,便于理解底层的“手工活”。

假设你使用 SocketCAN(Linux 下常见)或 PCAN 的 CAN 发送接口。

2.1 发送单帧请求(例如读 DID0xF190

#include  

#include
#include
#include

// 假设 sock 已初始化,CAN ID 为 0x7DF(功能寻址)或 0x7E0(物理寻址)
int send_uds_single_frame(int sock, canid_t tx_id, uint8_t sid, uint8_t did_high, uint8_t did_low) {
struct can_frame frame;
memset(&frame, 0, sizeof(frame));
frame.can_id = tx_id;
frame.can_dlc = 8;

// ISO-TP 单帧格式:高4位=0(单帧),低4位=数据长度(3字节)
frame.data[0] = 0x03; // SF, 长度为3
frame.data[1] = sid; // 服务ID,例如 0x22
frame.data[2] = did_high; // DID 高位
frame.data[3] = did_low; // DID 低位
// data[4..7] 为填充字节(通常 0xCC 或 0x00)
frame.data[4] = 0xCC;
frame.data[5] = 0xCC;
frame.data[6] = 0xCC;
frame.data[7] = 0xCC;

int nbytes = write(sock, &frame, sizeof(frame));
if (nbytes != sizeof(frame)) {
std::cerr << "发送失败" << std::endl;
return -1;
}
return 0;
}

调用方式:send_uds_single_frame(sock, 0x7E0, 0x22, 0xF1, 0x90)。

2.2 多帧接收的流控逻辑(简化示意)

当 ECU 返回的响应超过 7 字节时,会先发首帧(FF),此时 Tester 需要回一条流控帧(FC)告诉 ECU “继续发,每包间隔 X 毫秒”。

// 收到 ECU 的响应首帧后,发送流控帧
void send_flow_control(int sock, canid_t tx_id) {
struct can_frame fc;
memset(&fc, 0, sizeof(fc));
fc.can_id = tx_id;
fc.can_dlc = 8;

// FC 格式:高4位=3(流控),低4位=流状态(0=继续)
fc.data[0] = 0x30; // 0x3 表示 FC,0x0 表示 CTS(继续发送)
fc.data[1] = 0x00; // Block Size = 0(无限制)
fc.data[2] = 0x14; // STmin = 20ms(0x14 是 ISO-TP 时间参数编码)
// 后续填充
fc.data[3] = 0xAA;
fc.data[4] = 0xAA;
fc.data[5] = 0xAA;
fc.data[6] = 0xAA;
fc.data[7] = 0xAA;

write(sock, &fc, sizeof(fc));
}

ECU 收到 FC 后,就会用连续帧(CF)把剩余数据发完,Tester 再按序列号拼装即可。

三、实际开发中更推荐的做法:使用成熟的 UDS 库

手写 ISO-TP 容易在超时、序列号错误、NRC 处理上踩坑。实际项目中通常使用现成的库,例如PCAN-UDS API或开源 C++ 实现。

以 PCAN-UDS 发送一条“清除故障码”请求为例,API 封装了所有传输层细节:

TPUDSMsg request, response, requestConfirmation;
TPUDSStatus result;

// 配置网络地址信息
request.NETADDRINFO.SA = PUDS_ISO_15765_4_ADDR_TEST_EQUIPMENT; // 0xF1
request.NETADDRINFO.TA = PUDS_ISO_15765_4_ADDR_ECU_1; // 0x01
request.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
request.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;

// 发送 ClearDiagnosticInformation(0x14),清除所有 DTC
result = UDS_SvcClearDiagnosticInformation(PUDS_USBBUS1, &request, 0xFFFFFF);
if (result == PUDS_ERROR_OK) {
// 等待 ECU 响应,库内部自动处理流控和重组
result = UDS_WaitForService(PUDS_USBBUS1, &response, &request, &requestConfirmation);
}
// 检查 response 中是否为正响应 0x54

这样代码聚焦于业务逻辑(发什么服务、带什么参数),而不必纠缠于帧切分。

四、如何用 CAN 工具进行诊断:以 CANoe 为例

CANoe/CANalyzer 是行业主流诊断工具,其诊断功能围绕CDD 文件(CANdela Diagnostic Description)展开。

4.1 配置阶段

在Diagnostics / ISO-TP Configuration窗口中导入 CDD 文件。CDD 文件由 OEM 或 ECU 供应商提供,里面描述了该 ECU 支持哪些 UDS 服务、每个服务需要什么参数、DID 的含义、DTC 的定义等。

导入 CDD 后,CANoe 会自动弹出Fault Memory和Session Control窗口,前者用于读写 DTC,后者用于切换诊断会话(Default / Extended / Programming)和安全等级。

4.2 手动发送诊断请求

在Diagnostic Console窗口中,左侧会列出 CDD 中定义的所有服务。双击某个服务,右侧会生成请求报文,填写参数后点击发送,响应会实时显示。

如果 CDD 中没有某个服务,或者你需要发送“非正常”报文来测试 ECU 的 NRC 处理,可以使用窗口底部的手动输入框,直接填入十六进制诊断报文。

4.3 自动化测试

对于需要反复执行或批量执行的诊断序列(例如刷写前的会话切换、安全解锁、写 DID),CANoe 支持通过CAPL 脚本自动化。例如保持会话的0x3E服务,可以在配置中启用“Send Tester Present”,设置周期后由 CANoe 自动周期发送。

五、总结

CAN 诊断的骨架是清晰的:ISO-TP 负责拆包组包,UDS 负责服务语义。理解了这个分层,无论是手写代码还是用工具排查问题,都能找到切入点。

C++ 开发中,小规模验证可以自己封装 ISO-TP 单帧/多帧逻辑;产品级项目建议直接使用 PCAN-UDS、开源 UDS 库或 OEM 提供的诊断协议栈,把精力留给诊断序列的业务逻辑。工具侧,CANoe 搭配 CDD 文件是效率最高的方案,适合测试工程师进行交互式诊断和自动化脚本开发。

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

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.

相关推荐
热点推荐
知名医学院三大附属医院一把手换人,两个都是80后

知名医学院三大附属医院一把手换人,两个都是80后

金水路7号站
2026-09-28 11:49:52
去世仅2天,人民日报改了对刘欢的称呼,简短5个字释放出强烈信号

去世仅2天,人民日报改了对刘欢的称呼,简短5个字释放出强烈信号

爱写的樱桃
2026-09-27 20:23:14
1换7!神级大交易!火箭已经彻底傻眼

1换7!神级大交易!火箭已经彻底傻眼

篮球实战宝典
2026-09-27 20:36:49
中国选手刷新了亚运会尘封36年的纪录

中国选手刷新了亚运会尘封36年的纪录

极目新闻
2026-09-27 12:07:23
稳了,俄罗斯总统普京喊话中国了!

稳了,俄罗斯总统普京喊话中国了!

故事终将光明磊落
2026-09-27 10:45:17
张本智和暴跳如雷!输国乒不丢人,真正崩盘的原因,全在队友身上

张本智和暴跳如雷!输国乒不丢人,真正崩盘的原因,全在队友身上

烟雨洛神生
2026-09-28 02:46:20
圆桌|特朗普“放话”将与古巴达成协议,“委内瑞拉模式”在古巴行得通?

圆桌|特朗普“放话”将与古巴达成协议,“委内瑞拉模式”在古巴行得通?

澎湃新闻
2026-09-28 07:08:28
奥委会这下尴尬了:2036年奥运会,中国上海、成都、广州都没申办

奥委会这下尴尬了:2036年奥运会,中国上海、成都、广州都没申办

轻扬墨雨
2026-08-14 13:21:23
0-3惨败新西兰被喊下课!邵佳一,你拿什么跟安东尼奥比?

0-3惨败新西兰被喊下课!邵佳一,你拿什么跟安东尼奥比?

曹老师评球
2026-09-27 21:59:44
杜伦与活塞和解,拉锯战结束,名额已腾空

杜伦与活塞和解,拉锯战结束,名额已腾空

体育篮球弟
2026-09-28 05:48:24
A股:上午跳水到3812收长阴,种种迹象表明,A股C浪调整要开始了吗?

A股:上午跳水到3812收长阴,种种迹象表明,A股C浪调整要开始了吗?

趋势清风侠
2026-09-28 11:48:36
喝的中药大半是假货!药材全链条造假,千年中医被自己人毁掉

喝的中药大半是假货!药材全链条造假,千年中医被自己人毁掉

米果说识
2026-09-14 10:03:10
万万想不到,高举反华大旗的高市早苗,竟然把孙子送到中国留学!

万万想不到,高举反华大旗的高市早苗,竟然把孙子送到中国留学!

墨印斋
2026-06-06 14:41:27
他们是陈妤颉父母,都是浙大体育特长生,父亲国家一级运动员

他们是陈妤颉父母,都是浙大体育特长生,父亲国家一级运动员

娱说瑜悦
2026-09-27 22:41:01
女篮回国,宫鲁鸣下课?篮协发声,官宣决定,名记:全员先写总结

女篮回国,宫鲁鸣下课?篮协发声,官宣决定,名记:全员先写总结

喜欢体育的猫
2026-09-28 09:32:15
理想汽车抽奖送iPhone,“唯一中奖人”是罗永浩!此前刚发文炮轰苹果新款折叠屏,罗永浩最新回应:将以抽奖形式送网友

理想汽车抽奖送iPhone,“唯一中奖人”是罗永浩!此前刚发文炮轰苹果新款折叠屏,罗永浩最新回应:将以抽奖形式送网友

大风新闻
2026-09-27 18:14:18
疫苗女王终审无期!当年炫富儿媳多奢靡,如今91亿罚款追债上门

疫苗女王终审无期!当年炫富儿媳多奢靡,如今91亿罚款追债上门

爱看剧的阿峰
2026-09-27 06:20:44
原来他俩是亲兄弟,哥哥是全国冠军,弟弟是乒乓天才,都进北京队

原来他俩是亲兄弟,哥哥是全国冠军,弟弟是乒乓天才,都进北京队

深析古今
2026-07-24 16:35:43
金融圈吃瓜!顶级银行美女辞职,要出道当偶像了

金融圈吃瓜!顶级银行美女辞职,要出道当偶像了

金石随笔
2026-09-28 07:03:48
随着国足0-3新西兰,邵佳一迎执教第2败,以下5人基本无缘国家队

随着国足0-3新西兰,邵佳一迎执教第2败,以下5人基本无缘国家队

小火箭爱体育
2026-09-27 21:46:01
2026-09-28 14:07:00
新能源自动驾驶 incentive-icons
新能源自动驾驶
专注于半导体行业资讯
1015文章数 348关注度
往期回顾 全部

汽车要闻

神龙科技与Momenta达成全球战略合作 2027年起推新车

头条要闻

小孩姐一掷杀死比赛投哭日本奥运冠军 对方抱着国旗哭

头条要闻

小孩姐一掷杀死比赛投哭日本奥运冠军 对方抱着国旗哭

体育要闻

114项指控成立,曼城已经完蛋了吗?

娱乐要闻

好汉刘欢:一副好嗓子,一颗赤子心

财经要闻

标价298元核桃油, 实为大豆油冒充

科技要闻

智能体惹了多少祸,OpenAI自己没查清!

态度原创

教育
时尚
手机
健康
数码

教育要闻

一个家庭,父母越“尊重”孩子,孩子脾气越大……

女人过了三四十岁,一定要准备一件小西装,大方得体又显瘦

手机要闻

首批搭载第六代骁龙8超级至尊版!荣耀Magic9 Pro Max安兔兔跑分超552万

鼻子三角区的痘,千万别乱挤!

数码要闻

雷蛇推出Hello Kitty和朋友们联名键帽盲盒,包含5大IP形象

无障碍浏览 进入关怀版