博主去年年底搞了2周的J1939协议栈,把协议栈调通,满足OEM姥爷的需求之后就没再深究。对这变态玩意有一些简单的心得感悟,略做分享。
目录
J1939抽象在哪?
首先:
J1939这玩意,必须基于CAN扩展帧,它把29bit的CAN ID用来赋予其特定的意义--PG。所以这就需要你死记硬背或者查表等方法弄明白每个ID被协议本身强制赋予的意义。
其次:
J1939这玩意,在总线上传输的时候不一定是CANID<-->CANID这样传,而是有可能明明你发的是CAN ID X,而经过协议本身给你拆成了CANID N+CANID M甚至更多。举例

我们看,我们实际上发的报文是18FECA12x对吧,但在支持J1939协议的CAN上位机上,
18FECA12,它实际上是用
18ECFF12,以及
18EBFF12,这两个报文发出去的。那么这两个报文啥意义呢?我们拆一下

- 18FECA12 -- DMx报文(0xFECA~)
- 18ECFF12 -- TP.CM连接控制帧(0xEC00)
- 18EBFF12 -- TP.DT数据帧(0xEB00)
再结合下图,实际上在总线上数据传递的时候,DMx报文是以
- BAM广播:PG = TP.CM+TP.DT+TP.DT+TP.DT+...
- CMDT点对点:PG = TP.CM+TP.DT + TP.CM+TP.DT + TP.CM+TP.DT + ...
此时总线上的数据载体为TP.CM和TP.DT
PNG与CAN报文一一对应吗?

PNG:参数Parameter,组Group,编号Number。我们看这个,这是DM1的PGN,但是0xxxFECAxx都是属于DM1,所以说,PGN是一组报文的合集(这一组报文有着一定的共性,比如0xxxFECAxx组的报文为DM1,其都有上报当前DTC的作用)。
**举例说明:**报文ID:0x18FECA17
第一个字节是18,转为二进制是 0001 1000,可以看到优先级是110(对应十进制的6),EDP=0,DP=0。
第二个字节是PF=FE(十进制是254>240)
第三个字节是GE=CA,(因为PF>240,GE取正常值)
第四个字节SA是17, 源地址 ,代表是谁发送的数据,比如0x52代表是氮氧,0x00代表 ECU。
所以PGN码是:00FECA
MetaData是什么?
在AUTOSAR中配置J1939的时候,需要在CANIF里面为J1939所用的PDU指定Metadata。

Vector 在他的TechnoicalReference中是这样写的:

我个人的理解,是"由于在AUTOSAR分层结构中,数据一旦被接收之后,CANIF之后的其他模块不会保留CANID,只会保留其内容。所以meta data的作用就是将CANID在其他上层中保留下来,使得CANIF之上的层架也能获取到CANID数据---而这正是J1939协议所需要的!"
PG与TP.DT的区别?
某些参数组(PG)定义需要8个以上的数据字节,因此需要一个以上的CAN数据帧来发送相应的数据。传输协议(TP)消息用于传输具有超过8个数据字节的PG。
PG是一个数据单元,有可能>8Byte,
以BAM传输为例,PG = TP.CM+TP.DT+TP.DT+TP.DT+...
以CMDT为例,PG = TP.CM+TP.DT + TP.CM+TP.DT + TP.CM+TP.DT + ...
此时总线上的数据载体为TP.CM和TP.DT
一个PG最大可以为 7*255 = 1785个Byte。
如果是单帧报文(PG长度<=8),那么他们(即PGN)各自用自己的ID直接发到总线上。
BAM与CMDT?
即广播与单播的区别。
|----------------------------------------------------------------------------|----------------------------------------------------------------------------|
| 广播BAM | 点对点CMDT |
| |
|
J1939RM模块的作用?
AUTOSAR架构下,J1939的实现主要由4个模块:
-
J1939Rm:这个模块有点难理解,网络上也找不到很合适的解释,RM即Request Manager,我的理解J1939Rm用来传达一些普通的PG请求的,什么意思呢?我们看上图J1939RM的上面是RTE,下面是PDUR,左边是COM,右边是J1939DCM,右下面是J1939NM,九省通衢,四通八达,长袖善舞,它更像是J1939中PDU的一个中转站,用于将特定PG路由到J1939其他模块--这样说J1939RM有点类似于PDUR呢(欢迎评论区给出高见)!
-
J1939Nm:这个可以结合CanNM来对比理解,主要用于J1939的网络管理。
-
J1939Tp:这个可以对比CanTp来理解,主要用于TP层的实现,用于拆包解包。
-
J1939Dcm:这个类比Dcm就可以了,用于实现J1939诊断协议的。
J1939协议怎么在总线上传输?
参考"J1939抽象在哪/其次。。。",即J1939协议中,报文不一定是以原始报文的形式发出去的,存在拆分和组装。
J1939协议栈配置法宝:PDU传递图

根据这张图,基本上可以搞定AUTOSAR中J1939TP+J1939NM+J1939DCM+J1939RM的配置,因为在我们AUTOSAR里面J1939各个模块之间也是以PDU的形式传输的。所以,可以直接根据这个图来配各个PDU。
如果嫌弃上面太复杂,我这有个自己画的更简化版的:

J1939配置中必需的PNG
- J1939TP使用的PGN:2个,连接管理报文TP_CM(0x00EC00:RTS+CTS+ACK+END) 和 TP_DT数据传输报文(0x00EB00)
- J1939DCM使用的PGN:DMx报文(0xFECA~),这个是我们项目中必需的,不一定适合你们。
- J1939RM使用的PGN:(所谓请求消息Request Msg就是请求一个PGN(CANID)中的值,类似远程帧)请求参数组RQST PG(0x0EA00) 和 ACKM应答参数组(0xE800) 和 请求2 RQST2(0xC900)
- J1939NM使用的PGN:地址声明报文(0xEE00)