CAN总线之ISO15765协议

时间:2022-07-24
本文章向大家介绍CAN总线之ISO15765协议,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

ISO 15765协议是一种CAN总线上的诊断协议。其中ISO 15765-1包括物理层和数据链路层,ISO 15765-2对网络层进行说明,ISO 15765-3则是规定到应用层的具体服务。

下面重点看下网络层,根据ISO 15765-2中的定义,网络层的功能是接收到应用层发送过来的消息流后,根据定义中的分包、位填充和时间控制等步骤,对消息流进行控制传输。流控制输有单帧传输、多帧传输两种类型,根据传输数据的长度进行帧传输方式的选择。

相反当接收到来自诊断仪的数据时,网络层完成的是一个组包的过程,这时需要一个可以存放接收的缓冲区。单帧的组包相对简单,而接收到多帧数据则根据接收到的首帧和连续帧的数据域提取,后按照排列顺序重新组合交给上层的应用层。

ISO 15765网络层的功能主要有:

(1)为上层的应用层提供接口服务

(2)进行内部操作。为上层服务提供接口从而实现数据流;主要有为对等实体间的通信提供分段、重组和流控制这几种方法

(3)网络层中的时间控制。

网络层原语服务分析:

N_PCI 则包含了原语帧的具体信息如:此消息帧属于何种帧类型(单帧、首帧、连续帧)、帧长度等

N_Data为该原语所包含的具体的数据。

网络层内部传输服务,CAN总线上的数据帧没帧只能传输8个字节,ISO 为了适应CAN总线上的数据传输,根据诊断报文数据长度的不同规定了单帧传输和多帧传输两种方式

1.单帧传输

当应用层的诊断服务数据可以利用单帧CAN数据传送时,可采用单帧传送方式

2.多帧传输

多帧传送方式中,网络层根据需要,将诊断数据进行拆分成一个首帧和多个连续帧。首帧包括了分段数据的总长度信息以及一些数据帧;每个连续帧的第一个字节包含拆分的顺序编号,后面的七个字节用于存放诊断数据。接收端在接收到连续帧后根据接收数据帧的编号重组服务数据。

发送端和接收端通过N_PCI确认发送或者接收的帧为首帧、流控帧还是连续帧,

接收端通过对接收到数据帧的第一个字节进行分析就可以得出所接收到的数据帧为何种数据帧,以及所要接收的数据长度

接收的数据第一个字节的高四位为0则表示所接收的数据帧为单帧,再通过读取低四位以确定单帧数据中的有效字节长度

接收的数据的第一个字节为高四位为1则表示所接收的数据帧为多帧的首帧。再读取第四位和第二个字节后确认所需要接收的字节数后,根据接收的能力和双方通信的速率发送流控帧,然后等待多帧连续的到来。

接收的数据第一个字节的高四位为2则表示所接收的数据帧为多帧连续帧。然后在对SN连续帧编号之后的数据放入接收缓冲区

接收的数据第一个字节的高四位为3,则表示接收的数据帧为流控帧。低四位的FS表示所发送端所需要进行的动作,BS为能够发送连续帧的数据,STmin为每两帧的时间间隔。

网络层时间控制分析

网络层时间管理是为了保证发送端和接收端不会因为等待而永久挂起,从而失去通信能力,因此每次通话的过程中设置了超时的时间参数

N_As:发送端将数据传送到接收端的最大时间

N_Bs:发送端在成功发送首帧后到接收到流控帧的最大时间

N_Br:接收端在接收到首帧后到发送流控制的最大时间。

N_Ar:接收端将流控制传送到发送端的最大时间。

N_Cr :接收端在发送成功流控制后到收到连续帧的最大时间

Ttan:每帧传输时间。

STmin:连续帧之间的最小发送时间间隔。

根据这个传输流程我们可以得到诊断报文的传输延迟的公式:

T=N_As+N_Bs+N_Cr-Tan+(Ttan+STmin)N-STmin

附加一段相关伪代码:

if(接收长度!=内容长度)
{
  
    for(i=内容长度;i<接收长度;i++)//比较实际内容长度外的部分是否因为补0,不相等
	   {
		    if(OBDReceBuf[i]==0)
					 break;
				else
					 return ;		 
		 
		 }
}

if((change0.byte.LL>0x20)&&(Frames_remain!=0))
{
  count++;
	Frames_remain--;//还需要接收的剩余帧次数
	tmp = change0.byte.LL & 0x0F;
	 p = (INT8U *)&p_caninfo->DATAA;
	if(T5ms-FirstTime<STmin) return;//如果不在规定时间内接收到数据,返回
	if(count==1) SN[0]=*p;//记录第一个序列号
	if(*p+1==(SN[0]+ count))	
	   FirstTime=T5ms;//记录上一次收到连续帧的时间
   memcpy(OBDReceBuf+1+tmp*7, &p[1], 7);//接收数据
	if(Frames_remain==0){
  
       DIAG_ReceOver_Flag=1;
     }
        else{
            DIAG_ReceOver_Flag=0;
      }
}
if((change0.byte.LL&0xF0)==0x30)
{
   p = (INT8U *)&p_caninfo->DATAA; 
	 STmin=*p+2;
}

	case CAN_LINK_SEND_DATA:
			 if(T5ms-can_lind_time<STmin) return 0;//连续发送的数据满足最小时间间隔