失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > CANOE入门:CAPL语言实现诊断发送和接收

CANOE入门:CAPL语言实现诊断发送和接收

时间:2020-02-19 05:58:21

相关推荐

CANOE入门:CAPL语言实现诊断发送和接收

目录

什么是诊断

CAPL诊断发送

CAPL接收

完整示例

什么是诊断

诊断,就是通过问和听的方式,也即发送和接收信号的方式,发送一条指定ID的CAN报文,ECU接收到后回应另一条指定ID的报文来确认当前ECU的相关信息,诊断的本质也是CAN上面的一条报文。在汽车测试中,诊断是非常重要的功能。与ECU相关的信息大部份是通过诊断的方式获取的,比如说,当前ECU软件版本号,ECU工作状态等等。在CAPL中,操作ECU的方式,就是发送一条CAN报文,再接收指定的报文实现诊断功能。CANoe软件中有诊断功能,但是当需要批量测试诊断功能就需要CAPL语言来做了。同时也可通过诊断功能实现自动化测试,如清除ECU中的配置信息,更改VIN码之类的功能。

CAPL诊断发送

CAPL中实现发送诊断请求的功能一般情况以下有两种方式:

通过发送message的方式实现通过调cdd文件中已定义好的诊断功能实现发送诊断

这里主要以第二种方法为示例讲解。示例代码如下:

/*@!Encoding:936*/includes{}variables{// GAC.ReadVIN 表示名为GAC的cdd文件中名为ReadVIN的诊断方法diagRequest GAC.ReadVIN ReadVin; //发送的did结构体}//发送didon key 'd'{diagSendRequest(ReadVin); //发送诊断请求write("已发送诊断请求....");}

由上面的示例可以知道,发送诊断请求,只需定义diagRequest对象和调用diagSendRequest()函数即可以。上面的示例代码是通过键盘事件触发的,实际使用时,也可以通过其他的事件触发。需要强调说明的是所有定义的diagRequest对象都需要在cdd文件中提前定义好。

CAPL接收

CAPL中,诊断接收可以通过on diagResponse *事件进行接收,也可以通过具体诊断报文进行接收,如 on diagResponse GAC.ReadVIN,其中GAC.ReadVIN就是cdd库文件定文的诊断方法。这两种方式本质上是同一种,只不过一种是无差别接收,另一种是精准接收。代码示例如下:

on diagResponse *{byte data[20]; //响应数据接收数组int size; //响应数据长度变量diagResponse * resp; // 声明无具体解释的回应(即操作句柄)size=this.GetPrimitiveSize(); // 获取响应数据的长度this.GetPrimitiveData(data,elcount(data)); // 将实际响应复制到数组中//通过遍历的方式打印数据for(k=0;k<size;k++){ write("data[%d] = %x",k,data[k]);}}

上面就是最简单的诊断接收示例,需要注意的是,接收到的数据类型为byte[],需要将其转换为对应的类型才能进行下一步操作。

完整示例

实现功能:通过CAPL发送一个诊断,读取ECU中的vin码,再将响应的vin码写入到txt文件中。

/*@!Encoding:936*/includes{}variables{diagRequest GAC.ReadVIN ReadVin; //发送的did结构体char out_char_array[60]; //诊断响应接收变量int k;dword glbHandle= 0; //文件操作句柄long glbValue;}//发送didon key 'd'{diagSendRequest(ReadVin);//发送诊断请求write("d");}//诊断结果响应on diagResponse *{long ret; //字符串写入结果接收变量byte data[20];int size;double param_value1=0xFF;double param_value2=0xFF;diagResponse * resp; // 声明无具体解释的回应size=this.GetPrimitiveSize(); // 获取响应数据的长度this.GetPrimitiveData(data,elcount(data)); // 将实际响应从“on diagResponse*”复制到数据阵列中for(k=0;k<20;k++){ //通过遍历的方式打印数据write("data[%d] = %x",k,data[k]);}write("%d",size);GBF_Convert_ByteArrToHexStr(data,size,out_char_array); write("outr=%s",out_char_array);//设置文件目录,2表明可以对这个目录下的文件可读可写setFilePath(".//TestModule", 2);//模式为2,表示追加模式,发生错误则返回0否则文件打开成功glbHandle = openFileWrite ("out.txt",2); if ( glbHandle!=0 ){//写入字符串,发生错误则返回0,徜则返回1ret = filePutString(out_char_array, strlen(out_char_array), glbHandle); if(ret){write ("write ok."); //在Wirte窗口打印成功提示fileClose (glbHandle); //关闭文件}else{write ("write error.");//在Wirte窗口打印失败提示fileClose(glbHandle);//关闭文件} } }//byte[]转char[]函数byte GBF_Convert_ByteArrToHexStr(byte rawData[], int datalen,char outHexStr[]){int gcOk = 0;int gcNok = 0;int i;int hexLength;int byteIndex;byte tmpVal;byte retVal;char tmpStr[60];char tmpErrStr[60];byte dataType = 2;// Init to failedretVal = gcNok; // Reset output arrayfor (i = 0; i < elcount(outHexStr); i++){outHexStr[i] = 0;}// get the hex lengthhexLength = datalen * dataType;//check that the supplied output array can hold the hex string if ( elcount(outHexStr) < hexLength ){snprintf(tmpErrStr, elcount(tmpErrStr), "GBF_ConvertIntArrToHexStr: ERROR: char array to small, Hex Data is %d but outHexStr only contains %d elements!", hexLength, elcount(outHexStr));}else { write("hexLength == %d",hexLength);//All checks went fine, convert datafor (i = 0; i < hexLength; i++){byteIndex = i / dataType;tmpVal = ((byte)(rawData[byteIndex] >> (4 * (dataType -1 - (i % dataType))))) & 0x0F;snprintf(tmpStr,elcount(tmpStr),"%X",tmpVal);strncat(outHexStr,tmpStr,elcount(outHexStr));if(i % dataType == dataType-1){write("outHexStr = %d",strlen(outHexStr));strncat(outHexStr,"",elcount(outHexStr));}}retVal = gcOk;}return retVal;}

如果觉得《CANOE入门:CAPL语言实现诊断发送和接收》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。