正常报文(on message)
on message 可以 如下图所示,可以对单个报文,多个报文,所有报文监控。
message在 CAPL中是一种数据类型,所以他有自己的属性和方法。可以通过 this.xxx来访问message的属性:
下面通过代码随便选取获取message的属性
on message 0x189
{
write("this.id = %x",this.id);//获取报文ID
write("this.name = %s",this.name);//获取报文名字
write("this.can = %d",this.can);//获取当前报文在哪路can上
write("this.dir = %d",this.dir);//获取当前报文是TX还是RX
write("this.dlc = %d",this.dlc);//获取当前报文的报文长度
write("this.dlc = %x",this.Byte(0));//获取当前报文的第一个字节
write("this.dlc = %x",this.QWord(0));//获取当前报文的第一个QWord(8个字节)
}
//下面是在trace中截取的 0x189报文信息
Time Channel Name Slot Payload Type Cycle Dir Length Frame State Frame State (Ab.) Schedule Sync Flag PP Flag Header CRC Startup Flag
[+] 2.973424 CAN 2 message_1 189 2B AE 00 00 00 00 00 00 CAN Frame Tx 8 3.214 ms
对应打印的输出结果:
this.id = 189
this.name = message_1
this.can = 2
this.dir = 0
this.dlc = 8
this.dlc = 2b
this.dlc = ae2b
错误报文(on errorFrame)
The error frame handler is called after receiving an Error Frame or an Overload Frame.
当收到一个错误报文或者过载报文的时候触发这个事件。
同 on message一样 ,on errorFrame 也有很多属性
下面代码简单介绍下属性:
on errorFrame
{
write("this.time = %fs",this.time/100000.0);//获取时间戳,时间单位是秒
write("this.id = 0x%x",this.ID);
write("this.ErrorPosition_Bit = %d",this.ErrorPosition_Bit);
write("this.ErrorCode = 0x%x",this.ErrorCode);
}
下面是在Trace中出现的一帧错误报文:有ErrorCode,ErrorPosition_Bit,ID等参数,我们在 脚本中打印出来,进行比对下:
输出结果:
this.time = 0.359260s
this.id = 0x30
this.ErrorPosition_Bit = 99
this.ErrorCode = 0x11d9
一个报文报错,最重要的就是要知道因为什么报的错,下面是errorCode对照表:
总共两个字节,0-4 bits没用 ,14-15没用,其它都有定义,因为我这里用的环境是canoe的环境,就使用左边的对照表。
上面的输出结果this.ErrorCode = 0x11d9 :展开成二进制就是 :0001000111001001 因为 0-4 bits没用 ,14-15没用,所以可以写成 xx010001110xxxxx这个结果是和Trace中的截图 ECC的结果是一致的。
下面的代码是Vector提供的官方标准代码,直接放在脚本中就可以使用:
on errorFrame
{
const int bufferSize = 256;
char buffer[bufferSize];
char cdirection[2][3] = {"RX", "TX"};
int ndir;
word ecc;
word extInfo;
int isProtocolException;
ecc = (this.ErrorCode >> 6) & 0x3f;
extInfo = (this.ErrorCode >> 12) & 0x3;
isProtocolException = (this.ErrorCode & (1 << 15)) != 0;
ndir = extInfo == 0 || extInfo == 2 ? 0 : 1; //set ndir to 0 for RX and to 1 for TX
if(this.CtrlType == 1){
//SJA1000 specific
switch (ecc){
case 0: snprintf(buffer, bufferSize, "Bit error"); break;
case 1: snprintf(buffer, bufferSize, "Form error"); break;
case 2: snprintf(buffer, bufferSize, "Stuff error"); break;
case 3: snprintf(buffer, bufferSize, "Other error"); break;
default: snprintf(buffer, bufferSize, "Unknown error code");
}
}
else if(this.CtrlType == 2){
//CAN core specific
switch (ecc){
case 0: snprintf(buffer, bufferSize, "Bit error"); break;
case 1: snprintf(buffer, bufferSize, "Form error"); break;
case 2: snprintf(buffer, bufferSize, "Stuff error"); break;
case 3: snprintf(buffer, bufferSize, "Other error"); break;
case 4: snprintf(buffer, bufferSize, "CRC error"); break;
case 5: snprintf(buffer, bufferSize, "ACK Del. error"); break;
case 7:
{
switch (extInfo){
case 0: snprintf(buffer, bufferSize, "RX NACK error (recessive error flag)"); break;
case 1: snprintf(buffer, bufferSize, "TX NACK error (recessive error flag)"); break;
case 2: snprintf(buffer, bufferSize, "RX NACK error (dominant error flag)"); break;
case 3: snprintf(buffer, bufferSize, "TX NACK error (dominant error flag)"); break;
}
break;
}
case 8: snprintf(buffer, bufferSize, "Overload frame"); break;
case 9: snprintf(buffer, bufferSize, "FDF or res recessive"); break; //protocol exception specific
default: snprintf(buffer, bufferSize, "Unknown error code"); break;
}
}
else snprintf(buffer, bufferSize, "Unsupported CAN controller");
if(isProtocolException){
write("Protocol exception on CAN%d at %fs: %s", this.can, this.time/1e5, buffer);
}
else{
write("%s error frame on CAN%d at %fs: %s", cdirection[ndir], this.can, this.time/1e5, buffer);
}
}