日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CANoe——CAPL

發布時間:2023/12/31 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CANoe——CAPL 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、CAPL

CAPL(Communication Access Programming Language)基于C語言開發的,專門用于CANalyzer和CANoe工具環境。

二、語法

CAPL程序的結構包含了頭文件、全局變量、事件函數、自定義函數

?includes{ }? ? ? ? ? ? ? ? ? ? ? ? ? ?頭文件是對其他文件及dll文件的包含說明

variables{ }? ? ? ? ? ? ? ? ? ? ? ? ? ?是對全局變量的聲明定義

char letter_a = “a”; int number_days_in_year = 365; message 0x003 xxx; timer one_second; int j, k = 2; double x = 33.7; char p;

on start{ },on timer{ }? ? ? ? ? ? 是工程中用到的各類事件

(1)注釋

1. /* 注釋內容 */ 2. /* 注釋內容 注釋內容*/ 3. /* 注釋內容*/ 4. // 注釋內容

(2)變量名稱

A.變量名、函數名和數組名可以由字母和數字和下劃線組成,但是首字母不能是數字

B.對于用戶定義的變量,小寫字母和大寫字母是不同的變量

C.CAPL支持的關鍵字是不區分大小寫

(3)運算符

(4)?數據類型

A.整型

類型有/無符號?長度描述語法結構
byteunsigned1B字節,8位,無符號
wordunsigned2B字,16位,無符號
dwordunsigned4B雙字,32位,無符號
qwordunsigned8B整型,64位,無符號
int?signed2B短整型,16位

int value = 20;? ? ? ? ?十進制

int value2 = 0x14;? ?十六進制

longsigned4B長整型,32位
int64signed8B整型,64位

B.浮點型

類型長度描述語法結構
float8B單精度float value = 0.23
double8B雙精度

B.字符

類型長度語法結構
char1B

(1)單引號:

char value = ‘B’; char value2 = ‘8’; char value3 = ‘?’;

(2)支持使用ASCII字符集:

char value = 0x42; char value2 = 0x38; char value3 = 0x3F;

(3)字符串

char value[30] = “Here’s a string in C and CAPL”;

C.復合類型

類型語法結構
結構struct

struct Data {

? ? ? ? ? ? ? ? ? ? ? ?int age;

? ? ? ? ? ? ? ? ? ? ? ?long hight;

? ? ? ? ? ? ? ? ? ? ? ?char name[50];

? ? ? ? ? ? ? ? ? };

枚舉enum

enum Colors { Red, Green, Blue }; // 默認 從 0開始,每個元素+1

enum State { State_Off = -1, State_On = 1 }; //可以指定值

數組array

(1)

char alphabet[27] = “ABCDEFGHIJK”;

alphabet[0] = ‘A’

(2)整形或者浮點型數組

int sample_data[4] = { 100, 300, 500, 600 };

(3)二維數組

int M[4][5] = {
{ 10, 5, -3, 17, 82 },
{ 9, 0, 0, 8, -7 },
{ 32, 20, 1, 0, 14 },
{ 0, 0, 8, 7, 6 }
};

多維數組elCount(數組名)

D.特殊類型

類型描述代碼
報文使用關鍵字message來聲明一個報文變量

message 0xA m1;

message EngineDate m3;

診斷報文

DiagRequest ServiceQualifier request;//診斷請

DiagResponse ServiceQualifier response;//診斷響應

系統變量
定時器

msTimer myTimer; //聲明一個毫秒定時器myTimer? ?單位:ms

timer?myTimer;//聲明一個秒定時器myTimer? ?單位:s

(5)關鍵字

breakcasecharcontinuedefaultdodoubleelsefloatforif
longreturnswitchwhlieenumstructautoconstexterngotoregister
signedsizeofstatictypedefunionunsignedvolatileintshortthismessage
dbMsg*signal*

service

singnal*

diag

Request

sysval*

diag

Response

timertestcase

this用法:

1.在普通方法中,this代表該方法運行所創建的那個對象;

2.在構造方法中,this代表該方法運行所創建的那個對象;

write

格式輸出
“%ld” or “%d”整數十進制格式顯示
“%lx” or “%x”整數十六進制格式顯示
“%lX” or “%X”整數十六進制格式顯示 (字母大寫顯示)
“%lu” or “%u”無符號整數格式顯示
“%lo” or “%o”整數八進制格式顯示
“%s”顯示字符串
“%g”浮點數顯示(最終顯示為科學計數法)
“%f”浮點數顯示
“%c”顯示一個字符
“%I64d” or “%lld”64位整數的十進制格式顯示
“%I64x” or “%llx”64位整數的十六進制格式顯示
“%I64X” or “%llX”64位整數的十六進制格式顯示(字母大寫顯示)
“%I64u” or “%llu”64位無符號整數的十進制格式顯示
“%I64o” or “%llo”64位整數的八進制格式顯示
“%%”顯示一個%
void WRITE() {write("Hello world");write("number = %d",number);write("number = %x",number);write("number = %X",number);write("number = %o",number);write("number = %u",number);write("str1 = %s",str1);write("str = %g",str);write("str = %f",str);write("str = %5.3f",str);write("str = %15.33f",str);write("str = %6.8g",str);write("str1 = %c",str2);write("number = %I64d",number);write("number = %I64x",number);write("number = %I64X",number);write("number = %I64o",number);write("number = %I64u",number); }/*輸出*/ Hello world number = 160 number = a0 number = A0 number = 240 number = 160 str1 = abcd str = 1.23457e+008 str = 123456789.987654 str = 123456789.988 str = 123456789.987654330000000000000000000000000 str = 1.2345679e+008 str1 = b number = 712964571296 number = a6000000a0 number = A6000000A0 number = 12300000000240 number = 712964571296

Message

msg.CAN = 1 /*幀的傳輸通道*/ msg.ID = 0x600 /*幀的ID*/ msg.name=Msg1 /*幀的名稱*//*DIR和RTR結合使用*/ msg.DIR = Tx / Rx /*幀的傳輸方向:Rx(received);Tx(sent)*/ msg.RTR =1 /*幀的傳輸請求的狀態:0(無遠程傳輸請求);1(遠程傳輸請求)*/msg.type=RXREMOTE /*TYPE = (RTR << 8) | DIR*/msg.dlc = 8 /*幀的長度*/

(6)事件類型

類型事件名執行條件語法結構
系統事件preStartCANoe初始化時執行on preStart { . . . }
start測量開始時執行on start { . . . }
stopMeasurement測量結束時執行on stopMeasurement { . . . }
CAN消息事件自定義接受到指定消息時執行on message 自定義名 { . . . }
時間事件定時時間到后執行on timer 自定義名 { . . . }
鍵盤事件指定按鍵按下時on key 按鍵名 { . . . }
CAN控制器事件busoff硬件檢測到busoff時執行on busoff { . . . }
errorActive硬件檢測到errorActive時執行on errorActive { . . . }
errorPassive硬件檢測到errorPassive時執行on errorPassive { . . . }
warningLimit硬件檢測到warningLimit時執行on warningLimit { . . . }
錯誤幀事件errorFrame硬件檢測到錯誤幀時執行on errorFrame { . . . }

系統事件

系統事件的發生順序依次是:preStart-->start-->preStop-->stopMeasurement

on preStart /*系統事件,初始化時執行*/ {write("Measurement started!");msg_Count = 0; }on start /*系統事件,工程開始時執行*/ {write("start Node A");setTimer(cycTimer,20);CallAllOnEnvVar(); // CANoe only }on preStop /*系統事件,工程預備停止時執行;發生在stopMeasurement事件前面*/ {message ShutdownReq m;output(m);DeferStop(1000); }on stopMeasurement /*系統事件,工程停止時執行*/ {write("Message 0x%x received: %d", msg.id, msg_Count); }

?CAN控制器事件

on errorPassive /*CAN控制器事件:硬件檢測到errorPassive時執行*/ {...write("CAN Controller is in errorPassive state")write(" errorCountTX = %d", this.errorCountTX);write(" errorCountRX = %d", this.errorCountRX); };on busOff /*CAN控制器事件:硬件檢測到BusOff時執行*/ {int errRxCnt;int errTxCnt;int channel;double timestamp; // [seconds]timestamp = (double)timeNow() / (double)100000;channel = this.can;errRxCnt = this.errorCountRX;errTxCnt = this.errorCountTX;Write("Bus Off: time=%f channel=%d, errRxCnt=%d, errTxCnt=%d",timestamp, channel, errRxCnt, errTxCnt);resetCanEx(channel); }

CAN報文事件

on message 123 /*接收到123(10進制)這個ID的報文時執行*/ on message 0x441 /*接收到0x441(16進制)這個ID的報文時執行*/ on message BCM /*接收到BCM(工程dbc文件中的報文名)這個報文時執行*/ on message* /*接收到任意報文時都執行(注意*與message之間沒有空格)*/ on message 0x300-0x444 /*接收到這個范圍內的ID報文時執行*/ {write(“Received %x”,this.id); /*打印接收到的報文id*/write(“Received Message %d in total!”,count); }

報文的索引及發送操作(通過報文的信號(msg.VoiceType)去操作)

void TxMsg_VoiceStatus(void) {message VoiceStatus msg; /*將工程中dbc中定義的VoiceStatus這條報文取名為msg*/msg.VoiceType = @VoiceType; /*對應賦值給到報文的信號,通過報文別名"msg."調出*/msg.VoiceOperation = @VoiceOperation;output(msg); /*通過output指令發送該報文*/ }

(通過數據類型(msg.byte(0))去操作?

void TxMsg_VoiceStatus(void) {message VoiceStatus msg; /*將工程中dbc中定義的VoiceStatus這條報文取名為msg*/msg.byte(0) = @VoiceType; /*報文第1個數據字節*/msg.word(1) = @VoiceOperation; ; /*報文從第1個字節開始的一個字(2個字節)*/output(msg); /*通過output指令發送該報文*/ }

鍵盤事件

on key ‘a’ /*在小寫輸入法下,按下鍵盤的’A’鍵時執行*/ on key ‘A’ /*在大寫輸入法下,按下鍵盤的’A’鍵時執行*/ on key ‘ ’ /*按下鍵盤的空格鍵時執行,注意單引號中間是有空格的*/ on key 0x20 /*按下鍵盤的空格鍵時執行*/ on key F2 /*按下鍵盤的’F2’鍵時執行*/ on key CtrlF3 /*同時按下鍵盤的’Ctrl’鍵和’F3’鍵時執行*/ on key* /*按下鍵盤的任意鍵時都會執行(注意*與key之間沒有空格) */ {write(“The Key Is Press”); }

定時器事件

variables {msTimer Timer1; /*在variables中聲明一個以ms為單位的定時器變量Timer1*/ }msTimer myTimer; message 100 msg; ... on key 'a' {setTimer(myTimer,20); } ... on timer myTimer {output(msg); }on start { setTimer(Timer1,100); /將Timer1的定時時間設定為100ms,并啟動它/ }on timer Timer1 /定義的Timer1時間事件,每100ms執行一次/ { setTimer(Timer1,100); /啟動下一個周期循環/ }on key ‘a‘ /鍵盤事件,按下鍵盤’A’鍵時執行/ { cancelTimer(Timer1); /停止Timer1這個100ms執行一次的定時器/ }

錯誤幀事件(在硬件檢測到錯誤幀時執行

on errorFrame /*錯誤幀事件:硬件檢測到錯誤幀時執行*/ {write("The error has occur"); }

系統變量事件

通過”on sysvar”定義系統變量事件;該事件會在指定的系統變量值有新的輸入時執行;

注:

系統變量與環境變量差別只在于環境變量是在dbc文件中定義的

on sysvar IO::DI_0 { $Gateway::IOValue = @this; }on sysvar SysVar1 /*系統變量事件:指定的系統變量值有新的輸入時執行*/ {write("The SysVar1 is %d",@SysVar1); }

環境變量事件

通過”on envVar”定義環境變量事件;該事件會在指定的環境變量值有新的輸入時執行

注:

環境變量常常用于關聯上一個面板控件,當我們對控件進行操作時,對應改變關聯上的環境變量值

on envVar BCM_HightBeamAlarm /*環境變量事件:指定的環境變量值有輸入時執行*/ {byte num=0;num = getValue(this); /*可以使用getValue(環境變量名/this關鍵字)獲取指定的環境變量的值*/if(num == 1){write("The envVar is %d",@BCM_HightBeamAlarm); }else{putValue(this,1);/*使用putValue(環境變量名/this關鍵字,設定的值)改變指定的環境變量的值;直接賦值的話,格式是@BCM_HightBeamAlarm = 1; */write("Change envVar to %d",@BCM_HightBeamAlarm);} }

?

(7)函數

函數執行條件語法結構
setTimer()設置開啟一個定時器,時間到后關閉setTimer(Timer1,100)
cancelTimer關閉定時器cancelTimer(Timer1)
write()消息輸出打印write(“The error has occur”)
output發送報文output(msg)

通用函數:

?計算函數

?字符串函數

?CAN總線函數

?診斷函數

diagResize:

調整診斷對象的大小以匹配指定的參數迭代,或將總線消息的大小設置為給定的字節數

diagRequest PAS3.* pasDiagReqst; dword diagLen; diagLen = stringToBytes(diagString, rawDiagReqst); diagResize(pasDiagReqst, diagLen);

diagSetPrimitiveByte:

用于設定診斷對象指定字節的數值?

for(i=0;i<diagLen;i++){diagSetPrimitiveByte(pasDiagReqst, i, diagData[i]);}

?diagSetPrimitiveData:
用于設置完整服務原語的原始數據(通過傳輸協議傳輸的所有數據)

PrintDiagRequestBytes( diagRequest * req) { BYTE primitiveRaw[4095]; long size; size = DiagGetPrimitiveData( req, primitiveRaw, elcount( primitiveRaw)); if( size > 0) write( "Request = (%d)[%02x ...]", size, primitiveRaw[0]); else write( "Request: error %d", size); }

TestReportWriteDiagObject / TestReportWriteDiagResponse:
用于在測試報告中增加診斷請求或響應的報文打印?

diagRequest PAS3.* pasDiagReqst; testReportWriteDiagObject(pasDiagReqst);

?TestWaitForDiagRequestSent:
用于定義在指定時間內將要求的診斷請求發送出去

DiagRequest SerialNumber_Read req; long result;DiagSetTarget("Door"); req.SendRequest(); // waits until request is completely sent if (TestWaitForDiagRequestSent(req, 2000)== 1)TestStepPass("Request was sent successfully!"); elseTestStepFail("Request could not be sent!"); TestWaitForDiagResponse(req, 2000);

?TestWaitForDiagResponse:
用于定義在指定時間內是否收到診斷請求的響應

diagResponse PAS3.* pasDiagRespd; const cApplicationTimeoutMs = 5000; result = testWaitForDiagResponse(pasDiagReqst, cApplicationTimeoutMs)

diagGetLastResponse

用于獲取最新的診斷請求響應?

diagResponse PAS3.* pasDiagRespd; diagGetLastResponse(pasDiagRespd);

?diagGetPrimitiveData :
用于讀取一個診斷服務的原始數據

PrintDiagRequestBytes( diagRequest * req) { BYTE primitiveRaw[4095]; long size; size = DiagGetPrimitiveData( req, primitiveRaw, elcount( primitiveRaw)); if( size > 0) write( "Request = (%d)[%02x ...]", size, primitiveRaw[0]); else write( "Request: error %d", size); }

diagGetPrimitiveByte :

用于讀取診斷服務中的某一字節的數據?

diagIsPositiveResponse / diagIsNegativeResponse:
用于判斷回復的診斷相應是否為正/負響應,如果是則返回一個不為0的數值?

on diagResponse * {// Handle the ambiguity of neg responses by treating them as '*'if( diagIsNegativeResponse ( this ) ){write( "Received negative response for service 0x%x, code 0x%x",(long) diagGetParameter( this, "SIDRQ_NR" ),(long) diagGetParameter( this, "NRC" ) );} }

?

(8)流程控制

控制類型執行條件語法結構
if?

if 括號內的表達式為真,或者非0,則執行if 下面的語句

if (speed > 60)

{

? //花括號內的語句都會執行

? ?write("line 1");

? ?write("line 2");

}

如果沒有花括號,則只執行if下面的第一行語句

if (speed > 60)

write("line 1");//這一行語句受if語句控制

write("line 2");//這一行語句不受if語句控制

if else如果下面表達式為真或者非0,則執行語句塊1,否則執行語句塊2

if (speed > 60)

{?

? ?write("line 1");

}

else if(speed > 80)

{?

? write("line 2");

}

else

{

? write("line 3");

}

switchswitch ( operator )?
{?
?case ‘+’: result = value1 + value2;?
?break;?
?case ‘-’: result = value1 – value2;?
?break;
?case ‘*’: result = value1 * value2;?
?break;?
?default: write (“Unknown operator.”);?
?break;?
}?
while循環

while( a < 20 )

{

? write("a 的值: %d\n", a);

? a++;

}

do…while

循環

當條件為 true 時執行循環。 當條件為 false 時,退出循環

注:

do…while 循環與 while 循環類似,但是 do…while 循環會確保至少執行一次循環

/* do 循環執行,在條件被測試之前至少執行一次 */

do

{? ? write("a 的值: %d\n", a);

? ? ?a = a + 1;

}while( a < 20 );

for循環

/* for 循環執行 */

for( a = 10; a < 20; a = a + 1 )

{? ?write("a 的值: %d\n", a);

}

/* for 循環執行 */

for( ; a < 20; )//第1,3個表達式為空

{

? ?write("a 的值: %d\n", a);

? ?a = a + 1;

}

break

當 break 語句出現在一個循環內時,循環會立即終止

嵌套循環(即一個循環內嵌套另一個循環),break 語句會停止執行最內層的循環

continue
return

不帶參數的return也可以退出循環語句

用來在函數中,返回一個值或者值的表達式

while( a < 20 )
? ?{
? ? ? write("a 的值: %d\n", a);
? ? ? a++;
? ? ? if( a > 15)
? ? ? {
? ? ? ? ?/* 使用 break 語句終止循環 */
? ? ? ? ? return;
? ? ? }
? ?}
————————————————
for (i = 1; i <= y; i++)

result *= x;

return result;

?三、案例

(1)周期消息發送

?仿真或測試時向總線模擬發送周期消息

variables { msTimer myTimer;message 100 msg; } on key 'a' {setTimer(myTimer,20); } on timer myTimer {output(msg);setTimer(myTimer,20); }

(2)應用報文Request/Response

?ECU請求/應答式的功能

variables {message BCM_Request tBCM_Request; //請求報文message BCM_Response tBCM_Response; //響應報文int result = 0;int waitTime = 1000; }void MainTest() {TestModuleTitle ("Test BCM Features");TestModuleDescription ("Check all features in BCM.");TestGroupBegin("BCM Wiper Feature", "Check the perfomance of Wiper");Check_Wiper_Feature(0,0); //測試雨刮關閉功能Check_Wiper_Feature(1,1); //測試雨刮開啟功能TestGroupEnd(); }//自定義函數 testcase Check_Wiper_Feature(int request, int response ) {tBCM_Request.WiperRequest.phys = request;// 報文名稱.信號.信號值output(tBCM_Request);//測試請求發出去后1000ms內是否收到BCM的響應信號。result = TestWaitForSignalMatch(BCM_Response::WiperResponse,response,waitTime);passResult(result,request,response); } void passResult(long result,int request,int response) {switch(result){case 1: TestStepPass("1.0","Test Pass - request : %d expect response : %d ",request,response);break;case 0: TestStepFail("1.0","Timeout - request : %d expect response : %d ",request,response);break;case -1: TestStepFail("1.0","General error - request : %d expect response : %d ",request,response);break;case -2: TestStepFail("1.0","Signal is not valid");break;default:break;} }

(3)檢測總線中周期報文的發送周期

dword ChkCreate_MsgRelCycleTimeViolation (Message aObservedMessage, double aMinRelCycleTime, double aMaxRelCycleTime, Callback aCallback);dword ChkStart_MsgRelCycleTimeViolation (Message aObservedMessage, double aMinRelCycleTime, double aMaxRelCycleTime, Callback aCallback);dword ChkCreate_MsgAbsCycleTimeViolation (Message aObservedMessage, duration aMinCycleTime, duration aMaxCycleTime, char[] aCallback);dword ChkStart_MsgAbsCycleTimeViolation (Message aObservedMessage, duration aMinCycleTime, duration aMaxCycleTime, char[] aCallback);案例:testcase CheckMsgEngineData() {float aMinRelCycleTime = 0.9; float aMaxRelCycleTime = 1.1; // Information for test report.TestCaseTitle("TC 4", "Check cycle time of message EngineData");// checks the cycle time of the messagegCycCheckId = ChkStart_MsgRelCycleTimeViolation (EngineData, aMinRelCycleTime , aMaxRelCycleTime );TestAddCondition(gCycCheckId);// sequence of different actions and waiting conditionsTestWaitForTimeout(1000);TestRemoveCondition(gCycCheckId); }

總結

以上是生活随笔為你收集整理的CANoe——CAPL的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。