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

網易首頁 > 網易號 > 正文 申請入駐

J1939診斷應用層協議詳解:從DM1報文格式到DTC解析的完整指南

0
分享至

J1939診斷應用層協議(SAE J1939-73)是重型車輛診斷的核心標準,它規范了故障碼(DTC)的格式、診斷報文的定義以及多包傳輸機制。本文結合協議原理與C++代碼示例,深入解析DM1報文的解析與發送過程。


1. J1939診斷應用層協議簡介

J1939的診斷應用層(對應SAE J1939-73標準)不僅覆蓋基礎的故障檢測功能,還涵蓋了監視系統、內存存取、數據轉換、引導載入、標定等一系列復雜的交互功能。其核心目的之一是標準化不同廠商、不同車型的診斷信息交互方式,避免重復開發。

這些功能通過不同類型的診斷報文(Diagnostic Message, DM) 實現,例如:

  • DM1 :當前激活故障碼

  • DM2 :歷史故障碼

  • DM3 :歷史故障碼清除/復位

  • DM11 :凍結幀數據

2. 核心概念解析

在深入代碼之前,需要理解J1939診斷的幾個核心術語。

2.1 SPN (可疑參數編號)

SPN用于標識具體的子系統、部件或故障對象(如發動機、傳感器)。它是一個19位的編號,前511個與SAE J1587兼容,之后的由SAE定義或廠商自定義。

2.2 DTC (診斷故障碼) 的構成

J1939的DTC結構與常見的UDS(3字節)不同,它由4個字段組成,共占4個字節

字段

位數

描述

SPN

19位

指示故障發生在哪個部件/子系統

FMI

5位

故障模式指示器,描述故障類型(如電壓高、數據不穩定)

OC

7位

故障發生次數

CM

1位

SPN轉換方式(通常設為0,表示使用最新版本轉換)


2.3 PGN (參數組編號)

診斷報文在總線上通過PGN進行識別。例如,**DM1報文的PGN是65226 (0x00FECA)**。

3. 診斷應用示例:DM1報文(當前故障碼)

DM1是診斷中最核心的報文,用于周期性廣播當前處于激活狀態的故障碼。根據SAE J1939-73規范,當存在激活故障時,ECU必須每秒發送一次DM1報文;如果故障狀態發生變化,必須立即發送。

3.1 DM1報文格式

DM1報文數據域格式如下(Intel格式,小端模式):

Byte

參數

描述

1

指示燈狀態

Bit 7-6: MIL, Bit 5-4: 紅色停止燈, Bit 3-2: 琥珀色警告燈, Bit 1-0: 保護燈

2

預留

通常為0xFF

3-6

DTC

SPN (19位) + FMI (5位) + OC (7位) + CM (1位)

7-8

DTC

如果存在多個故障,繼續排列


3.2 C++ 代碼示例:解析DM1報文

以下代碼演示如何從CAN原始數據中提取DM1中的第一個DTC,并解析相關的指示燈狀態。

#include  
          
#include

// 定義DTC結構體
struct J1939_DTC {
uint32_t spn; // 可疑參數編號 (0 - 524287)
uint8_t fmi; // 故障模式標識 (0 - 31)
uint8_t oc; // 發生次數 (0 - 126)
bool cm; // 轉換方式 (通常為0)
};

// 解析DM1報文的函數
// data: 指向CAN數據域8字節的指針
void Parse_DM1(const uint8_t* data) {
// 1. 解析指示燈狀態 (Byte 1)
uint8_t lampStatus = data[0];
bool mil_on = (lampStatus >> 7) & 0x01; // Malfunction Indicator Lamp
bool red_stop_on = (lampStatus >> 5) & 0x01; // Red Stop Lamp
bool amber_warning_on = (lampStatus >> 3) & 0x01; // Amber Warning Lamp
bool protect_on = (lampStatus >> 1) & 0x01; // Protection Lamp

std::cout << "=== DM1 解析結果 ===" << std::endl;
std::cout << "MIL燈: " << (mil_on ? "點亮" : "熄滅") << std::endl;
std::cout << "紅色停止燈: " << (red_stop_on ? "點亮" : "熄滅") << std::endl;
std::cout << "琥珀色警告燈: " << (amber_warning_on ? "點亮" : "熄滅") << std::endl;

// 2. 解析第一個DTC (Byte 3-6)
// 注:J1939通常使用Intel格式,即低字節在前
uint32_t raw_spn_fmi = data[3] | (data[4] << 8) | (data[5] << 16) | (data[6] << 24);
J1939_DTC dtc;
// 提取SPN (低19位: bits 0-18)
dtc.spn = raw_spn_fmi & 0x7FFFF;
// 提取FMI (bits 19-23) -> 右移19位,取低5位
dtc.fmi = (raw_spn_fmi >> 19) & 0x1F;
// 提取CM (bit 24) -> 右移24位,取低1位
dtc.cm = (raw_spn_fmi >> 24) & 0x01;
// 提取OC (bits 25-31) -> 右移25位,取低7位
dtc.oc = (raw_spn_fmi >> 25) & 0x7F;

std::cout << "\n=== 當前激活故障碼 (DTC ) ===" << std::endl;
std::cout << "SPN: " << dtc.spn << " (部件標識)" << std::endl;
std::cout << "FMI: " << (int)dtc.fmi << " (故障模式)" << std::endl;
std::cout << "OC: " << (int)dtc.oc << " (發生次數)" << std::endl;
std::cout << "CM: " << dtc.cm << " (轉換方式)" << std::endl;
}

int main() {
// 模擬總線接收到的一幀DM1報文
// 場景:發動機進氣歧管壓力(SPN 102)電壓低于正常值(FMI 4),發生2次
// 數據排列 (Intel 格式):
// Byte1: 指示燈(0x04) -> AMBER燈亮
// Byte2: 0xFF
// Byte3-6: SPN=102, FMI=4, OC=2, CM=0
// 計算 Raw Value: SPN(102) | (FMI(4)<<19) | (CM(0)<<24) | (OC(2)<<25)
// 結果 = 0x00040066 (小端存儲在內存中: 0x66, 0x00, 0x04, 0x00)
uint8_t simulated_dm1[8] = {0x04, 0xFF, 0x66, 0x00, 0x04, 0x00, 0xFF, 0xFF};
Parse_DM1(simulated_dm1);
return 0;
}
3.3 C++ 代碼示例:發送DM1報文

在實際ECU開發中,需要構造并發送DM1。以下示例展示如何打包一個DTC并發送(此處模擬傳輸層發送函數)。

#include  
          
#include
#include

// 模擬CAN發送函數(實際開發中替換為驅動層函數)
bool CAN_Send(uint32_t id, const uint8_t* data, uint8_t len) {
std::cout << "發送CAN ID: 0x" << std::hex << id << std::endl;
std::cout << "數據: ";
for (int i = 0; i < len; i++) {
std::cout << std::hex << (int)data[i] << " ";
}
std::cout << std::dec << std::endl;
return true;
}

// 發送DM1報文的函數
void Send_DM1(uint8_t lamp_status, const J1939_DTC* dtc_list, uint8_t count) {
uint8_t data[8];
memset(data, 0xFF, sizeof(data)); // 初始化填充0xFF
// 設置Byte 1: 指示燈狀態
data[0] = lamp_status;
// 設置Byte 2: 預留
data[1] = 0xFF;
if (count > 0 && dtc_list != nullptr) {
// 打包第一個DTC到 Bytes 3-6
// 構造32位原始DTC值: Bytes = SPN + (FMI<<19) + (CM<<24) + (OC<<25)
uint32_t raw_dtc = dtc_list[0].spn;
raw_dtc |= (dtc_list[0].fmi << 19);
raw_dtc |= ((dtc_list[0].cm ? 1 : 0) << 24);
raw_dtc |= (dtc_list[0].oc << 25);
// 寫入數組 (Intel格式: 低字節在低地址)
data[3] = raw_dtc & 0xFF;
data[4] = (raw_dtc >> 8) & 0xFF;
data[5] = (raw_dtc >> 16) & 0xFF;
data[6] = (raw_dtc >> 24) & 0xFF;
// 注意:若有多個DTC,需要利用傳輸層協議(TP)發送多包,此處僅演示單包
}
// DM1的PGN是65226,對應CAN ID通常為 0x18FECA00 + Source Address
uint32_t can_id = 0x18FECA00; // 假設源地址為0
CAN_Send(can_id, data, 8);
}

int main() {
J1939_DTC active_dtc;
active_dtc.spn = 100; // 發動機機油壓力
active_dtc.fmi = 1; // 數據低于正常范圍
active_dtc.oc = 3; // 發生3次
active_dtc.cm = 0; // 標準轉換
// 點亮琥珀色警告燈
uint8_t lamp = 0x04; // Amber燈亮
std::cout << "發送激活故障碼 DM1..." << std::endl;
Send_DM1(lamp, &active_dtc, 1);
return 0;
}
4. 多包傳輸機制

當DM1報文包含的激活故障碼超過1個時(即數據超過8字節),必須使用J1939傳輸層協議(TP) 進行多包傳輸。

  1. **BAM (廣播公告報文)**:發送方先發出PGN 60416的報文,聲明即將發送消息的字節總數、分包數量及目標PGN(如65226)。

  2. **DT (數據傳輸報文)**:隨后發送一系列PGN 60160的報文,每一包包含7字節的有效載荷,順序拼接成完整的DM1報文。

下圖展示了多包DM1在總線上的邏輯結構:

[ BAM Packet ] --> 告知: 我要發送22字節數據,分4包發,內容屬于DM1
[ DT Packet ] --> 序列號1 + Data(Byte 0-6)
[ DT Packet ] --> 序列號2 + Data(Byte 7-13)
[ DT Packet ] --> 序列號3 + Data(Byte 14-20)
[ DT Packet ] --> 序列號4 + Data(Byte 21-22 + 填充)
5. 總結

J1939診斷應用層協議(J1939-73)通過標準化的SPNFMIDM1報文,為重型車輛提供了高效的故障自診斷方案。理解其DTC的位/字節布局以及多包傳輸(BAM/DT) 機制,是進行商用車控制器(ECU)開發和故障診斷的基礎。

與乘用車常用的UDS協議不同,J1939診斷具有更強的周期性廣播特性(每秒一次的固定心跳),這要求開發者在設計ECU軟件時,需嚴格遵循其發送時序,以防止因報文速率過高導致總線負載異常。

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

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.

相關推薦
熱點推薦
啥都和愛國扯到一起,就是一種病

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

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

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

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

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

新京報
2026-05-15 20:29:22
上海87-82戰勝北京!賽后數據一清二楚,不是王哲林 最大功臣是他

上海87-82戰勝北京!賽后數據一清二楚,不是王哲林 最大功臣是他

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

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

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

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

芹姐說生活
2026-05-14 23:38:55
上海奪G1但3人需總結!盧偉應變差點,白邊優勢被打沒,弗格太鐵

上海奪G1但3人需總結!盧偉應變差點,白邊優勢被打沒,弗格太鐵

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

38.98萬,夸張啊...

放毒
2026-05-15 19:14:23
中紀委再次重拳出擊!這4個領域將被嚴查,這4種行為將被嚴肅處理

中紀委再次重拳出擊!這4個領域將被嚴查,這4種行為將被嚴肅處理

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

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

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

悲催!上海一母親將700萬遺產給兒子,6年后才發現被女兒徹底拉黑

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

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

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

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

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

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

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

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

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

張雪宣布停產!博主:雷軍出問題你建議退款 自己出問題只補償

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

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

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

這跟不穿有啥區別?趙露思演唱會內衣外穿:被眾嘲一套比一套辣眼

胡一舸南游y
2026-05-13 15:23:56
看好誰當選臺北市長?1.4萬人網絡投票結果一面倒

看好誰當選臺北市長?1.4萬人網絡投票結果一面倒

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

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

懂球帝
2026-05-16 02:43:35
2026-05-16 02:59:00
新能源自動駕駛 incentive-icons
新能源自動駕駛
專注于半導體行業資訊
977文章數 347關注度
往期回顧 全部

汽車要聞

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

頭條要聞

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

頭條要聞

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

體育要聞

德約科維奇買的球隊,從第6級聯賽升入法甲

娛樂要聞

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

財經要聞

騰訊掉隊,馬化騰戳破真相

科技要聞

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

態度原創

時尚
旅游
親子
本地
軍事航空

頂級團隊拍出來的作品不如素人,問題出在哪兒了?

旅游要聞

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

親子要聞

孕婦補鈣怕刺激怎么選?液體鈣無添加配方實測,藍帽認證更靠譜

本地新聞

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

軍事要聞

烏克蘭首都基輔遭空襲 死亡人數增至12人

無障礙瀏覽 進入關懷版