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结构体
}

//发送did
on 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

上面就是最简单的诊断接收示例,需要注意的是,接收到的数据类型为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;
}

//发送did
on 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,徜则返回1
    ret = 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 failed
    retVal = gcNok;   
  
    // Reset output array
    for (i = 0; i < elcount(outHexStr); i++)
    {
        outHexStr[i] = 0;
    }
    // get the hex length
    hexLength = 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 data
        for (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;
}

你可能感兴趣的:(汽车)