从代码角度看CAN网络层协议 ISO 15765-2
Posted 蚂蚁小兵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从代码角度看CAN网络层协议 ISO 15765-2相关的知识,希望对你有一定的参考价值。
相关文章
系列用的CANoe演示工程我放在了Git上,不定时根据博客更新。
前言
-
测试软硬件环境:
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的主要内容,如果未能解决你的问题,请参考以下文章