zoukankan      html  css  js  c++  java
  • Kwp2000协议的应用(程序后续篇)

    作者:良知犹存

    转载授权以及围观:欢迎添加微信:becom_me

    总述

    接上篇文章,本篇继续对基于PID解析数据,如何依据J1979的标准进行解析数据

    先给昨天的文章补上一张故障码对照表,昨天分析了如何读取故障码,但是如何把16bit的hex数据转为我们可以解释的故障码,一般各大厂家的维修手册会有显示,第二就是ECU的协议手册里面会进行描述故障码对应的hex数据。

    下面就是部分故障码展示:

     

    四、继续读取ECU常用数据

     

    通过服务ID:0x01 读取整车状态数据:

    从上面可以看到支持的整车的数据的ID 有0x20 0x40 0xC0打头的整段ID

    或者我们也可以通过向ECU发送相应格式的数据,用来解析能够支持的PID有哪些。

     

     

    TEST->ECU (设备端发往ECU请求读取转速的数据)hex:C2 33 F1 01 0C F3

    读取代码如下:仅供参考

    ​
    __packed typedef struct{
      u8 fmt;                 
      u8 tgt;                 
      u8 src;               
      u8 sid;               
    }KlineSend;
    u8 KLineReadrpm(void)/*读发动机转速*/
    {
      KLIN_RecOK = 0;
      u8* p1;
      KlineSend *p = (KlineSend*)malloc(20);
      
      p->fmt = 0xC2;
      p->tgt = 0x33;
      p->src = 0xF1;
      p->sid = 0x01;
      p1=(u8*)&(p->sid);
      *++p1= 0x0C;
      *++p1=CheckSum((u8*)p, sizeof(KlineSend)+1);
      SendBuf_KLin((u8*)p, sizeof(KlineSend)+2);
    ​
      free(p);
      return 0;
    }

     

    ECU ->TEST (ECU 应答设备转速的回复)德尔福hex ::C4 F1 11 41 0C 0000 13

    BOSH ECU回应数据格式 hex:C4 F1 11 41 0C 0000 13

    虽然数据内容有些不同,但是都是符合kwp2000的数据格式,这样对我们来说我们只需要把握数据整体是否能用,再解析关键字即可,不需要一种ECU写一套代码。

     

    其中解析方式可以参照当前协议中ID支持的标准解析方式,我开发的PID都符合J1979的解析方式,所以我就按照如下表进行解析数据。

     

    汽车现在有新的解析标准,大家可以自行查找,这里给大家描述的是一种方法,至于最终开发的产品,请严格按ECU所符合的标准来操作。

    同理:车速的读取信息

    tester ->德尔福ECU hex:C2 33 F1 01 0D F4

    德尔福ECU-> tester hex:83 F1 10 41 0D 23 F5

    读取关键词车速为 0x23

    BOSH ECU回应格式为 hex:C3 F1 11 41 0D 00 13

    读取关键词车速为 0x00

    解析判断代码如下:

        u8 ReceiveReadCommData(u8 *p,u8 len)
    {
      u16 EngRpm,carSpeed;
      switch(*++p)//关键字判断
      {
        case 0x0C:
        {
          EngRpm=((*(((u8*)p)+1))*256+(*(((u8*)p)+2)))/4;
    ​
          break;
        }  
        case 0x0D:
        {
          carSpeed=*(((u8*)p)+1);
          break;
        }
        default:
          break;
        
      }
      return 0;
    }

    但是有些时间我们会遇到读取过来的数据无法使用,那么我们第一要判断的就是否是服务ID不支持,虽然上面可以看到很多ID的解析方式,甚至ECU都会回应你正确的格式,但是有些时候外部接线以及其他原因,我们获得的数据是无法使用的。

    比如车速,如果ECU没有此项功能,ECU则会回复0x12否定代码,示例如下:

    tester->:C233F1010DF4

    ECU ->: 83F1117F011217

    但是有些时候,因为一些原因该功能ECU支持信息回复,但是实际上ECU上硬线并没有连接,所以需要我们及时分辨:

     

    五、读取一体的函数结构

     

    加上昨天现在有几个ID的读取了,昨天没有分享读取的总函数,现在展示一下读取执行的总函数:仅供参考

    KlinSendTimTypeDefTab KlineSendTimTab[KlineTask] =
    {
      { 0, 0, 3   ,  *Tester        },            //用来与ECU保持长连接
      { 0, 0, 1   ,  *KLineReadrpm  },
      { 0, 0, 1   ,  *KLineReadSpeed},
      { 0, 0, 15  ,  *ReadDTC       },
      { 1, 0, 20  ,  *KLineDtcClear },            
    };
    u8 KlineScan(void)
    {
        if(KlinRcvLen()>3)
        {
          
           KlineAnalyz(KlinRcvBuff(), KlinRcvLen());//调用串口接收函数
           memset((u8*)KlinRcvBuff(),0x00, 0xff);
        }
        KLIN_RecOK = 0;
        KlinClsRecvd();
      }
      if (KlineSendIndFlag.flag == 0)
      {
        if (KlineSendIndFlag.init == 1)
        {      
          printf("Klin_init
    ");
          KlineFastInit();
          KlineSendIndFlag.count = 0;
          KlineSendIndFlag.src = 600;
          KlineSendIndFlag.flag = 1;
          
    ​
          (KlineSendIndFlag.cnt > 8)? (KlineSendIndFlag.cnt =0):(KlineSendIndFlag.cnt++);
          if(KlineSendIndFlag.cnt>3&&KlineSendIndFlag.cnt<6)
          {
              KlineSendIndFlag.init =1;
              KlineSendIndFlag.count = 0;
              KlineSendIndFlag.flag =0;
              KlineSendIndFlag.sta=0;/*判断为0*/
          }
          else{
              KlinComInit();  
          }            
    ​
        }
        else
        {
          for (char i = 0; i < sizeof(KlineSendTimTab)/sizeof(KlinSendTimTypeDefTab); i++)
          {
            if (KlineSendTimTab[i].flag == 0)
            {
              KlineSendTimTab[i].flag = 1;
              KlineSendTimTab[i].count = 0;//计算接收时间长度
              KlineSendTimTab[i].p() ;
    ​
              KlineSendIndFlag.flag  = 1;    
              KlineSendIndFlag.count = 0;    
              if(KlineSendIndFlag.cnt)KlineSendIndFlag.cnt =0;  /*转为0*/            
              break;
            }
          }
        }
      }
      return 0;
    }

    这就是我分享的kwp2000解析,还有很多细节操作,实际开发和文字描述上还是差距很多,如有需要欢迎大家联系我与我交流,添加我的微信:become_me。

     

    更多分享,扫码关注我

  • 相关阅读:
    杭电1013-Digitai Root(另解)
    gets()和getchar()还有getch()的区别
    杭电1013-Digitai Root(这是一道考研编程题-天大2015)
    杭电1062-字符串翻转
    杭电2012-素数判定
    杭电2010-水仙花
    杭电1002-A + B Problem II
    【bzoj4008 hnoi2015】 亚瑟王
    【bzoj4572 scoi2016】围棋
    【bzoj4571 scoi2016】美味
  • 原文地址:https://www.cnblogs.com/conscience-remain/p/13091186.html
Copyright © 2011-2022 走看看