1. 诊断请求发送基础

任务目标

编写一个CAPL脚本,通过CAN总线向ECU发送UDS诊断请求(读取VIN码,服务ID 0x22,DID 0xF190),并验证是否收到正确的肯定响应。

环境依赖

需要Vector CANoe/CANalyzer环境,并配置好CAN通道(本文以CAN1为例)。诊断请求通过CAPL的diag函数库或原始CAN帧发送均可,本案例采用原始CAN帧方式,不依赖诊断数据库(CDD),便于独立运行。

关键完整代码

/* 诊断请求发送基础 - 读取VIN码 */
variables
{
  const int CAN_CHANNEL = 1;          // CAN通道
  const long ARB_ID_REQ = 0x7E0;      // 物理请求ID(诊断仪->ECU)
  const long ARB_ID_RESP = 0x7E8;     // 物理响应ID(ECU->诊断仪)
  
  // 诊断请求报文:0x22(读取DID) + 0xF1 0x90(VIN DID)
  const byte REQ_DATA[4] = {0x02, 0x22, 0xF1, 0x90};
  
  message CAN1_MSG_REQ = { dlc = 8 };  // 请求报文对象
  message CAN1_MSG_RESP = { dlc = 8 }; // 响应报文对象
  
  byte respData[8];                    // 存储响应数据
  int respCount = 0;                   // 响应计数器
  timer tTimeout;                      // 超时定时器
}

on start
{
  // 配置请求报文
  CAN1_MSG_REQ.id = ARB_ID_REQ;
  CAN1_MSG_REQ.can = CAN_CHANNEL;
  CAN1_MSG_REQ.byte(0) = REQ_DATA[0];  // PCI:单帧,2字节数据
  CAN1_MSG_REQ.byte(1) = REQ_DATA[1];  // SID:0x22
  CAN1_MSG_REQ.byte(2) = REQ_DATA[2];  // DID高字节:0xF1
  CAN1_MSG_REQ.byte(3) = REQ_DATA[3];  // DID低字节:0x90
  // 其余字节默认填充0xCC或0x00,不影响诊断解析
  
  // 发送请求
  output(CAN1_MSG_REQ);
  write("诊断请求已发送:读取VIN (DID 0xF190)");
  
  // 启动500ms超时定时器
  settimer(tTimeout, 500);
}

on message CAN1_MSG_RESP
{
  int i;
  respCount++;
  canceltimer(tTimeout);
  
  // 复制响应数据
  for (i = 0; i < 8; i++)
  {
    respData[i] = this.byte(i);
  }
  
  // 验证响应:检查SID是否为0x62(肯定响应)
  if ((this.byte(1) & 0x3F) == 0x22)  // 0x62 & 0x3F = 0x22
  {
    write("收到肯定响应!响应帧数:%d", respCount);
    write("响应数据:%02x %02x %02x %02x %02x %02x %02x %02x",
          respData[0], respData[1], respData[2], respData[3],
          respData[4], respData[5], respData[6], respData[7]);
    
    // 检查VIN数据长度(PCI字节指示数据长度)
    if (respData[0] > 0x03)
    {
      write("VIN数据长度:%d 字节", respData[0] - 2);
      write("VIN内容(ASCII):");
      for (i = 3; i < respData[0] + 1 && i < 8; i++)
      {
        write("  [%d] 0x%02X = '%c'", i, respData[i], respData[i]);
      }
    }
  }
  else
  {
    write("收到否定响应或错误SID:0x%02X", this.byte(1));
  }
}

on timer tTimeout
{
  write("错误:等待响应超时(500ms),未收到ECU响应");
}

运行与验证方法

运行步骤:

  1. 在CANoe中新建工程,配置CAN1通道连接仿真总线或真实ECU。
  2. 将上述代码粘贴到CAPL Browser中,关联到CAN1网络节点。
  3. 点击“编译”确保无语法错误,然后点击“运行”启动测量。

验证通过条件:

  • 在Write窗口看到“诊断请求已发送”日志。
  • 若ECU正常响应,应看到“收到肯定响应”及响应数据,其中VIN的ASCII字符可读。
  • 若ECU无响应或响应错误,Write窗口会显示超时或否定响应提示。

预期输出(以仿真ECU返回VIN“12345678901234567”为例):

诊断请求已发送:读取VIN (DID 0xF190)
收到肯定响应!响应帧数:1
响应数据:12 62 f1 90 31 32 33 34
VIN数据长度:17 字节
VIN内容(ASCII):
  [3] 0x31 = '1'
  [4] 0x32 = '2'
  ...

注意:实际VIN内容取决于ECU实现,上述仅为格式示例。若VIN超过4字节(单帧最多传6字节数据),ECU会发送多帧响应,本案例仅验证首帧正确性,完整VIN拼接需扩展处理多帧逻辑。