CAN15765和1939协议

1. 15765协议介绍

简单的来说,15765协议指的是

基于CAN2.0A/B 协议 (也可以叫做ISO11898协议 -链路层)

硬件接口的 应用层 通讯协议,

它用于实现通用的车辆诊断服务。

ISO11898协议参考下图。

参考搜索到的“CAN总线协议讲解”文档。

它规定了:

1、总线 CAN_H 和 CAN_L 之间要连接120欧姆电阻。

2、CAN总线为隐性时(即逻辑电平为1时)总线电压差为0V(图示默认电平都为2.5V)。

CAN总线为显性时(即逻辑电平为0时)总线电压差为2.0V左右(图示电平为3.5V和1.5V)。

3、总线通讯速度在125K到1M 比特率每秒。

2. 协议数据单元PDU

这是硬件层的。

15765中一个PDU就是一帧CAN数据。它主要包括:帧ID和(最多8个)字节数据。

帧ID分29bit的扩展帧和11bit的标准帧。

整体格式见下图,具体内容要去参考CAN2.0协议(ISO11898)。

3. 服务数据单元FDU

由1到多个PDU组成FDU,其组织方式可以简单理解为就是15765协议。

PDU有4个类型:

1)单帧

帧数量为1,也即数据不超过8个字节。

首字节表示长度,后面紧跟数据。

如 02 3E 00  //长度为2,诊断ID为0x3E 子数据为00

2)多帧首帧

帧数量大于1,也即数据超过8个字节。

首字节的前4bit为1表示为多帧首帧。

首字节左移8位 再加上次字节表示数据长度,也即数据最大为4095个字节。

如 10 08 01 02 03 04 05 06 //多帧首帧,且数据长度为8,后面6个是有效数据

3)多帧数据帧

首字节的前4bit为2表示为多帧首帧。

首字节的后4bit表示序号,第一包从1开始,后面顺序递增,递增超过15时从0开始。

10 08 01 02 03 04 05 06 //首帧

30 00 00 00 00 00 00 00 //流控帧

21 07 08 //数据帧

4)多帧流控帧

首字节的前4bit为3表示为多帧流控帧。

首字节的后4bit表示响应码,00表示正常,可以继续发送数据,否则应当停止后续发送。

第三个字节一般表示多帧发送延时,一般为00表示后续多帧数据帧之前发送间隔为0,为1表示要间隔1ms发送。

其它位置各家厂商定义不尽相同,有些甚至不用流控帧。

4. 15765组包和拆包实现

4.1 准备环境

我们准备2个设备,连接CAN高和CAN低。默认配置好和打开CAN-1M 波特率通讯。

发送数据(发起端发送ID用18FFFFFF):

{
    "cmd":"get_vol",
    "from":"master",
    "to":"device"
}


压缩:

{"cmd":"get_vol","from":"master","to":"device"}

转Hex:7b22636d64223a226765745f766f6c222c2266726f6d223a226d6173746572222c22746f223a22646576696365227d

数据长度为47 即0x2F

响应数据(接收端响应ID用18FFFFFE):

{
    "cmd":"23.89v",
    "from":"device",
    "to":"master"
}


压缩:

{"cmd":"23.89v","from":"device","to":"master"}

转Hex:

7b22636d64223a2232332e383976222c2266726f6d223a22646576696365222c22746f223a226d6173746572227d

数据长度为46 即0x2E

4.2 组包

由于发送数据长度大于8,需要多包方式进行组包。

首包及数据包可拆解如下:

发起端:
10 2F 7b 22 63 6d 64 22 //发送
30 00 00 00 00 00 00 00 //响应
21 3a 22 67 65 74 5f 76 //发送
22 6f 6c 22 2c 22 66 72
23 6f 6d 22 3a 22 6d 61
24 73 74 65 72 22 2c 22
25 74 6f 22 3a 22 64 65
26 76 69 63 65 22 7d 00 //空余1字节填充00

接收端:
10 2E 7b 22 63 6d 64 22 //发送
30 00 00 00 00 00 00 00 //响应
21 3a 22 32 33 2e 38 39 //发送
22 76 22 2c 22 66 72 6f
23 6d 22 3a 22 64 65 76
24 69 63 65 22 2c 22 74
25 6f 22 3a 22 6d 61 73
26 74 65 72 22 7d 00 00

发起端流程:

先发送10帧,等待30帧响应。

收到30帧正响应后,按顺序将21~26 共6包数据依次发出去。

然后再等待接收ID的10帧。收到后要立即响应30帧。

然后读取或缓存收到的2x数据帧,提取有效数据用Json API进行解析。

4.3 拆包

对于发送端的数据,组好包的数据只管发送。

处理接收时要进行逐个判断。

参考代码如下:

int ISO15765CanFrameRxDeal(uint8_t data, uint32_t id)
{
	switch(data[0]&0xF0)
	{
		case 0x00://单帧
		//单帧可以当场处理掉
			break;
			
		case 0x10://首帧
		//1,提取要接收的长度
		//2,根据长度或这包数申请内存buf(或者创建/清空数据队列)
		//3,缓存第一包的6byte数据
		//4,发送30帧响应
			break;
			
		case 0x20://数据帧
		//根据包序号判断是否接收完毕
		//将数据缓存到buf(或者将数据写入队列)
			break;
			
		case 0x30://流控帧
		//发送完10帧后等待30帧,一般判断是不是30帧正响应即可
			break;
	}
}

5. J1939协议

1939和15765 硬件层面完全相同的,只不过1939规定了250K波特率通讯。

且用于商用车、卡车客车的网络通讯,是一种广播的网络形式,车上一般规定用6/14针脚-250K波特率进行通讯。

如下图,商用车中,

仪表、空调、后处理、行程记录仪、发动机、变速箱等等都要讲必要数据以广播形式发到CAN网络中。通常所见的车上仪表盘,其实就是监听和解析广播帧ID数据(车辆通信内容可以轻易破解)。

对于不同的车上模块,如何区分不同模块的数据,

第一个就是帧ID,以及PGN。

对于1939的PDU,帧ID和数据部分定义如下:

1)1939固定250K通讯,帧ID采用29bit,也即4个字节

2)帧ID第一个字节的5个有效bit中,

前3bit定义为P-仲裁优先级

第4和5bit定义为扩展数据页及数据页

3)帧ID第二个字节表示PF,即PDU格式

PF值区间为0~239(0x00~0xEF),则表明是PDU1格式,如区间为240~255(0xF0~0xFF),则表明是PDU2格式

4)帧ID第三个字节表示PS,PDU Specific

如为PUD1格式,则该场表示帧的目标地址,如为PDU2格式,则表示组扩展GE

5)帧ID第四个字节表示SA,即源地址

源地址即表示从哪来的,协议规定:00为发动机,3D为后处理,17/21为仪表,等等

那么简单的来说,PGN就是由PF和PS组成,即帧ID的第2/3字节。(完整的PGN定义由EDP+DP和PF、PS共三个字节组成,但是由于EDP和DP一般全部都为00,所以忽略了帧ID的第1字节)

实际应用场景中,就是监听车上广播ID,根据PGN规则和协议匹配对应的数据流或故障码解析规则,进而解析数据。

如商用车一般都有的0x0CF00400广播数据,其有效数据为8字节。对于PGN为 00F004

可以根据ID直接匹配。以小端序提取其第4和5字节,除以80得到车上发动机的转速值。

同样的,1939协议中也有多帧数据,一般其内容是故障码数据,以及复杂或扩展数据。

PGN 00FECA 表示当前故障

PGN 00FECB 表示历史故障

PGN 00FECC 表示清除故障

车上多帧数据一般用两个帧ID表示,一个帧ID表示首帧,一个帧ID表示数据帧。

首帧不含有效数据,首字节一般为10或20表示不同的寻址方式,2/3字节表示长度,第4字节表示包数,5字节填充,6/7/8字节填充PGN。

数据帧首字节表示包数,剩余7字节为有效数据。

猜你喜欢

转载自blog.csdn.net/weixin_38743772/article/details/126494994