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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CANoe教程:CAPL编程

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

?

CANoe教程 | CAPL編程 - 數(shù)據(jù)類型

CAPL是一種類C語言,CAPL數(shù)據(jù)類型的定義很多C語言類似,但也有很多獨(dú)特的地方。 CAPL數(shù)據(jù)類型包括基本類型、結(jié)構(gòu)體、枚舉、關(guān)聯(lián)類型和對象類型。變量的數(shù)據(jù)類型決定了變量存儲占用的空間。

1 基本類型

2 枚舉

枚舉變量的定義和使用同C語言:

enum State { State_Off = -1, State_On = 1 };

如果枚舉成員的值未定義,那么第一個成員默認(rèn)值為1,之后的成員按順序依次加1.?

枚舉變量的定義和使用

variables {enum { Apple, Pear, Banana } fruit = Apple;enum Colors { Red, Green, Blue };enum Colors color; }enum Colors NextColor(enum Colors c) {if (c == Blue) return Red;else return (enum Colors) (c + 1); }

3 關(guān)聯(lián)類型

CAPL支持一種類似Python字典和C++ Map的關(guān)聯(lián)類型(Associative Fields),關(guān)聯(lián)類型的元素是鍵值對(key value pairs)。 關(guān)聯(lián)類型定義格式如下,左邊是value類型,右邊[ ]內(nèi)是key類型:

int m[float]; // maps floats to ints float x[int64]; // maps int64s to floats char[30] s[ char[] ] // maps strings (of unspecified length) to strings of length < 30

example 1:關(guān)聯(lián)浮點(diǎn)型

float m[float]; m[4.1] = 5.5; //key is 4.1 (float) and value is 5.5 (float) m[5.3] = 6.6; write ("4.1 is mapped to %2.2lf", m[4.1]); write ("5.3 is mapped to %2.2lf", m[5.3]); for (float mykey : m) {write("%2.2lf is mapped to %2.2lf.", mykey, m[mykey]); }

example 2:關(guān)聯(lián)字符串

char[30] namen[char []]; strncpy(namen["Max"], "Mustermann", 30); strncpy(namen["Vector"], "Informatik", 30);for (char[] mykey : namen) {write("%s is mapped to %s", mykey, namen[mykey]); }

4 結(jié)構(gòu)體

結(jié)構(gòu)的定義和使用同C:

variables {struct Point{int x;int y;};struct Point myPoint;struct Point allPoints[50]; } on start {myPoint.x = 7;myPoint.y = 2;allPoints[3].x = 1;allPoints[3].y = 5; }

注意: CAPL中結(jié)構(gòu)體默認(rèn)按8字節(jié)對齊,可以在結(jié)構(gòu)體定義前加_align來改變結(jié)構(gòu)體對齊方式。

example:

struct Point { // note: default _align(8) byte x; // offset 0, size 1 byte y; // alignment 1, offset 1, size 1, padding before: 0 }; // size 2, alignment (of the struct) 1struct LongPoint { // note: default _align(8) byte x; // offset 0, size 1 qword y; // alignment 8, offset 8, size 8, padding before: 7 }; // size 16, alignment (of the struct) 8_align(2) struct Point2 { byte x; // offset 0, size 1, (alignment 1) qword y; // alignment 2, offset 2, size 8, padding before: 1 }; // size 10, alignment (of the struct) 2struct Points { // note: _align(8) per default struct Point p1; // offset 0, size 2, (alignment 1) byte x; // alignment 1, offset 2, size 1, padding before: 0 struct Point2 p2; // alignment 2, offset 4, size 10, padding before: 1 }; // size 14, alignment (of the struct) 2

可以使用如下函數(shù)獲取結(jié)構(gòu)體大小(size)、對齊方式(alignment )和偏移量(offset )信息:

example:

struct Points { // note: _align(8) per default Point p1; // offset 0, size 2, (alignment 1) byte x; // alignment 1, offset 2, size 1, padding before: 0 Point2 p2; // alignment 2, offset 4, size 10, padding before: 1 }; // size 14, alignment (of the struct) 2__size_of(struct Points); // returns 14 __alignment_of(struct Points); // returns 2 __offset_of(struct Points, p1); // returns 0 __offset_of(struct Points, x); // returns 2 __offset_of(struct Points, p2); // returns 4

5 對象類型

除了以上介紹的基礎(chǔ)數(shù)據(jù)類型,CAPL還提供了一些CANoe特有的對象類型來幫助用戶快速完成仿真測試功能的開發(fā)。

CAN messages

CAPL提供了各種網(wǎng)絡(luò)對應(yīng)的報文類。本文以CAN message為例進(jìn)行介紹。 報文變量定義格式:

message + message ID/message name + variable

使用message關(guān)鍵字來聲明一個報文變量,message后是message ID或CANoe工程導(dǎo)入DBC后的message name,然后是在CAPL程序中要使用的報文變量名。

message 0xA m1; //定義一個ID為0xA的報文變量m1 message 100x m2; //定義一個ID為100的擴(kuò)展幀報文變量m2,ID后的x后綴表示這是一個擴(kuò)展幀 message EngineData m3; //定義一個在DBC中message name為EngineData的報文變量m3 ... output(m1); output(m2); output(m3);

CAPL提供了一系列的選擇器(Selectors)來設(shè)置或讀取CAN message的屬性,例如:

?

example:

message 0x100 msg; //定義一個ID為0x100的message變量msg msg.CAN = 1; //將msg的通道設(shè)置為1 msg.DLC = 2; //將msg的DLC設(shè)置為2 msg.BYTE(0) = 0xAA; //給msg報文數(shù)據(jù)段的第一個byte賦值為0xAA; msg.BYTE(1) = 0xBB; //給msg報文數(shù)據(jù)段的第二個byte賦值為0xBB; output(msg); //將定義好的msg發(fā)送到總線中

?6 定時器變量

CAPL提供兩種定時器變量: timer:基于秒(s)的定時器 msTimer:基于毫秒(ms)的定時器 example:點(diǎn)擊鍵盤'a'后以20ms為周期發(fā)送id為100的報文

msTimer myTimer; //定義一個ms定時器myTimer message 100 msg; ... on key 'a' {setTimer(myTimer,20); //點(diǎn)擊鍵盤'a'將定時器myTimer設(shè)置為20ms,并開始計(jì)時 } ... on timer myTimer { //響應(yīng)定時器事件myTimer,將msg發(fā)送到總線,output(msg);setTimer(myTimer,20); //重新設(shè)置定時器myTimer為20ms }

CANoe教程 | CAPL編程-運(yùn)算符/流程控制

CAPL中算數(shù)運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算以及流程控制語句和C語言一致。?

1 運(yùn)算符

2 流程控制

?

CANoe教程 | CAPL編程 - 事件驅(qū)動

1 事件概述

CAPL是一種面向過程、由事件驅(qū)動的類C語言。

事件驅(qū)動針對于順序執(zhí)行,其區(qū)別如下:

順序執(zhí)行:順序執(zhí)行流程中,子例程或過程函數(shù)按照代碼編寫順序逐句執(zhí)行。

事件驅(qū)動:CAPL程序由事件驅(qū)動,工程運(yùn)行過程中發(fā)生指定的事件時才會運(yùn)行相應(yīng)的事件處理函數(shù)。

順序執(zhí)行VS事件驅(qū)動

在CAPL中添加事件處理函數(shù):?

重要的事件處理函數(shù):

事件總覽:?[3]

2 事件詳解

事件起始關(guān)鍵字 on

on后加某種事件,工程運(yùn)行時條件觸發(fā),則執(zhí)行函數(shù)體內(nèi)的語句。

關(guān)鍵字this

系統(tǒng)變量、環(huán)境變量或CAN報文事件中,可以用this關(guān)鍵字訪問其指代的數(shù)據(jù)內(nèi)容,如:

on envvar Switch { // Declare a CAN message to be transmitteed message Controller msg;// Read out the value of the switch // Assign to the signal Stop msg.Stop = getvalue(this); // Output the message on the bus output(msg); }

系統(tǒng)事件

系統(tǒng)事件主要用于處理CANoe測量系統(tǒng)的控制功能,主要有on start、on preStart、onstopMeasurement、on preStop、on key<newKey>以及on timer


系統(tǒng)事件Example:

//on preStart procedureon preStart {write("Measurement started!");msg_Count = 0; }//on start procedureon start {write("start Node A");setTimer(cycTimer,20);CallAllOnEnvVar(); // CANoe only }//on preStop procedureon preStop {message ShutdownReq m;output(m);DeferStop(1000); }//on stopMeasurement procedureon stopMeasurement {write("Message 0x%x received: %d", msg.id, msg_Count); }

CAN控制器事件

當(dāng)CAN控制器或錯誤計(jì)數(shù)器狀態(tài)變化時調(diào)用CAN控制器事件。

CAN控制器事件Example:

//on errorPassive procedure on errorPassive {...write("CAN Controller is in errorPassive state")write(" errorCountTX = %d", this.errorCountTX);write(" errorCountRX = %d", this.errorCountRX); };//on busOff procedure on 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報文/信號事件

CAN報文或信號變化時調(diào)用報文/信號事件。

CAN報文/信號事件

報文事件:

信號事件:

on signal LightSwitch::OnOff {v1 = this.raw;v2 = $LightSwitch::OnOff.raw; }

定時器事件

定義好定時器變量后,由SetTimer函數(shù)設(shè)置定時器間隔并啟動定時器。當(dāng)定時器運(yùn)行到設(shè)定的時間間隔時觸發(fā)定時器事件,并執(zhí)行on timer函數(shù)體中的程序。

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

鍵盤事件

通過定義鍵盤事件,用戶可以在工程運(yùn)行時通過點(diǎn)擊鍵盤觸發(fā)預(yù)先定義的行為。這在實(shí)際開發(fā)和測試時非常常用。比如用戶可以在任意時刻向總線發(fā)送特定的消息、改變信號或系統(tǒng)變量的值或是啟動停止測量。

系統(tǒng)變量/環(huán)境變量事件

系統(tǒng)變量和環(huán)境變量事件分別是對系統(tǒng)變量和環(huán)境變量發(fā)生變化時的響應(yīng)。

系統(tǒng)變量事件:

on sysvar IO::DI_0 { $Gateway::IOValue = @this; }

環(huán)境變量事件

on envvar Switch { // Declare a CAN message to be transmitteed message Controller msg;// Read out the value of the switch // Assign to the signal Stop msg.Stop = getvalue(this); // Output the message on the bus output(msg); }

?

CANoe教程 | CAPL編程 - 實(shí)用CAPL代碼片段

本文根據(jù)CAPL編程中經(jīng)常遇到的案例場景整理簡潔通用的代碼片段。

1 周期消息發(fā)送

無論是Simulation Setup中的仿真節(jié)點(diǎn)還是Test Setup中的Test Module所關(guān)聯(lián)的CAPL腳本在做仿真或測試時都經(jīng)常需要向總線模擬發(fā)送周期消息。

點(diǎn)擊鍵盤按鍵 'a' 后向總線發(fā)送周期為20ms的can 消息msg:

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

2 應(yīng)用報文Request/Response測試

ECU通常都有很多請求/應(yīng)答式的功能,比如BCM可以接收用戶點(diǎn)擊車窗、雨刮、遮陽簾等車身相關(guān)硬件的控制按鈕向總線發(fā)出的開關(guān)請求(Request),然后由BCM向總線發(fā)出響應(yīng)消息,并控制車窗、雨刮、遮陽簾等做出相應(yīng)的反饋動作(Response)。

下面以測試BCM雨刮開關(guān)功能為例進(jìn)行Request/Response測試。

DBC定義:

Signal NameMessage NameSignal Value Description
WiperRequestBCM_RequestOff : 0
On : 1
WiperResponseBCM_ResponseOff : 0
On : 1

參考代碼:

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); //測試雨刮關(guān)閉功能Check_Wiper_Feature(1,1); //測試雨刮開啟功能TestGroupEnd(); } //Wiper Feature testcase testcase Check_Wiper_Feature(int request, int response ) {tBCM_Request.WiperRequest.phys = request;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 檢測總線中周期報文的發(fā)送周期是否在給定范圍內(nèi)

TSL提供了兩組函數(shù)用于測試周期報文:

一組使用相對時間因子,當(dāng)周期小于 (aMinRelCycleTime * GenMsgCycleTime)或大于(aMaxRelCycleTime* GenMsgCycleTime)時產(chǎn)生事件。

函數(shù)原型:

dword ChkCreate_MsgRelCycleTimeViolation (Message aObservedMessage, double aMinRelCycleTime, double aMaxRelCycleTime, Callback aCallback);dword ChkStart_MsgRelCycleTimeViolation (Message aObservedMessage, double aMinRelCycleTime, double aMaxRelCycleTime, Callback aCallback);

另一組使用絕對時間參數(shù),當(dāng)周期小于 aMinCycleTime 或大于 aMaxCycleTime 時產(chǎn)生事件。

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); }

測試報告中設(shè)置的命令如下,請您自行查閱CANoe幫助文檔,或者查找自帶的模板。

TestModuleTitle ("Test BCM Features");\\測試報告標(biāo)題。TestModuleDescription ("Check all features in BCM.");\\測試報告描述。

輸出的測試報告如下圖所示:

如上圖所示,測試報告展示了錯誤事件產(chǎn)生的次數(shù)以及錯誤事件所處的事件范圍。

4 統(tǒng)一診斷測試(UDS)

診斷測試經(jīng)常需要進(jìn)行切換session,22/2E讀寫等request/response式的操作,CANoe Demo工程UDSBasic.cfg中Simulation Setup窗口里的TestModule節(jié)點(diǎn)關(guān)聯(lián)的CAPL腳本為我們提供了一個很好的參考模板:

參考代碼:

/*@!Encoding:1252*/ // -------------------------------------------------- // Simple test module for automated tests. // For the sake of simplicity, this example omits // security access mechanisms, especially for the // write services. In some cases, return parameters // are not checked. // // CANoe 10.0 and higher // --------------------------------------------------includes {// As this is a test module, neither including the CAPL callback interface nor adding// the corresponding transport protocol node layer DLL is necessary, because in this case,// the "built-in" diagnostic channel of CANoe can be used. }variables {enum bool {true=1, false=0};const cAccessModeNumerical=0;const cAccessModePhysical=1;const cAccessModeCoded=2;const test_vehicle_Speed_kmh = 40.0;// This timeout is used just to force CANoe to continue, i.e. normally a TestWaitForDiag...// function will return much earlier due to diagnostic level timing!const cApplicationTimeoutMs = 5000; char gTestIdStr[10]; // Test step ID for test reportword gTestCaseIndex=0;word gTestStepIndex=0;char gResultString[200]; // String for temporary test step result outputs }// Set and increment test step ID for test report updateTestIdStr() {snprintf(gTestIdStr, elcount(gTestIdStr), "%d.%d", gTestCaseIndex, gTestStepIndex); }setTestId(word tcIndex, word tsIndex) {gTestCaseIndex=tcIndex;gTestStepIndex=tsIndex;updateTestIdStr(); }incTestStepId() {gTestStepIndex++;updateTestIdStr(); }word SendRequestAndWaitForResponse(diagRequest *req, enum bool posResponseExpected) {long ret;// Trigger sending the requestif (0 > (ret=req.SendRequest())) { snprintf(gResultString, elcount(gResultString), "Trigger sending the request failed (Return code=%d)!", ret);testStepFail(gTestIdStr, gResultString);return 0;}testStepPass(gTestIdStr, "Trigger sending the request succeded.");incTestStepId();// Wait until the complete request has been sent, e.g. in case of long requests which spread over several messages (segmented message)if (1!=(ret=testWaitForDiagRequestSent(req, cApplicationTimeoutMs))){ snprintf(gResultString, elcount(gResultString), "Failed to finish sending the request (Return code=%d)!", ret);testStepFail(gTestIdStr, gResultString);return 0;}testStepPass(gTestIdStr, "Request was sent successfully.");incTestStepId();// Wait until the complete response has been received, e.g. segmented messages might take some time for transmissionif (1!=(ret=testWaitForDiagResponse(req, cApplicationTimeoutMs))) { snprintf(gResultString, elcount(gResultString), "Valid response missing or received too late (Return code=%d)!", ret);testStepFail(gTestIdStr, gResultString);return 0;}testStepPass(gTestIdStr, "Response received successfully.");incTestStepId();// Check whether the response was a positive responseif (-1==(ret=diagGetLastResponseCode(req))) {if (!posResponseExpected) {snprintf(gResultString, elcount(gResultString), "Positive response received although negative response was expected!");testStepFail(gTestIdStr, gResultString);return 0;}testStepPass(gTestIdStr, "Positive Response received as expected.");}else if (ret>0) {if (posResponseExpected) {snprintf(gResultString, elcount(gResultString), "Negative response received (NRC=0x%02x) although positive response was expected!", ret);testStepFail(gTestIdStr, gResultString);return 0;}testStepPass(gTestIdStr, "Negative Response received as expected (NRC=%d).", ret);}return 1; }// Check whether writing the vehicle speed parameter is done correctly by reading its value after writing testcase tcWriteAndReadVehicleSpeed() {diagRequest Door.Variant_Coding_Write req_write;diagRequest Door.Variant_Coding_Read req_read;double ret;word testCaseIndex; setTestId(1,1);TestStep(gTestIdStr, "Writing variant coding");if (0>req_write.SetParameter(cAccessModePhysical, "Codingstring.VehicleSpeedToLockDoor", test_vehicle_Speed_kmh)) {testStepFail(gTestIdStr, "Could not set parameter 'VehicleSpeedToLockDoor' in write request!");}else {if (0>req_write.SetParameter("Codingstring.VehicleType", "Sedan")) {testStepFail(gTestIdStr, "Could not set parameter 'VehicleType' in write request!");}else {sendRequestAndWaitForResponse(req_write, true);}}incTestStepId();TestStep(gTestIdStr, "Reading variant coding");if (sendRequestAndWaitForResponse(req_read, true)) {incTestStepId();ret=req_read.GetRespParameter(cAccessModePhysical, "Codingstring.VehicleSpeedToLockDoor");if (test_vehicle_Speed_kmh == ret) {testStepPass(gTestIdStr, "VehicleSpeedToLockDoor read as expected!");}else {testStepFail(gTestIdStr, "Read VehicleSpeedToLockDoor value is wrong (value=%f)!", ret);}} }void MainTest () {tcWriteAndReadVehicleSpeed(); }

CANoe提供的Demo工程是學(xué)習(xí)CANoe最好的資源,熟悉以上示例代碼已經(jīng)能夠幫助我們開發(fā)出大部分診斷測試case。

?

?

總結(jié)

以上是生活随笔為你收集整理的CANoe教程:CAPL编程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。