从代码角度看CAN网络层协议 ISO 15765-2

Posted 蚂蚁小兵

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从代码角度看CAN网络层协议 ISO 15765-2相关的知识,希望对你有一定的参考价值。

相关文章

从代码角度看CAN网络层协议 ISO 15765-2(一)

系列用的CANoe演示工程我放在了Git上,不定时根据博客更新。

CANoe-Demn


前言

  • 测试软硬件环境:
    CANoe 11 SP2
    Win10 X64
    ISO 15765-2 -2016

  • ISO 15765-2 是TP层的规范,在上一节博客内容中,我们了解了标准的重要文档内容,下面我们通过代码的方式进一步了解下多帧传输的参数


文章目录


固定配置N_PCI参数


下图是一个CANoe工程中加载了CDD文件的 TP层配置参数和一段对应的真实Trace,


动态配置N_PCI参数


在做工程中正常我们加载cdd,可以正常做诊断,但是我们在做TP测试的时候,就需要我们拿掉cdd文件,使用底层函数测试了。
下面我们就按照TP测试,来熟悉下TP层的底层函数。

本次测试根据真实ECU,我们新建个CAN工程,并配置好通信波特率(CAN-FD),下图所示连接号通道和配置好波特率,就能正常收到ECU发送的报文了,
NOTE:测试所用ECU,无需网络唤醒,上电即通信。


①, 新建一个Network Node

新建一个TP_Test.can 文件,并在Components里面导入OSEK_TP.dll


② ,先定义以下代码 将Tester和 ECU 建立连接

variables

  const long sysTxIdentifier = 0x72E; //Tester的物理地址ID
  const long sysRxIdentifier = 0x73E; //真实ECU的物理地址ID
  long gHandleConn1;
  long dbHandle;


on start

  InitConn();

InitConn()
  
  //连个ID 建立连接
  dbHandle = CanTpGetDBConnection();
  write("**************dbHandle:%d**************",dbHandle);  
  if (dbHandle > 0) 
  
    CanTpCloseConnection(dbHandle);
  
  gHandleConn1 = CanTpCreateConnection(0); // Normal mode
  write("**************gHandleConn1:%d**************",gHandleConn1);
  
  CanTpSetTxIdentifier(gHandleConn1, sysTxIdentifier);
  CanTpSetRxIdentifier(gHandleConn1, sysRxIdentifier);
  CanTpSetMaxCANFDFrameLength( gHandleConn1,8); // 因为测试使用的ECU 是基于CAN-FD ,并且DL =8 ,所以需要设置
  //CanTpSetBitRateSwitch( gHandleConn1,0);



on key 'a' 

  byte txDataBuffer[2]=0x19,0x0A;
  write("**************press key a**************");
  CanTpSendData(gHandleConn1, txDataBuffer, 2); 


按键‘a’ 里面的代码发送 0x19 0x0A读取ECU支持的DTC.
按键‘a’ ,可以看出响应的Trace,这说明以上代码Tester 和 ECU建立连接是成功的。
流控的参数和填充 都是默认的,后面我们再看具体的设置函数
上面的代码用到的函数在help文档中都有,这里就不一一展开细讲了。


③ ,添加回调函数

如下,我们在上面的代码基础上,添加4个回调函数,可以监控到传输的细节

//以下4个都是回调函数
void CanTp_SendCon( long connHandle, dword count) //发送成功后会调起此函数

  write( "Transmission of %d byte on connection %d successful"
  , count, connHandle);

void CanTp_FirstFrameInd( long connHandle, dword length)//发送成功后会调起此函数

  write("Peer has started transfer of %d byte on connection %d"
  , length, connHandle);
 
void CanTp_ReceptionInd( long connHandle, byte data[])//接收到报文会调起此函数

  write( "Received %d byte on connection %d: [%02x] ..." 
  , elcount( data), connHandle, data[0]);


void CanTp_ErrorInd( long connHandle, long error) //连接过程中报错会调起此函数

  write( "Error %d for connection %d", error, connHandle);



再次按键‘a’ ,根据write 窗口的打印信息,理解下回调函数的执行过程


④ ,设置 流控帧参数(发送方 是单帧)

如下,我们在上面的代码基础上,列出流控帧控制的参数

on key 'b' 

   //设置流控帧参数的函数
    CanTpSetPadding(gHandleConn1, 0xff);
    write( "Padding value = 0x%x", CanTpGetPadding(gHandleConn1));

    CanTpSetBlockSize(gHandleConn1, 0x00);
    write( "Block size = 0x%x", CanTpGetBlockSize(gHandleConn1));

    CanTpSetSTmin(gHandleConn1, 50);
    write( "ST min = %d", CanTpGetSTmin(gHandleConn1));



先按按键‘b’, 再次按键‘a’ ,根据write 窗口的打印信息,对比下流控帧参数的变化

注意我们发送0x19 0A 是单帧,ECU响应的是多帧, 流控帧是我们发出的,约束的是ECU的连续帧的行为
ECU是可以根据自身情况,是否根据流控帧的内容进行传输的,比如下面trace就说明了BS参数奏效了,但是STmin 并没有按照我们设置的进行传输


⑤,设置 流控帧参数 (发送方是多帧)

如下,我们在上面的代码基础上,我们再进一步增加测试代码,我们仿真下 发送方为多帧,ECU发送流控帧的情况
on key ‘c’ 里面发送100个字节,内容是乱写的,不影响作为多帧观察

on key 'c' 

  byte txDataBuffer[100]=0x2e,0x2;
  write("**************press key a**************");
  CanTpSendData(gHandleConn1, txDataBuffer, elCount(txDataBuffer)); 

on key 'd' 

    //设置流控帧参数的函数
    CanTpUseFlowControlFrames(gHandleConn1,1);//是否使用流控帧参数进行传输,1是使用
    write("Use flow control = %d",CanTpIsUseFlowControlFrames(gHandleConn1));
   //设置填充
    CanTpSetPadding(gHandleConn1, 0xff);
    write( "Padding value = 0x%x", CanTpGetPadding(gHandleConn1));


先按按键‘d’, 再次按键‘c’ ,根据Trace的打印信息,代码中使用流控帧的参数传输,所以我们发送的规则必须按照流控帧的参数来


如下,我们在上面的代码基础上,我们将 on key 'd' 的内容改成如下代码,不使用 ECU发送的流控帧参数,使用自己设置的参数

Note : 由于 ECU响应的BS=0,所以 BS参数没法去测试,可以测试 STmin 参数

on key 'd' 

    //设置流控帧参数的函数
    CanTpUseFlowControlFrames(gHandleConn1,0);//是否使用流控帧参数进行传输,1是使用
    write("Use flow control = %d",CanTpIsUseFlowControlFrames(gHandleConn1));

    CanTpSetSTmin(gHandleConn1, 20);
    write( "ST min = %d", CanTpGetSTmin(gHandleConn1));

    CanTpUseFlowControlSTmin( gHandleConn1, 0);
    write("Use FSTmin = %d", CanTpIsUseFlowControlSTmin(gHandleConn1));

   //设置填充
    CanTpSetPadding(gHandleConn1, 0xff);
    write( "Padding value = 0x%x", CanTpGetPadding(gHandleConn1));



动态配置 网络层时间参数

添加如下代码,可以设置和读取网络层定时参数。

on key 'e' 

    //CanTpSetTimeoutAr(gHandleConn1,1000);
    write( "Ar_ms value = %d", CanTpGetTimeoutAr(gHandleConn1));
    write( "As_ms value = %d", CanTpGetTimeoutAs(gHandleConn1));
    write( "Br_ms value = %d", CanTpGetTimeBr(gHandleConn1));
    write( "Bs_ms value = %d", CanTpGetTimeoutBs(gHandleConn1));
    write( "Br_ms value = %d", CanTpGetTimeBr(gHandleConn1));
    write( "Cr_ms value = %d", CanTpGetTimeoutCr(gHandleConn1));


总结

本章博客进一步理解ISO-15756-2多帧传输的意义,以及 通过OSEK_TP.dll的 简单应用可以动态设置 TP层的各种传输参数

OSEK_TP.dll是一个函数库,函数众多,本博客通过一个简单的实例了解其中重要的几个函数,进一步的学习可以参考官方Help文档

  • 要有最朴素的生活,最遥远的梦想,即使明天天寒地冻,路遥马亡!
  • 如果这篇博客对你有帮助,请 “点赞” “评论”“收藏”一键三连 哦!码字不易,大家的支持就是我坚持下去的动力。

以上是关于从代码角度看CAN网络层协议 ISO 15765-2的主要内容,如果未能解决你的问题,请参考以下文章

UDS诊断网络层ISO15765-2(CAN)

网络层协议数据单元-N_PDU(地址格式)

请问汽车can总线分析工具怎么用?

如何看懂UDS诊断报文

关于ISO 15765-2的解读

如何看懂UDS诊断报文