CANoe——CAPL
一、CAPL
CAPL(Communication Access Programming Language)基于C語言開發(fā)的,專門用于CANalyzer和CANoe工具環(huán)境。
二、語法
CAPL程序的結(jié)構(gòu)包含了頭文件、全局變量、事件函數(shù)、自定義函數(shù)
?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. /* 注釋內(nèi)容 */ 2. /* 注釋內(nèi)容 注釋內(nèi)容*/ 3. /* 注釋內(nèi)容*/ 4. // 注釋內(nèi)容(2)變量名稱
A.變量名、函數(shù)名和數(shù)組名可以由字母和數(shù)字和下劃線組成,但是首字母不能是數(shù)字
B.對于用戶定義的變量,小寫字母和大寫字母是不同的變量
C.CAPL支持的關(guān)鍵字是不區(qū)分大小寫
(3)運(yùn)算符
(4)?數(shù)據(jù)類型
A.整型
| 類型 | 有/無符號? | 長度 | 描述 | 語法結(jié)構(gòu) |
| byte | unsigned | 1B | 字節(jié),8位,無符號 | |
| word | unsigned | 2B | 字,16位,無符號 | |
| dword | unsigned | 4B | 雙字,32位,無符號 | |
| qword | unsigned | 8B | 整型,64位,無符號 | |
| int? | signed | 2B | 短整型,16位 | int value = 20;? ? ? ? ?十進(jìn)制 int value2 = 0x14;? ?十六進(jìn)制 |
| long | signed | 4B | 長整型,32位 | |
| int64 | signed | 8B | 整型,64位 |
B.浮點(diǎn)型
| 類型 | 長度 | 描述 | 語法結(jié)構(gòu) |
| float | 8B | 單精度 | float value = 0.23 |
| double | 8B | 雙精度 |
B.字符
| 類型 | 長度 | 語法結(jié)構(gòu) |
| 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.復(fù)合類型
| 類型 | 語法結(jié)構(gòu) | |
| 結(jié)構(gòu) | struct | struct Data { ? ? ? ? ? ? ? ? ? ? ? ?int age; ? ? ? ? ? ? ? ? ? ? ? ?long hight; ? ? ? ? ? ? ? ? ? ? ? ?char name[50]; ? ? ? ? ? ? ? ? ? }; |
| 枚舉 | enum | enum Colors { Red, Green, Blue }; // 默認(rèn) 從 0開始,每個(gè)元素+1 enum State { State_Off = -1, State_On = 1 }; //可以指定值 |
| 數(shù)組 | array | (1) char alphabet[27] = “ABCDEFGHIJK”; alphabet[0] = ‘A’ (2)整形或者浮點(diǎn)型數(shù)組 int sample_data[4] = { 100, 300, 500, 600 }; (3)二維數(shù)組 int M[4][5] = { |
| 多維數(shù)組 | elCount(數(shù)組名) | |
D.特殊類型
| 類型 | 描述 | 代碼 |
| 報(bào)文 | 使用關(guān)鍵字message來聲明一個(gè)報(bào)文變量 | message 0xA m1; message EngineDate m3; |
| 診斷報(bào)文 | DiagRequest ServiceQualifier request;//診斷請 DiagResponse ServiceQualifier response;//診斷響應(yīng) | |
| 系統(tǒng)變量 | ||
| 定時(shí)器 | msTimer myTimer; //聲明一個(gè)毫秒定時(shí)器myTimer? ?單位:ms timer?myTimer;//聲明一個(gè)秒定時(shí)器myTimer? ?單位:s | |
(5)關(guān)鍵字
| 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代表該方法運(yùn)行所創(chuàng)建的那個(gè)對象;
2.在構(gòu)造方法中,this代表該方法運(yùn)行所創(chuàng)建的那個(gè)對象;
write
| 格式 | 輸出 |
| “%ld” or “%d” | 整數(shù)十進(jìn)制格式顯示 |
| “%lx” or “%x” | 整數(shù)十六進(jìn)制格式顯示 |
| “%lX” or “%X” | 整數(shù)十六進(jìn)制格式顯示 (字母大寫顯示) |
| “%lu” or “%u” | 無符號整數(shù)格式顯示 |
| “%lo” or “%o” | 整數(shù)八進(jìn)制格式顯示 |
| “%s” | 顯示字符串 |
| “%g” | 浮點(diǎn)數(shù)顯示(最終顯示為科學(xué)計(jì)數(shù)法) |
| “%f” | 浮點(diǎn)數(shù)顯示 |
| “%c” | 顯示一個(gè)字符 |
| “%I64d” or “%lld” | 64位整數(shù)的十進(jìn)制格式顯示 |
| “%I64x” or “%llx” | 64位整數(shù)的十六進(jìn)制格式顯示 |
| “%I64X” or “%llX” | 64位整數(shù)的十六進(jìn)制格式顯示(字母大寫顯示) |
| “%I64u” or “%llu” | 64位無符號整數(shù)的十進(jìn)制格式顯示 |
| “%I64o” or “%llo” | 64位整數(shù)的八進(jìn)制格式顯示 |
| “%%” | 顯示一個(gè)% |
Message
msg.CAN = 1 /*幀的傳輸通道*/ msg.ID = 0x600 /*幀的ID*/ msg.name=Msg1 /*幀的名稱*//*DIR和RTR結(jié)合使用*/ msg.DIR = Tx / Rx /*幀的傳輸方向:Rx(received);Tx(sent)*/ msg.RTR =1 /*幀的傳輸請求的狀態(tài):0(無遠(yuǎn)程傳輸請求);1(遠(yuǎn)程傳輸請求)*/msg.type=RXREMOTE /*TYPE = (RTR << 8) | DIR*/msg.dlc = 8 /*幀的長度*/(6)事件類型
| 類型 | 事件名 | 執(zhí)行條件 | 語法結(jié)構(gòu) |
| 系統(tǒng)事件 | preStart | CANoe初始化時(shí)執(zhí)行 | on preStart { . . . } |
| start | 測量開始時(shí)執(zhí)行 | on start { . . . } | |
| stopMeasurement | 測量結(jié)束時(shí)執(zhí)行 | on stopMeasurement { . . . } | |
| CAN消息事件 | 自定義 | 接受到指定消息時(shí)執(zhí)行 | on message 自定義名 { . . . } |
| 時(shí)間事件 | 定時(shí)時(shí)間到后執(zhí)行 | on timer 自定義名 { . . . } | |
| 鍵盤事件 | 指定按鍵按下時(shí) | on key 按鍵名 { . . . } | |
| CAN控制器事件 | busoff | 硬件檢測到busoff時(shí)執(zhí)行 | on busoff { . . . } |
| errorActive | 硬件檢測到errorActive時(shí)執(zhí)行 | on errorActive { . . . } | |
| errorPassive | 硬件檢測到errorPassive時(shí)執(zhí)行 | on errorPassive { . . . } | |
| warningLimit | 硬件檢測到warningLimit時(shí)執(zhí)行 | on warningLimit { . . . } | |
| 錯(cuò)誤幀事件 | errorFrame | 硬件檢測到錯(cuò)誤幀時(shí)執(zhí)行 | on errorFrame { . . . } |
系統(tǒng)事件
系統(tǒng)事件的發(fā)生順序依次是:preStart-->start-->preStop-->stopMeasurement
on preStart /*系統(tǒng)事件,初始化時(shí)執(zhí)行*/ {write("Measurement started!");msg_Count = 0; }on start /*系統(tǒng)事件,工程開始時(shí)執(zhí)行*/ {write("start Node A");setTimer(cycTimer,20);CallAllOnEnvVar(); // CANoe only }on preStop /*系統(tǒng)事件,工程預(yù)備停止時(shí)執(zhí)行;發(fā)生在stopMeasurement事件前面*/ {message ShutdownReq m;output(m);DeferStop(1000); }on stopMeasurement /*系統(tǒng)事件,工程停止時(shí)執(zhí)行*/ {write("Message 0x%x received: %d", msg.id, msg_Count); }?CAN控制器事件
on errorPassive /*CAN控制器事件:硬件檢測到errorPassive時(shí)執(zhí)行*/ {...write("CAN Controller is in errorPassive state")write(" errorCountTX = %d", this.errorCountTX);write(" errorCountRX = %d", this.errorCountRX); };on busOff /*CAN控制器事件:硬件檢測到BusOff時(shí)執(zhí)行*/ {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報(bào)文事件
on message 123 /*接收到123(10進(jìn)制)這個(gè)ID的報(bào)文時(shí)執(zhí)行*/ on message 0x441 /*接收到0x441(16進(jìn)制)這個(gè)ID的報(bào)文時(shí)執(zhí)行*/ on message BCM /*接收到BCM(工程dbc文件中的報(bào)文名)這個(gè)報(bào)文時(shí)執(zhí)行*/ on message* /*接收到任意報(bào)文時(shí)都執(zhí)行(注意*與message之間沒有空格)*/ on message 0x300-0x444 /*接收到這個(gè)范圍內(nèi)的ID報(bào)文時(shí)執(zhí)行*/ {write(“Received %x”,this.id); /*打印接收到的報(bào)文id*/write(“Received Message %d in total!”,count); }報(bào)文的索引及發(fā)送操作(通過報(bào)文的信號(msg.VoiceType)去操作)
void TxMsg_VoiceStatus(void) {message VoiceStatus msg; /*將工程中dbc中定義的VoiceStatus這條報(bào)文取名為msg*/msg.VoiceType = @VoiceType; /*對應(yīng)賦值給到報(bào)文的信號,通過報(bào)文別名"msg."調(diào)出*/msg.VoiceOperation = @VoiceOperation;output(msg); /*通過output指令發(fā)送該報(bào)文*/ }(通過數(shù)據(jù)類型(msg.byte(0))去操作?)
void TxMsg_VoiceStatus(void) {message VoiceStatus msg; /*將工程中dbc中定義的VoiceStatus這條報(bào)文取名為msg*/msg.byte(0) = @VoiceType; /*報(bào)文第1個(gè)數(shù)據(jù)字節(jié)*/msg.word(1) = @VoiceOperation; ; /*報(bào)文從第1個(gè)字節(jié)開始的一個(gè)字(2個(gè)字節(jié))*/output(msg); /*通過output指令發(fā)送該報(bào)文*/ }鍵盤事件
on key ‘a(chǎn)’ /*在小寫輸入法下,按下鍵盤的’A’鍵時(shí)執(zhí)行*/ on key ‘A’ /*在大寫輸入法下,按下鍵盤的’A’鍵時(shí)執(zhí)行*/ on key ‘ ’ /*按下鍵盤的空格鍵時(shí)執(zhí)行,注意單引號中間是有空格的*/ on key 0x20 /*按下鍵盤的空格鍵時(shí)執(zhí)行*/ on key F2 /*按下鍵盤的’F2’鍵時(shí)執(zhí)行*/ on key CtrlF3 /*同時(shí)按下鍵盤的’Ctrl’鍵和’F3’鍵時(shí)執(zhí)行*/ on key* /*按下鍵盤的任意鍵時(shí)都會執(zhí)行(注意*與key之間沒有空格) */ {write(“The Key Is Press”); }定時(shí)器事件
variables {msTimer Timer1; /*在variables中聲明一個(gè)以ms為單位的定時(shí)器變量Timer1*/ }msTimer myTimer; message 100 msg; ... on key 'a' {setTimer(myTimer,20); } ... on timer myTimer {output(msg); }on start { setTimer(Timer1,100); /將Timer1的定時(shí)時(shí)間設(shè)定為100ms,并啟動(dòng)它/ }on timer Timer1 /定義的Timer1時(shí)間事件,每100ms執(zhí)行一次/ { setTimer(Timer1,100); /啟動(dòng)下一個(gè)周期循環(huán)/ }on key ‘a(chǎn)‘ /鍵盤事件,按下鍵盤’A’鍵時(shí)執(zhí)行/ { cancelTimer(Timer1); /停止Timer1這個(gè)100ms執(zhí)行一次的定時(shí)器/ }錯(cuò)誤幀事件(在硬件檢測到錯(cuò)誤幀時(shí)執(zhí)行)
on errorFrame /*錯(cuò)誤幀事件:硬件檢測到錯(cuò)誤幀時(shí)執(zhí)行*/ {write("The error has occur"); }系統(tǒng)變量事件
通過”on sysvar”定義系統(tǒng)變量事件;該事件會在指定的系統(tǒng)變量值有新的輸入時(shí)執(zhí)行;
注:
系統(tǒng)變量與環(huán)境變量差別只在于環(huán)境變量是在dbc文件中定義的
on sysvar IO::DI_0 { $Gateway::IOValue = @this; }on sysvar SysVar1 /*系統(tǒng)變量事件:指定的系統(tǒng)變量值有新的輸入時(shí)執(zhí)行*/ {write("The SysVar1 is %d",@SysVar1); }環(huán)境變量事件
通過”on envVar”定義環(huán)境變量事件;該事件會在指定的環(huán)境變量值有新的輸入時(shí)執(zhí)行
注:
環(huán)境變量常常用于關(guān)聯(lián)上一個(gè)面板控件,當(dāng)我們對控件進(jìn)行操作時(shí),對應(yīng)改變關(guān)聯(lián)上的環(huán)境變量值
on envVar BCM_HightBeamAlarm /*環(huán)境變量事件:指定的環(huán)境變量值有輸入時(shí)執(zhí)行*/ {byte num=0;num = getValue(this); /*可以使用getValue(環(huán)境變量名/this關(guān)鍵字)獲取指定的環(huán)境變量的值*/if(num == 1){write("The envVar is %d",@BCM_HightBeamAlarm); }else{putValue(this,1);/*使用putValue(環(huán)境變量名/this關(guān)鍵字,設(shè)定的值)改變指定的環(huán)境變量的值;直接賦值的話,格式是@BCM_HightBeamAlarm = 1; */write("Change envVar to %d",@BCM_HightBeamAlarm);} }?
(7)函數(shù)
| 函數(shù) | 執(zhí)行條件 | 語法結(jié)構(gòu) |
| setTimer() | 設(shè)置開啟一個(gè)定時(shí)器,時(shí)間到后關(guān)閉 | setTimer(Timer1,100) |
| cancelTimer | 關(guān)閉定時(shí)器 | cancelTimer(Timer1) |
| write() | 消息輸出打印 | write(“The error has occur”) |
| output | 發(fā)送報(bào)文 | output(msg) |
通用函數(shù):
?計(jì)算函數(shù)
?字符串函數(shù)
?CAN總線函數(shù)
?診斷函數(shù)
diagResize:
調(diào)整診斷對象的大小以匹配指定的參數(shù)迭代,或?qū)⒖偩€消息的大小設(shè)置為給定的字節(jié)數(shù)
diagRequest PAS3.* pasDiagReqst; dword diagLen; diagLen = stringToBytes(diagString, rawDiagReqst); diagResize(pasDiagReqst, diagLen);diagSetPrimitiveByte:
用于設(shè)定診斷對象指定字節(jié)的數(shù)值?
for(i=0;i<diagLen;i++){diagSetPrimitiveByte(pasDiagReqst, i, diagData[i]);}?diagSetPrimitiveData:
用于設(shè)置完整服務(wù)原語的原始數(shù)據(jù)(通過傳輸協(xié)議傳輸?shù)乃袛?shù)據(jù))
TestReportWriteDiagObject / TestReportWriteDiagResponse:
用于在測試報(bào)告中增加診斷請求或響應(yīng)的報(bào)文打印?
?TestWaitForDiagRequestSent:
用于定義在指定時(shí)間內(nèi)將要求的診斷請求發(fā)送出去
?TestWaitForDiagResponse:
用于定義在指定時(shí)間內(nèi)是否收到診斷請求的響應(yīng)
diagGetLastResponse
用于獲取最新的診斷請求響應(yīng)?
diagResponse PAS3.* pasDiagRespd; diagGetLastResponse(pasDiagRespd);?diagGetPrimitiveData :
用于讀取一個(gè)診斷服務(wù)的原始數(shù)據(jù)
diagGetPrimitiveByte :
用于讀取診斷服務(wù)中的某一字節(jié)的數(shù)據(jù)?
diagIsPositiveResponse / diagIsNegativeResponse:
用于判斷回復(fù)的診斷相應(yīng)是否為正/負(fù)響應(yīng),如果是則返回一個(gè)不為0的數(shù)值?
?
(8)流程控制
| 控制類型 | 執(zhí)行條件 | 語法結(jié)構(gòu) |
| if? | if 括號內(nèi)的表達(dá)式為真,或者非0,則執(zhí)行if 下面的語句 | if (speed > 60) { ? //花括號內(nèi)的語句都會執(zhí)行 ? ?write("line 1"); ? ?write("line 2"); } |
| 如果沒有花括號,則只執(zhí)行if下面的第一行語句 | if (speed > 60) write("line 1");//這一行語句受if語句控制 write("line 2");//這一行語句不受if語句控制 | |
| if else | 如果下面表達(dá)式為真或者非0,則執(zhí)行語句塊1,否則執(zhí)行語句塊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 | 循環(huán) | while( a < 20 ) { ? write("a 的值: %d\n", a); ? a++; } |
| do…while | 循環(huán) 當(dāng)條件為 true 時(shí)執(zhí)行循環(huán)。 當(dāng)條件為 false 時(shí),退出循環(huán) 注: do…while 循環(huán)與 while 循環(huán)類似,但是 do…while 循環(huán)會確保至少執(zhí)行一次循環(huán) | /* do 循環(huán)執(zhí)行,在條件被測試之前至少執(zhí)行一次 */ do {? ? write("a 的值: %d\n", a); ? ? ?a = a + 1; }while( a < 20 ); |
| for | 循環(huán) | /* for 循環(huán)執(zhí)行 */ for( a = 10; a < 20; a = a + 1 ) {? ?write("a 的值: %d\n", a); } /* for 循環(huán)執(zhí)行 */ for( ; a < 20; )//第1,3個(gè)表達(dá)式為空 { ? ?write("a 的值: %d\n", a); ? ?a = a + 1; } |
| break | 當(dāng) break 語句出現(xiàn)在一個(gè)循環(huán)內(nèi)時(shí),循環(huán)會立即終止 嵌套循環(huán)(即一個(gè)循環(huán)內(nèi)嵌套另一個(gè)循環(huán)),break 語句會停止執(zhí)行最內(nèi)層的循環(huán) | |
| continue | ||
| return | 不帶參數(shù)的return也可以退出循環(huán)語句 用來在函數(shù)中,返回一個(gè)值或者值的表達(dá)式 | while( a < 20 ) result *= x; return result; |
?三、案例
(1)周期消息發(fā)送
?仿真或測試時(shí)向總線模擬發(fā)送周期消息
variables { msTimer myTimer;message 100 msg; } on key 'a' {setTimer(myTimer,20); } on timer myTimer {output(msg);setTimer(myTimer,20); }(2)應(yīng)用報(bào)文Request/Response
?ECU請求/應(yīng)答式的功能
variables {message BCM_Request tBCM_Request; //請求報(bào)文message BCM_Response tBCM_Response; //響應(yīng)報(bào)文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); //測試雨刮關(guān)閉功能Check_Wiper_Feature(1,1); //測試雨刮開啟功能TestGroupEnd(); }//自定義函數(shù) testcase Check_Wiper_Feature(int request, int response ) {tBCM_Request.WiperRequest.phys = request;// 報(bào)文名稱.信號.信號值output(tBCM_Request);//測試請求發(fā)出去后1000ms內(nèi)是否收到BCM的響應(yīng)信號。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)檢測總線中周期報(bào)文的發(fā)送周期
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); }總結(jié)
以上是生活随笔為你收集整理的CANoe——CAPL的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 最新消息2022年广西最新消防设施操作员
- 下一篇: 行政区划编码转换区域名工具类