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.整型
| 類型 | 有/無符號? | 長度 | 描述 | 語法結構 |
| byte | unsigned | 1B | 字節,8位,無符號 | |
| word | unsigned | 2B | 字,16位,無符號 | |
| dword | unsigned | 4B | 雙字,32位,無符號 | |
| qword | unsigned | 8B | 整型,64位,無符號 | |
| int? | signed | 2B | 短整型,16位 | int value = 20;? ? ? ? ?十進制 int value2 = 0x14;? ?十六進制 |
| long | signed | 4B | 長整型,32位 | |
| int64 | signed | 8B | 整型,64位 |
B.浮點型
| 類型 | 長度 | 描述 | 語法結構 |
| float | 8B | 單精度 | float value = 0.23 |
| double | 8B | 雙精度 |
B.字符
| 類型 | 長度 | 語法結構 |
| char | 1B | (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] = { |
| 多維數組 | elCount(數組名) | |
D.特殊類型
| 類型 | 描述 | 代碼 |
| 報文 | 使用關鍵字message來聲明一個報文變量 | message 0xA m1; message EngineDate m3; |
| 診斷報文 | DiagRequest ServiceQualifier request;//診斷請 DiagResponse ServiceQualifier response;//診斷響應 | |
| 系統變量 | ||
| 定時器 | msTimer myTimer; //聲明一個毫秒定時器myTimer? ?單位:ms timer?myTimer;//聲明一個秒定時器myTimer? ?單位:s | |
(5)關鍵字
| break | case | char | continue | default | do | double | else | float | for | if |
| long | return | switch | whlie | enum | struct | auto | const | extern | goto | register |
| signed | sizeof | static | typedef | union | unsigned | volatile | int | short | this | message |
| dbMsg* | signal* | service singnal* | diag Request | sysval* | diag Response | timer | testcase |
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位整數的八進制格式顯示 |
| “%%” | 顯示一個% |
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)事件類型
| 類型 | 事件名 | 執行條件 | 語法結構 |
| 系統事件 | preStart | CANoe初始化時執行 | 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:
用于設置完整服務原語的原始數據(通過傳輸協議傳輸的所有數據)
TestReportWriteDiagObject / TestReportWriteDiagResponse:
用于在測試報告中增加診斷請求或響應的報文打印?
?TestWaitForDiagRequestSent:
用于定義在指定時間內將要求的診斷請求發送出去
?TestWaitForDiagResponse:
用于定義在指定時間內是否收到診斷請求的響應
diagGetLastResponse
用于獲取最新的診斷請求響應?
diagResponse PAS3.* pasDiagRespd; diagGetLastResponse(pasDiagRespd);?diagGetPrimitiveData :
用于讀取一個診斷服務的原始數據
diagGetPrimitiveByte :
用于讀取診斷服務中的某一字節的數據?
diagIsPositiveResponse / diagIsNegativeResponse:
用于判斷回復的診斷相應是否為正/負響應,如果是則返回一個不為0的數值?
?
(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"); } |
| switch | switch ( 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 ) 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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新消息2022年广西最新消防设施操作员
- 下一篇: 行政区划编码转换区域名工具类