无主之地2配置高吗|看真人裸体BBBBB|秋草莓丝瓜黄瓜榴莲色多多|真人強奷112分钟|精品一卡2卡3卡四卡新区|日本成人深夜苍井空|八十年代动画片

網(wǎng)易首頁 > 網(wǎng)易號 > 正文 申請入駐

UDS統(tǒng)一診斷服務(wù)詳解:核心機(jī)制、DoCAN傳輸與C++代碼實(shí)現(xiàn)

0
分享至


一、UDS 概述與定位 1.1 什么是UDS?

UDS(Unified Diagnostic Services)是ISO 14229定義的應(yīng)用層診斷協(xié)議,用于汽車電子控制單元(ECU)的故障讀取、數(shù)據(jù)通信、例程控制、軟件升級等。

1.2 UDS 與 OBD 的區(qū)別

項(xiàng)目

OBD

UDS

目的

排放相關(guān)強(qiáng)制診斷

全車ECU增強(qiáng)診斷

范圍

有限(發(fā)動機(jī)、排放)

所有ECU(BCM、GW、BMS等)

擴(kuò)展性

固定服務(wù)

支持自定義服務(wù)

網(wǎng)絡(luò)層

ISO 15765-4

ISO 15765-2(DoCAN)


1.3 DoCAN 協(xié)議棧

  • 應(yīng)用層:UDS(ISO 14229)

  • 網(wǎng)絡(luò)層:ISO 15765-2(多幀傳輸)

  • 數(shù)據(jù)鏈路層:CAN(ISO 11898)

二、核心通信機(jī)制 2.1 請求與響應(yīng)模型
  • 請求 :SID + SubFunction + 參數(shù)

  • 肯定響應(yīng) :SID + 0x40 + 參數(shù)

  • 否定響應(yīng) :0x7F + SID + NRC

示例:
  • 請求讀取DID 0xF19022 F1 90

  • 肯定響應(yīng): 62 F1 90 01 02 03

  • 否定響應(yīng): 7F 22 13 (無效長度)

三、C++ 實(shí)現(xiàn)示例(DoCAN + UDS 核心服務(wù)) 3.1 數(shù)據(jù)結(jié)構(gòu)定義

#include  
          
#include
#include
#include

using Byte = uint8_t;
using Bytes = std::vector ;

// UDS 服務(wù) ID(部分)
enum class UDS_SID : Byte {
DIAG_SESSION_CTRL = 0x10,
ECU_RESET = 0x11,
READ_DATA = 0x22,
WRITE_DATA = 0x2E,
SECURITY_ACCESS = 0x27,
TESTER_PRESENT = 0x3E,
ROUTINE_CTRL = 0x31,
READ_DTC = 0x19,
CLEAR_DTC = 0x14
};

// NRC
enum class NRC : Byte {
OK = 0x00,
GENERAL_REJECT = 0x10,
SERVICE_NOT_SUPPORTED = 0x11,
INVALID_FORMAT = 0x13,
CONDITIONS_NOT_CORRECT = 0x22,
SECURITY_ACCESS_DENIED = 0x33,
INVALID_KEY = 0x35
};
3.2 ISO 15765-2 網(wǎng)絡(luò)層簡版封裝

// 幀類型
enum class N_PCI_TYPE : Byte {
SINGLE = 0x00,
FIRST = 0x10,
CONSECUTIVE = 0x20,
FLOW_CTRL = 0x30
};

// 單幀/多幀處理(簡單示例)
class DoCANTransport {
public:
static Bytes packRequest(const Bytes& udsReq) {
if (udsReq.size() <= 7) {
// 單幀
Byte pci = static_cast (N_PCI_TYPE::SINGLE) | (Byte)udsReq.size();
Bytes frame = {pci};
frame.insert(frame.end(), udsReq.begin(), udsReq.end());
return frame;
} else {
// 簡化:實(shí)際需拆分為 FF/CF/FC,此處僅示意
std::cout << "[DoCAN] Multi-frame not fully implemented\n";
return {};
}
}

static Bytes unpackResponse(const Bytes& canFrame) {
if (canFrame.empty()) return {};
Byte pci = canFrame[0];
N_PCI_TYPE type = static_cast (pci & 0xF0);
if (type == N_PCI_TYPE::SINGLE) {
int len = pci & 0x0F;
return Bytes(canFrame.begin() + 1, canFrame.begin() + 1 + len);
}
// 實(shí)際需重組多幀
return {};
}
};
3.3 UDS 基礎(chǔ)處理類

class UDSHandler {
private:
std::map std ::function const Bytes&)>> handlers;
bool securityLocked = true ;

public :
UDSHandler() {
// 注冊服務(wù)
handlers[UDS_SID::READ_DATA] = [ this ]( const Bytes& req) { return handleReadData(req); };
handlers[UDS_SID::DIAG_SESSION_CTRL] = [ this ]( const Bytes& req) { return handleSessionCtrl(req); };
handlers[UDS_SID::TESTER_PRESENT] = [ this ]( const Bytes& req) { return handleTesterPresent(req); };
}

// 主處理入口
Bytes processRequest(const Bytes& udsReq) {
if (udsReq.empty()) return buildNegativeResponse( 0x00 , NRC::GENERAL_REJECT);
Byte sid = udsReq[ 0 ];
UDS_SID service = static_cast (sid);
if (handlers.find(service) == handlers.end()) {
return buildNegativeResponse(sid, NRC::SERVICE_NOT_SUPPORTED);
}
return handlers[service](udsReq);
}

private :
// 否定響應(yīng)
Bytes buildNegativeResponse(Byte sid, NRC nrc) {
return { 0x7F , sid, static_cast (nrc)};
}

// 肯定響應(yīng)
Bytes buildPositiveResponse(Byte sid, const Bytes& data = {}) {
Bytes resp;
resp.push_back(sid + 0x40 );
resp.insert(resp.end(), data.begin(), data.end());
return resp;
}

// 22 讀數(shù)據(jù)
Bytes handleReadData(const Bytes& req) {
if (req.size() < 3 ) return buildNegativeResponse( 0x22 , NRC::INVALID_FORMAT);
Byte didHigh = req[ 1 ];
Byte didLow = req[ 2 ];
uint16_t did = (didHigh << 8 ) | didLow;

// 模擬數(shù)據(jù)字典
if (did == 0xF190 ) {
return buildPositiveResponse( 0x22 , { 0xF1 , 0x90 , 0x01 , 0x02 , 0x03 });
} else if (did == 0xF187 ) {
return buildPositiveResponse( 0x22 , { 0xF1 , 0x87 , 'V' , '1' , '.' , '0' });
}
return buildNegativeResponse( 0x22 , NRC::GENERAL_REJECT);
}

// 10 會話控制
Bytes handleSessionCtrl(const Bytes& req) {
if (req.size() < 2 ) return buildNegativeResponse( 0x10 , NRC::INVALID_FORMAT);
Byte subfunc = req[ 1 ];
// 抑制肯定響應(yīng)檢查(bit7 = 1 時(shí)不發(fā)響應(yīng))
bool suppressResp = (subfunc & 0x80 ) != 0 ;
Byte session = subfunc & 0x7F ;

std :: cout << "[UDS] Switch to session: " << std ::hex << ( int )session << std :: endl ;
if (!suppressResp) {
return buildPositiveResponse( 0x10 , {subfunc, 0x00 , 0x32 , 0x01 , 0xF4 }); // 仿真實(shí)例
}
return {}; // 無響應(yīng)
}

// 3E 待機(jī)握手
Bytes handleTesterPresent(const Bytes& req) {
bool suppress = (req.size() > 1 ) && ((req[ 1 ] & 0x80 ) != 0 );
if (!suppress) {
return buildPositiveResponse( 0x3E , {});
}
return {};
}
};
3.4 主程序示例(診斷請求模擬)

int main() {
UDSHandler uds;
DoCANTransport canLayer;

// 模擬發(fā)送:22 F1 90 讀取 DID 0xF190
Bytes udsReq = {0x22, 0xF1, 0x90};
Bytes canFrame = DoCANTransport::packRequest(udsReq);

std::cout << "Send CAN: ";
for (auto b : canFrame) printf("%02X ", b);
std::cout << std::endl;

// 模擬 ECU 收到 CAN 幀,解包得到 UDS 請求
Bytes receivedUdsReq = DoCANTransport::unpackResponse(canFrame);
Bytes udsResp = uds.processRequest(receivedUdsReq);

std::cout << "UDS Response: ";
for (auto b : udsResp) printf("%02X ", b);
std::cout << std::endl;

// 測試會話切換(抑制響應(yīng))
Bytes sessionReq = {0x10, 0x83}; // subfunc 0x83 = 0x03 + 抑制bit
canFrame = DoCANTransport::packRequest(sessionReq);
receivedUdsReq = DoCANTransport::unpackResponse(canFrame);
udsResp = uds.processRequest(receivedUdsReq);
if (udsResp.empty()) {
std::cout << "[TesterPresent] No response (suppressed)" << std::endl;
}

return 0;
}
輸出示例:

Send CAN: 03 22 F1 90 
UDS Response: 62 F1 90 01 02 03
[UDS] Switch to session: 3
[TesterPresent] No response (suppressed)
四、關(guān)鍵服務(wù)實(shí)現(xiàn)要點(diǎn) 4.1 $27 安全訪問(種子密鑰簡化)

class SecureUDSHandler : public UDSHandler {
int seed = 0x1234;
int expectedKey = 0x5678; // 實(shí)際應(yīng)為算法:key = seed ^ 0x5555


Bytes handleSecurityAccess(const Bytes& req) {
Byte subfunc = req[1];
if (subfunc == 0x05) { // 請求種子
return buildPositiveResponse(0x27, {0x05, (Byte)(seed >> 8), (Byte)seed});
} else if (subfunc == 0x06) { // 發(fā)送密鑰
int key = (req[2] << 8) | req[3];
if (key == expectedKey) {
securityLocked = false;
return buildPositiveResponse(0x27, {0x06});
}
return buildNegativeResponse(0x27, NRC::INVALID_KEY);
}
return buildNegativeResponse(0x27, NRC::INVALID_FORMAT);
}
};
4.2 14 DTC 處理示例

// 簡化 DTC 讀取(按狀態(tài)掩碼 0xFF)
Bytes handleReadDTC(const Bytes& req) {
if (req.size() >= 2 && req[1] == 0x02) {
// 模擬返回 2 個(gè) DTC
return {0x59, 0x02,
0x01, 0x23, 0x45, 0x80, // DTC 1 + status
0x01, 0x67, 0x89, 0x20}; // DTC 2
}
return buildNegativeResponse(0x19, NRC::INVALID_FORMAT);
}
五、總結(jié)

特性

描述

標(biāo)準(zhǔn)化

UDS 統(tǒng)一了診斷服務(wù)格式,減少重復(fù)開發(fā)

靈活性

支持自定義 DID、Routine、安全算法

可擴(kuò)展

基于 ISO 15765-2 可承載任意長度診斷數(shù)據(jù)

工程落地

現(xiàn)代汽車診斷工具(CANoe、PCAN、ZLG)均支持 UDS + DoCAN

本 C++ 示例展示了:

  • UDS 請求/響應(yīng)處理框架

  • DoCAN 單幀打包/解包

  • 22/$3E 服務(wù)的簡化實(shí)現(xiàn)

  • 否定響應(yīng)與抑制響應(yīng)機(jī)制

實(shí)際 ECU 開發(fā)中需完善多幀傳輸、定時(shí)管理、會話狀態(tài)機(jī)和安全訪問算法。

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務(wù)。

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.

相關(guān)推薦
熱點(diǎn)推薦
啥都和愛國扯到一起,就是一種病

啥都和愛國扯到一起,就是一種病

老唐有話說
2026-05-14 16:18:17
A股:剛剛,國務(wù)院國資委發(fā)布,不出意外的話,下周將迎來新變化

A股:剛剛,國務(wù)院國資委發(fā)布,不出意外的話,下周將迎來新變化

云鵬敘事
2026-05-16 00:00:09
國家發(fā)改委主任鄭柵潔會見波音公司總裁奧特伯格

國家發(fā)改委主任鄭柵潔會見波音公司總裁奧特伯格

新京報(bào)
2026-05-15 20:29:22
上海87-82戰(zhàn)勝北京!賽后數(shù)據(jù)一清二楚,不是王哲林 最大功臣是他

上海87-82戰(zhàn)勝北京!賽后數(shù)據(jù)一清二楚,不是王哲林 最大功臣是他

小火箭愛體育
2026-05-15 21:32:09
難怪黃仁勛那么積極跟著特朗普訪華,一到北京就拿下了大額訂單。

難怪黃仁勛那么積極跟著特朗普訪華,一到北京就拿下了大額訂單。

魔都姐姐雜談
2026-05-14 22:09:10
人活多久,看喝酒就知道?壽命短的人,喝酒一般有這6個(gè)特征

人活多久,看喝酒就知道?壽命短的人,喝酒一般有這6個(gè)特征

芹姐說生活
2026-05-14 23:38:55
上海奪G1但3人需總結(jié)!盧偉應(yīng)變差點(diǎn),白邊優(yōu)勢被打沒,弗格太鐵

上海奪G1但3人需總結(jié)!盧偉應(yīng)變差點(diǎn),白邊優(yōu)勢被打沒,弗格太鐵

籃球資訊達(dá)人
2026-05-16 01:09:21
38.98萬,夸張啊...

38.98萬,夸張啊...

放毒
2026-05-15 19:14:23
中紀(jì)委再次重拳出擊!這4個(gè)領(lǐng)域?qū)⒈粐?yán)查,這4種行為將被嚴(yán)肅處理

中紀(jì)委再次重拳出擊!這4個(gè)領(lǐng)域?qū)⒈粐?yán)查,這4種行為將被嚴(yán)肅處理

細(xì)說職場
2026-05-15 14:01:05
鄺兆鐳U17亞洲杯首秀!送助攻后或舊傷復(fù)發(fā),只踢半場仍獲贊

鄺兆鐳U17亞洲杯首秀!送助攻后或舊傷復(fù)發(fā),只踢半場仍獲贊

奧拜爾
2026-05-16 02:13:48
悲催!上海一母親將700萬遺產(chǎn)給兒子,6年后才發(fā)現(xiàn)被女兒徹底拉黑

悲催!上海一母親將700萬遺產(chǎn)給兒子,6年后才發(fā)現(xiàn)被女兒徹底拉黑

火山詩話
2026-05-15 06:49:15
特朗普還沒回國,就開始放狠話了

特朗普還沒回國,就開始放狠話了

利刃號
2026-05-15 17:16:39
第一次感受到“荔枝核的威力”,泡水里20天,長成“粉盆栽”

第一次感受到“荔枝核的威力”,泡水里20天,長成“粉盆栽”

美家指南
2026-05-15 15:27:43
國宴名場面刷屏:穿紅衣的服務(wù)員火了,這才是大國該有的體面

國宴名場面刷屏:穿紅衣的服務(wù)員火了,這才是大國該有的體面

娛樂洞察點(diǎn)點(diǎn)
2026-05-15 12:40:18
“錢車兩空”!男子以租代購跑網(wǎng)約車,三年還清13.5萬,過戶前一夜車被拖走

“錢車兩空”!男子以租代購跑網(wǎng)約車,三年還清13.5萬,過戶前一夜車被拖走

網(wǎng)約車觀察室
2026-05-14 10:00:49
張雪宣布停產(chǎn)!博主:雷軍出問題你建議退款 自己出問題只補(bǔ)償

張雪宣布停產(chǎn)!博主:雷軍出問題你建議退款 自己出問題只補(bǔ)償

念洲
2026-05-14 14:29:33
不是洛夫頓!不是古德溫!許利民贊上海隊(duì)1人,威廉姆斯傷情出爐

不是洛夫頓!不是古德溫!許利民贊上海隊(duì)1人,威廉姆斯傷情出爐

老吳說體育
2026-05-15 23:31:25
這跟不穿有啥區(qū)別?趙露思演唱會內(nèi)衣外穿:被眾嘲一套比一套辣眼

這跟不穿有啥區(qū)別?趙露思演唱會內(nèi)衣外穿:被眾嘲一套比一套辣眼

胡一舸南游y
2026-05-13 15:23:56
看好誰當(dāng)選臺北市長?1.4萬人網(wǎng)絡(luò)投票結(jié)果一面倒

看好誰當(dāng)選臺北市長?1.4萬人網(wǎng)絡(luò)投票結(jié)果一面倒

新時(shí)光點(diǎn)滴
2026-05-16 00:10:48
沙拉維深情告別羅馬:我即將離開,但我的一部分靈魂將永駐于此

沙拉維深情告別羅馬:我即將離開,但我的一部分靈魂將永駐于此

懂球帝
2026-05-16 02:43:35
2026-05-16 02:59:00
新能源自動駕駛 incentive-icons
新能源自動駕駛
專注于半導(dǎo)體行業(yè)資訊
977文章數(shù) 347關(guān)注度
往期回顧 全部

科技要聞

直降千元起步!蘋果華為率先開啟618讓利

頭條要聞

黃仁勛在北京喝豆汁痛苦皺眉 問“這是什么東西”

頭條要聞

黃仁勛在北京喝豆汁痛苦皺眉 問“這是什么東西”

體育要聞

德約科維奇買的球隊(duì),從第6級聯(lián)賽升入法甲

娛樂要聞

方媛為何要來《桃花塢6》沒苦硬吃?

財(cái)經(jīng)要聞

騰訊掉隊(duì),馬化騰戳破真相

汽車要聞

高爾夫GTI刷新紐北紀(jì)錄 ID. Polo GTI迎全球首秀

態(tài)度原創(chuàng)

手機(jī)
親子
本地
旅游
公開課

手機(jī)要聞

iPhone 17系列全系跳水,最高立減2500!

親子要聞

孕婦補(bǔ)鈣怕刺激怎么選?液體鈣無添加配方實(shí)測,藍(lán)帽認(rèn)證更靠譜

本地新聞

用蘇繡的方式,打開江西婺源

旅游要聞

藏在沈陽鬧市的金色秘境!2 萬㎡油菜花全開,地鐵直達(dá)還免費(fèi)

公開課

李玫瑾:為什么性格比能力更重要?

無障礙瀏覽 進(jìn)入關(guān)懷版