前言
以UDS診斷為例,GMLAN會有些許差異,大同小異。
一般Canoe工程加載CDD以后,可以直接通過canoe工程的診斷界面,點擊需要的診斷命令就可以發(fā)送診斷了。
那為什么還需要通過CAPL來發(fā)送診斷呢,
1.診斷界面的數(shù)據(jù)長度和有的參數(shù)范圍是有限制(最大值最小值)的,但是如果你需要驗證發(fā)送錯誤的長度或者超出范圍的參數(shù)數(shù)據(jù)時ECU的響應是否符合要求的時候,沒有辦法通過診斷面板發(fā)送。
2.時間,可能你需要兩個連續(xù)的診斷在間隔多長時間內(nèi)發(fā)送,手動點擊太慢。
或者你的ECU修復了某個bug軟件升級之后,僅僅測試你修復的那個bug是不夠的,最好把所有的診斷都測一下,一個一個點太慢,腳本測試才夠快夠準確。
1、直接調(diào)用CDD里的診斷發(fā)送
在CAPL里,診斷你也可以理解為一種類似于int這種的特殊數(shù)據(jù)類型。
關鍵字是diagRequest,前提是你的Canoe工程里有加載CDD.
在CAPL里編輯diagRequest,然后按空格,編譯器會自動匹配你的canoe工程里加載的CDD名稱。
選中CDD名字后,按‘.’,編譯器會自動匹配出這個CDD支持的診斷列表,然后選中你要發(fā)送的診斷。
以要發(fā)送進入擴展層的診斷請求 10 03 為例,給這個診斷請求取個名字Diag_Tx_10_03,這樣一個診斷請求的數(shù)據(jù)類型就定義好了。
定義完成以后,發(fā)送診斷請求的函數(shù)是diagSendRequest(diagRequest obj),括號里的參數(shù)就是我們定義的診斷請求。
那就是:
on key 't'
{
diagSendRequest(Diag_Tx_10_03);
}
保存,編譯,運行工程,點擊按鍵t,
其他服務也是一樣的,比如0x22服務的讀SN的診斷
diagRequest Door.SerialNumber_Read Diag_Tx_ReadSN;
on key 's'
{
diagSendRequest(Diag_Tx_ReadSN);
}
細心的同學可能會問,為什么Trace兩個都是Tx,沒有Rx,因為我手邊暫時沒有真實的ECU模塊,是用的虛擬ECU,響應的數(shù)據(jù)是用另外一個節(jié)點模擬的,不過這不影響我們的測試驗證,沒有真實ECU的時候,想用驗證就需要設置為模擬總線。
2、用報文的形式發(fā)送診斷
調(diào)用CDD里的診斷進行發(fā)送,最終體現(xiàn)在數(shù)據(jù)流里,還是以報文的形式發(fā)送出來的,所以也可以用發(fā)送報文的形式來發(fā)送診斷,只不過定義報文的請求ID要是診斷的請求id,而且診斷里的前2個byte決定了是單幀還是多幀,
如果是單幀,診斷里的第一個byte就代表者后續(xù)的有效字節(jié)長度。
如果是多幀,診斷里的第一個byte的低4位和第二個byte的高8位代表有效字節(jié)長度
比如發(fā)送進入擴展層的請求,發(fā)送的報文數(shù)據(jù)是02 10 03,其中的02就代表后面只有2個byte是有效數(shù)據(jù)位(10 03)。
如果不知道怎么用Canoe發(fā)送報文的同學,可以參考這個
鏈接: CAPL發(fā)送報文.
圖片:
message 0x700 Diag_Tx_Request;
on key 't'
{
Diag_Tx_Request.dlc=8;
Diag_Tx_Request.byte(0)=0x02;
Diag_Tx_Request.byte(1)=0x10;
Diag_Tx_Request.byte(2)=0x03;
output(Diag_Tx_Request);
}
3、怎么用CAPL發(fā)送多幀的診斷
ECU的診斷每幀最多只能發(fā)8byte的數(shù)據(jù)(CAN FD好像可以64byte),但是如果有個診斷要發(fā)送的數(shù)據(jù)超過了8byte的怎么辦,那需要發(fā)送多幀數(shù)據(jù)才能完成一次發(fā)送了,而且多幀數(shù)據(jù)的發(fā)送是需要ECU端響應的,就是說
我上位機先發(fā)第一幀數(shù)據(jù)(首幀)給ECU端,
需要ECU給個響應(流控幀),
上位機才能接著發(fā)送后續(xù)數(shù)據(jù)幀(連續(xù)幀)。
比如說我需要發(fā)1,2,3,4,5,6,7,8,9,A共10個數(shù)據(jù),一幀只能發(fā)8個,發(fā)不完。
1.我需要先發(fā)首幀,首字節(jié)的高4位是1才代表首幀,人家ECU收到這個之后才知道你一幀發(fā)不完需要多幀,才會發(fā)流控幀給你,讓你有機會接著往下發(fā)
首幀如下:
0x10 0x0A 0x01 0x02 0x03 0x04 0x05 0x06
其中0x10的1代表首幀,00A代表有效數(shù)據(jù)長度,1,2,3,4,5,6是要發(fā)送的數(shù)據(jù)。
2.ECU回復個流控幀,第一個字節(jié)是0x30,上位機端接收到這個流控幀以后,才會接著發(fā)剛才沒有發(fā)完的數(shù)據(jù)。
0x30 0x00 0x00 0x00 0x00 x00 0x00 0x00
3.上位機接著發(fā)后續(xù)數(shù)據(jù)幀(連續(xù)幀),連續(xù)幀的首字節(jié)的高4位是2,ECU端接收到2以后,就知道這個數(shù)據(jù)是跟上一幀連起來的。
0x21 0x07 0x08 0x09 0x0A
3.1監(jiān)控流控幀后,把多幀數(shù)據(jù)自己分幀發(fā)送
假設我們通過發(fā)送報文的方式發(fā)送診斷里的F189,需要寫的數(shù)據(jù)有13byte,加上0x2E 0xF1 0x89,就是16位,一幀發(fā)送不完,需要多幀發(fā)送。
第一步:向ECU發(fā)首幀
第二步:等待接收ECU端響應的流控幀
第三步:向ECU發(fā)送連續(xù)幀
那首幀里表示長度的就占據(jù)2個byte了(byte1的高4位代表幀類型,byte1的低4位和byte2的8位一起定義有效數(shù)據(jù)長度)
首幀應該這樣發(fā)送,第一個0x10,高四位是1代表是首幀,第二個byte的0x10是代表后續(xù)的有效數(shù)據(jù)長度是16位。
0x10 0x10 0x2E 0xF1 0x89 0x00 0x00 0x00
發(fā)送完之后,需要等待ECU響應(回復流控幀0x30),才能接著往下發(fā)送后續(xù)數(shù)據(jù)幀(連續(xù)幀)。
on key 't'
{
Diag_Tx_Request.dlc=8;
Diag_Tx_Request.byte(0)=0x10;
Diag_Tx_Request.byte(1)=0x10;
Diag_Tx_Request.byte(2)=0x2E;
Diag_Tx_Request.byte(3)=0xF1;
Diag_Tx_Request.byte(4)=0x89;
Diag_Tx_Request.byte(5)=0x00;
Diag_Tx_Request.byte(6)=0x00;
Diag_Tx_Request.byte(7)=0x00;
output(Diag_Tx_Request);//先發(fā)首幀
Flag_Multi_F189=1;
}
//0x600是ECU的響應ID,就是說接收到ID為0x600的報文以后就會觸發(fā)下面這個函數(shù)
on message 0x600
{
if(this.byte(0)==0x30)//看看第一個byte如果是0x30代表是流控幀,代表可以接著往下發(fā)送數(shù)據(jù)
{
if(Flag_Multi_F189)//判斷是不是F189的流控幀
{
Flag_Multi_F189=0;
Diag_Tx_Request.byte(0)=0x21;
Diag_Tx_Request.byte(1)=0x00;
Diag_Tx_Request.byte(2)=0x00;
Diag_Tx_Request.byte(3)=0x00;
Diag_Tx_Request.byte(4)=0x00;
Diag_Tx_Request.byte(5)=0x00;
Diag_Tx_Request.byte(6)=0x00;
Diag_Tx_Request.byte(7)=0x00;
output(Diag_Tx_Request);//連續(xù)幀一次發(fā)不完可以一直連續(xù)發(fā)
Diag_Tx_Request.byte(0)=0x22;
Diag_Tx_Request.byte(1)=0x00;
Diag_Tx_Request.byte(2)=0x00;
Diag_Tx_Request.byte(3)=0x00;
output(Diag_Tx_Request);//連續(xù)幀一次發(fā)不完可以一直連續(xù)發(fā),兩個連續(xù)幀之間是否需要時間間隔是看流控幀返回的數(shù)據(jù)決定的,這里不展開講了,有需要的可以留言,可以專門寫一篇各個時間參數(shù)的
}
}
}
這是發(fā)送16個數(shù)據(jù)的多幀傳輸可以這樣寫。
如果要發(fā)送1000個byte呢,也可以這么寫,不過會比較麻煩。
3.2調(diào)用CDD里的診斷發(fā)送
還是以發(fā)送診斷F189為例,可以參考上面介紹的調(diào)用CDD里的診斷發(fā)送的,但是發(fā)送的數(shù)據(jù)是診斷界面默認的數(shù)據(jù),如下全0。
如果想用修改寫入的數(shù)據(jù)需要調(diào)用函數(shù)
long diagSetParameterRaw (diagRequest obj, char parameterName[], byte* buffer, DWORD buffersize)
每個參數(shù)的描述如下
第一個參數(shù) obj就是前面用diagrequest定義的那個變量,就是說你要發(fā)哪條診斷請求
第二個參數(shù)是你想寫入的參數(shù)的修飾詞qualifier,這個修飾詞去哪里找呢,我理解去CDD文件里找才是最準確的,比如F189的這個參數(shù)修飾詞就是Part_Number。(一般安裝完Canoe后默認附帶安裝candelastudio的,可以直接雙擊點開CDD文件,查看CDD,編輯CDD的話還需要硬件license,但是查看是不用license的)
第三個參數(shù)就是你要寫入的數(shù)據(jù)放到一個buffer里
第四個參數(shù)是buffer的長度.
如下,先定義diagrequest變量和要寫入的數(shù)據(jù)buffer,再給寫入的的診斷參數(shù)賦值,再發(fā)送診斷
byte ID_Write[13];
diagRequest Door.EcuIdentification_Write Diag_Tx_WriteID;
on key 'm'
{
ID_Write[0]=0xff;
ID_Write[1]=0x55;
ID_Write[2]=0xAA;
diagSetParameterRaw(Diag_Tx_WriteID,"Part_Number",ID_Write,13);
diagSendRequest(Diag_Tx_WriteID);
}
3.3使用CanTp分包分幀發(fā)送
當你使用第一種報文的方式發(fā)送多幀的診斷時,有沒有想過要是有個函數(shù),我直接告訴多發(fā)多長的數(shù)據(jù),然后把數(shù)據(jù)給他,讓它自己發(fā)送就好了,這樣就不用我自己在把數(shù)據(jù)分包了。
有的,cantp,我理解它的作用就是把這些數(shù)據(jù)按照協(xié)議打包/分包這種。
不過不是CAPL自帶的函數(shù),需要額外加載庫,但是這個庫是安裝canoe的時候就有了的,
3.1:把安裝目錄下的dll文件拷貝到你的工程目錄下。
3.2:在節(jié)點的配置Configuration選項里,選擇Components,再選擇Add添加osek_dp.dll文件
3.3在CAPL里選擇添加osek_tp.dll文件,保存,這里".\osek_tp.dll"是相對路徑,其中.\就代表你的工程文件路徑,我的dll文件是直接放在工程目錄下的
3.4.點擊保存CAPL文件以后你會發(fā)現(xiàn)在CAPL編輯器的右側多了osek_tp.dll,點擊+展開以后,會看到這個dll庫里支持的函數(shù),它給你開放了好多函數(shù)接口,前面includes了之后,你就可以用這些函數(shù)了,就像編輯器自帶的函數(shù)一樣。
3.5那怎么用這個庫里面的函數(shù)呢,函數(shù)很多,大部分我也不懂什么意思,
不過了解幾個能夠發(fā)送消息的函數(shù)就夠用了,其他的大家可以自己去嘗試。
要用cantp發(fā)送函數(shù),分幾步
第一步:先連接
用的函數(shù)是CanTpCreateConnection(),我理解這一步的作用就是先確定是標準幀還是擴展幀。
第二步:設置ID
設置發(fā)送請求的ID和ECU響應的ID
第三步發(fā)送數(shù)據(jù)
這幾步里都會用一個connhandle,就是在第一步建立連接的時候返回的一個數(shù)據(jù)吧,就是說無論干啥都要建立在連接ok的基礎上才可以。。
第一個參數(shù)是句柄,建立連接后得到的,
第二個參數(shù)是你要發(fā)送的數(shù)據(jù)
第3個數(shù)據(jù)是你要發(fā)送的數(shù)據(jù)長度
我們還是以發(fā)送診斷F189為例
代碼如下
includes
{
#pragma library (".\osek_tp.dll")
}
variables
{
const dword Diag_Tx_id = 0x700;
const dword Diag_Rx_id = 0x600;
const byte TpPadding = 0x55;
byte ID_Write[16];
long TpHandle;
}
on start
{
TpHandle = CanTpCreateConnection(0); //連接,參數(shù)是0代表標準幀
CanTpSetTxIdentifier(TpHandle, Diag_Tx_id); //設置ID
CanTpSetRxIdentifier(TpHandle, Diag_Rx_id);
CanTpSetPadding(TpHandle, TpPadding);//設置填充位
}
on key 't'
{
ID_Write[0]=0x2E;
ID_Write[1]=0xF1;
ID_Write[2]=0x89;
ID_Write[3]=0x33; //想用發(fā)送什么數(shù)據(jù),給要發(fā)送的數(shù)組賦值就好了,我這里隨便舉例一個數(shù)據(jù)
CanTpSendData(TpHandle, ID_Write, 16);//發(fā)送
}
建立連接,設置id這些只需要做一次就好了,所以放在on start里在工程運行的時候設置一次就好了。
還多了一個函數(shù)CanTpSetPadding
這個函數(shù)的意思是,
比如當你發(fā)送一幀數(shù)據(jù)時,02 10 03只有3個byte,但是一幀里需要發(fā)滿8個byte的時候(有的車廠就有這樣的要求),后面5個byte其實是沒有意義的,可以隨便填充,但是有的車廠會要求填充0xAA或0x55…
CanTpSetPadding這個函數(shù)就是設置填充數(shù)據(jù)的,車廠沒有要求的話可以不用這個.文章來源:http://www.zghlxwxcb.cn/news/detail-626290.html
看下面的數(shù)據(jù),填充0x55的那幾位,就是最后一幀連續(xù)幀里有效數(shù)據(jù)為不夠8位了,需要填充。文章來源地址http://www.zghlxwxcb.cn/news/detail-626290.html
到了這里,關于怎么用Canoe CAPL發(fā)送診斷的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!