【Android车载系列】第3章 车载通讯CAN协议

1 CAN总线的基本概念以及由来

1.1 简介

        CAN 总线即控制器局域网总线(CAN,Controller Area Network)是一种用于实时应用的串行通讯协议总线,被公认为最有发展前景的现场总线之一。由 BOSCH 发明的一种基于消息广播模式的串行通信总线,它起初用于实现汽车内ECU之间可靠的通信,后因其简单实用可靠等特点,而广泛应用于工业自动化、船舶、医疗等其它领域。CAN国际标准只涉及到 OSI(开放式通信系统参考模型 )的物理层和数据链路层。上层协议是在CAN标准基础上定义的应用层,市场上有不同的应用层标准。

        要了解CAN总线协议,我们首先知道的一个概念是汽车ECU是指的什么?ECU(Electronic Control Unit)电子控制器单元,又称为汽车的“行车电脑”,它们的用途就是控制汽车的行驶状态以及实现其各种功能。“节点”或“电子控制单元”(ECU)就像车身的一部分,通过CAN总线互连。一个部分感知到的信息可以与另一部分共享。主要是利用各种传感器、总线的数据采集与交换,来判断车辆状态以及司机的意图并通过执行器来操控汽车。

        CAN总线系统使每个ECU都能与所有其他ECU通信-无需复杂的专用接线。

        具体地说,ECU可以通过CAN总线(由两条线组成,CAN低和CAN高)准备和广播信息(例如传感器数据)。广播的数据被CAN网络上的所有ECU接收——然后每个ECU可以检查数据并决定是接收还是忽略它。

        简而言之CAN总线是用于各个ECU之间互相通信的网络以及协议。

        那么什么是ECU?

        在汽车CAN总线系统中,ECU可以是例如引擎控制单元,安全气囊,音频系统等。现代汽车可能具有多达70个ECU—每个ECU可能都需要与网络的其他部分共享的信息。

 

1.2 CAN总线的优势 

         由于具有如下优势,所以CAN总线广泛应用于汽车,自动化,机械,轨道交通等各个方面。

扫描二维码关注公众号,回复: 14734686 查看本文章

1.3 发展历程

1983年,BOSCH开始着手开发CAN总线;
1986年,在SAE会议上,CAN总线正式发布;
1987年,Intel和Philips推出第一款CAN控制器芯片;
1991年,奔驰 500E 是世界上第一款基于CAN总线系统的量产车型;
1991年,Bosch发布CAN 2.0标准,分 CAN 2.0A (11位标识符)和 CAN 2.0B (29位标识符);
1993年,ISO发布CAN总线标准(ISO 11898),随后该标准主要有三部分:
        ISO 11898-1:数据链路层协议
        ISO 11898-2:高速CAN总线物理层协议
        ISO 11898-3:低速CAN总线物理层协议
        注意:ISO 11898-2和ISO 11898-3物理层协议不属于 BOSCH CAN 2.0标准。
2012年,BOSCH发布 CAN FD 1.0 标准(CAN with Flexible Data-Rate),CAN FD定义了在仲裁后确使用不同的数据帧结构,从而达到最高 12Mbps 数据传输速率。CAN FD与CAN 2.0协议兼容,可以与传统的CAN 2.0设备共存于同样的网络。随着车辆功能的扩展,CAN总线上的负载也随之增加。为此,CAN FD(灵活数据速率)已被设计为“下一代” CAN总线。
        CAN FD具有三个优点(相对于经典CAN):
                它支持高达12 Mbit / s的数据速率(vs 1 Mbit / s)
                它允许高达64字节的数据有效载荷(与8字节相比)
                它能够改善安全通过认证

        简而言之,CAN FD可以提高速度和效率,因此,它正在新车型中应用。这也将推动对IoT CAN FD数据记录仪的需求增加。
2015年,CAN FD协议标准化(ISO 11898-1)
2016年,CAN物理层,数据速率高达5 Mbit / s,已通过ISO 11898-2标准化 

如今,CAN已成为汽车(汽车,卡车,公共汽车,拖拉机,…),轮船,飞机,电动汽车电池,机械等的标准配置。 

展望未来,CAN总线协议将保持相关性 —尽管它将受到主要趋势的影响:
        1.对日益先进的车辆功能的需求
        2.云计算的兴起
        3.物联网(IoT)和联网车辆的增长
        4.自动驾驶汽车的影响

特别是,联网汽车和云计算的增长将导致车载远程信息处理和物联网CAN记录器的快速增长。
反过来,使CAN总线“联机”也会使车辆面临安全风险 -并可能需要转向新的CAN协议。

 

2 CAN物理层 

 与 I2C、SPI 等具有时钟信号的同步通讯方式不同,CAN 通讯并不是以时钟信号来进行同步的,它是一种异步通讯,只具有 CAN_High 和 CAN_Low 两条信号线,共同构成一组差分信号线,以差分信号的形式进行通讯。我们来看一个示意图

2.1 通讯节点

        从 CAN 通讯网络图可了解到,CAN 总线上可以挂载多个通讯节点,节点之间的信号经过总线传输,实现节点间通讯。由于 CAN 通讯协议不对节点进行地址编码,而是对数据内容进行编码的,所以网络中的节点个数理论上不受限制,只要总线的负载足够即可,可以通过中继器增强负载。

        CAN 通讯节点由一个 CAN 控制器及 CAN 收发器组成,控制器与收发器之间通过 CAN_Tx 及CAN_Rx 信号线相连,收发器与 CAN 总线之间使用 CAN_High 及 CAN_Low 信号线相连。其中CAN_Tx 及 CAN_Rx 使用普通的类似 TTL 逻辑信号,而 CAN_High 及 CAN_Low 是一对差分信号线,使用比较特别的差分信号,下一小节再详细说明。

        当 CAN 节点需要发送数据时,控制器把要发送的二进制编码通过 CAN_Tx 线发送到收发器,然后由收发器把这个普通的逻辑电平信号转化成差分信号,通过差分线 CAN_High 和 CAN_Low 线输出到 CAN 总线网络。而通过收发器接收总线上的数据到控制器时,则是相反的过程,收发器把总线上收到的 CAN_High 及 CAN_Low 信号转化成普通的逻辑电平信号,通过 CAN_Rx 输出到控制器中。

        例如,STM32 的 CAN 片上外设就是通讯节点中的控制器,为了构成完整的节点,还要给它外接一个收发器,在我们实验板中使用型号为 TJA1050 的芯片作为 CAN 收发器。 CAN 控制器与 CAN收发器的关系如同 TTL 串口与 MAX3232 电平转换芯片的关系, MAX3232 芯片把 TTL 电平的串口信号转换成 RS-232 电平的串口信号,CAN 收发器的作用则是把 CAN 控制器的 TTL 电平信号转换成差分信号 (或者相反) 。

目前有以下CAN电平转换芯片(不全)

我们来用TJA1050来看下原理图:

2.2 差分信号

        差分信号又称差模信号,与传统使用单根信号线电压表示逻辑的方式有区别,使用差分信号传输时,需要两根信号线,这两个信号线的振幅相等,相位相反,通过两根信号线的电压差值来表示

        逻辑 0 和逻辑 1。见图,它使用了 V+ 与 V-信号的差值表达出了图下方的信号。

        相对于单信号线传输的方式,使用差分信号传输具有如下优点

        • 抗干扰能力强,当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所以外界的共模噪声可以被完全抵消。

        举一个例子,正常的单线假设逻辑1是3.3V,逻辑0假设是0V,但是如果有噪声,把3.3V弄成了0V(极端),把0V弄成了-3.3V,此时就逻辑错误,但是有CAN高/CAN低一般都作用于两根线,所以两个虽然都有噪声影响,但是差值还是不变的

        • 能有效抑制它对外部的电磁干扰,同样的道理,由于两根信号的极性相反,他们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。

        举一个例子,假设一根是10V,一根是-10V,单跟都会对外部造成电磁干扰,但是CAN可以把线拧在一起,跟编麻花一样,可以互相抵消电子干扰

        • 时序定位精确,由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺,温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。

        由于差分信号线具有这些优点,所以在 USB 协议、485 协议、以太网协议及 CAN 协议的物理层中,都使用了差分信号传输。

2.3 CAN 协议中的差分信号

        CAN 协议中对它使用的 CAN_High 及 CAN_Low 表示的差分信号做了规定,见表及图。以高速 CAN 协议为例,当表示逻辑 1 时 (隐性电平) ,CAN_High 和 CAN_Low 线上的电压均为 2.5v,即它们的电压差 VH-V:sub:L=0V;而表示逻辑 0 时 (显性电平) ,CAN_High 的电平为 3.5V,CAN_Low 线的电平为 1.5V,即它们的电压差为 VH-V:sub:L=2V。例如,当 CAN收发器从 CAN_Tx 线接收到来自 CAN 控制器的低电平信号时 (逻辑 0),它会使 CAN_High 输出3.5V,同时 CAN_Low 输出 1.5V,从而输出显性电平表示逻辑 0 。

        CAN总线使用的是双线差分信号,所以分为CAN_H和CAN_L两根总线,根据两根总线之间电压的差值大小来判断其显隐性。而线缆上传输的电平信号只有两种可能,分别为显性电平和隐性电平,其中显性电平代表逻辑0,隐性电平代表逻辑1。

        根据ISO11898高速CAN电平标准进行判断,但是线路上经常会受到各种干扰,为了保证传输的稳定性。所以差分电平小于0.5V就是隐性电平代表逻辑1(空闲状态),差分电平大于0.9V就是显性电平代表逻辑0

2 CAN总线协议详解 

2.1 CAN协议标准

CAN总线协议大的分类包含底层的标准协议上层协议两种;其中以ISO 11898-1;ISO 11898-2和ISO11898-3这三种协议为主,下面介绍这三种协议的主要作用和应用方向。

        ISO 11898-1: 2015 定义CAN总线的数据链路层(DLL)和电气信号标准,描述CAN总线的基本架构,定义不同CAN总线设备在数据链路层通信方式,详细说明逻辑链接控制(LLC)和介质访问控制(MAC)子层部分;

        ISO 11898-2: 2003 定义高速CAN总线(HS-CAN)物理层标准,最高数据传输速率 1Mbps ,应用为两线平衡式信号(CAN_H, CAN_L),HS CAN是汽车动力和工业控制网络中应用最为广泛的物理层协议;

        ISO 11898-3: 2006 定义低速CAN总线(LS-CAN, Fault-Tolerant CAN)物理层标准,数据传输速率在 40Kbps ~ 125Kbps 。Fault-Tolerant是指总线上一根传输信号失效时,依靠另外的单根信号也可以通信,LS CAN主要应用于汽车车身电控单元之间通信;

然而上层协议就更加丰富了,几乎每个厂商都有自己的can总线协议。下图就列举了一些CAN总线的常用上层协议类型: 

2.2 CAN总线特性

        CAN总线具有多种特点其中包括:多主的工作方式;每条协议具有不同的优先级;采用非破坏性总线仲裁技术;CAN可以通过报文实现点对点、一点对多点以及全局广播方式传送数据;节点数取决于总线驱动电路;采用短帧结构(8/16字节),传输时间短,鲁棒性强,抗干扰;CRC帧校验,数据出错率低。

        这其中最重要的特点是多主的工作方式,一般操作系统都有一个大脑,对整个操作系统的环境进行管理,但是CAN总线的是多主的工作方式,各个ECU只负责往总线上收发它们的协议帧即可,所以当多个ECU同时收发消息时,就会导致冲突,这就又和它第二三个特点相关了。仲裁的特点是基于协议的优先级进行仲裁的,主要是为了给CAN总线上的协议进行优先级排序,决定发生冲突的时候哪个协议先占用CAN总线进行通讯。同时CAN协议的一些特点比如短帧结构,鲁棒性强,抗干扰等等能力也让CAN总线具有了在汽车上适用的条件。

2.3 CAN总线的布局

        之前汽车的各个ECU之间是通过点对点连接的,但是随着现代汽车内的ECU单元愈发增多,CAN总线连接的方式可以显著降低汽车内部布线的复杂程度。

        现代汽车各个ECU的总数加起来可能超过70个如传动控制、安全气囊、ABS等装置;如果考虑到未来无人驾驶汽车的传感器装置,ECU的数量将会达到120个。CAN总线实现汽车内互连系统由传统的点对点互连向总线式系统的进化,大大降低汽车内电子系统布线的复杂度。当然从安全角度出发,总线的布局也更容易导致汽车安全问题。如下图所示,汽车CAN总线的控制布局大致如下图所示,主要包括四个部分:动力CAN部分,车身CAN,组合仪表CAN,诊断CAN。动力CAN部分总线主要控制汽车动力以及制动装置部分,这部分对时效性要求比较高,所以一般会使用高速CAN。车身CAN一般是控制空调,车窗,后视镜等等,对时效性要求比较低,一般使用低速CAN。组合仪表部分则是控制汽车组合仪表的CAN。另外还有对汽车接口进行诊断的CAN。 

        高速CAN(按BOSCH说法,也叫CAN-C),数据速率在 125kbps ~ 1Mbp;低速CAN(CAN-B),数据速率在 5kbps ~ 125kbps。高速CAN用在速率比较高的总线上,低速CAN则在实时性要求低的节点,主要在舒适和娱乐领域。这些节点对实时性要求不高,而且分布较为分散,线缆较易受到损坏,低速CAN的传输速度即可满足要求。CAN总线在汽车诊断领域使用的也非常多,汽车诊断领域ECU挂载在总线上。 

2.4 CAN总线报文

CAN总线的通信是通过CAN报文完成的。
下图是带有11位标识符(CAN ID)的标准帧(CAN 2.0A),这是大多数汽车中使用的类型。
扩展的29位标识符(CAN ID)报文(CAN 2.0B)除了更长的ID外,其它部分都是相同的。它主要在重型车辆的J1939协议中使用。
注意,CAN ID和CAN Data在记录CAN总线数据时,它们非常重要,我们记录的主要就是这两部分。

  • SOF: “帧开始”是一个“显性0”,用于告知其他节点CAN节点打算进行通话
  • ID: ID是帧标识符(值越小优先级越高)
  • RTR:远程传输请求指示一个节点是发送数据还是从另一个节点请求专用数据
  • Control:包含标识符扩展位(IDE),它是11位的“显性0”。它还包含4位数据长度代码(DLC),用于指定要传输的数据字节的长度(0至8字节)
  • Data:数据包含数据字节(也称为有效载荷),其中包括可以提取和解码以获取信息的CAN信号
  • CRC:循环冗余校验用于确保数据完整性
  • ACK: ACK指示节点是否已正确确认和接收数据
  • EOF: EOF标记CAN帧的结束

 

3 指数哥伦布编码(理论篇)

        目前大部分车企使用的都是格伦编码实现数据协议的定义,格伦布编码(Golomb code)是一种无损的数据压缩方法,由数学家Solomon W.Golomb在1960年代发明。Golomb编码只能对非负整数进行编码,符号表中的符号出现的概率符合几何分布(Geometric Distribution)时,使用Golomb编码可以取得最优效果,也就是说Golomb编码比较适合小的数字比大的数字出现概率比较高的编码。它使用较短的码长编码较小的数字,较长的码长编码较大的数字。

        指数哥伦布码(Exponential-Golomb code, 即Exp-Golomb code)是熵编码的一种编码方式,正常来说,可以拓展位k阶,但是在H264中使用的是0阶指数哥伦布编码,在H.264中使用ue(v)表示0阶无符号指数哥伦布编码的解码过程,用se(v)表示0阶有符号指数哥伦布编码过程

3.1 无符号指数哥伦布编码

用来表示无符号整数k阶指数哥伦布编码的生成步骤如下:

(1)将数字以二进制形式写出,去掉最低位的k个比特位,之后加1

(2)计算留下的比特数位数,将此数减1,即是需要增加的前导0的个数

(3)将第一步中去掉的最低个比特位补回到比特串尾部

3.1.1 0阶无符号指数哥伦布编码过程

0阶无符号指数哥伦布编码最后生成的比特串格式为"前缀1后缀",前缀和后缀的长度是相同的。

假如我们待编码的数字codeNum = 4,0阶无符号指数哥伦布编码的步骤如下:

(1)将数字以二进制写出,4的二进制为100,因为0阶指数哥伦布编码所有不用去掉低位

(2)将上面的二进制+1,100加1为101,留下的比特数为3,3-1=2,所有需要增加前导0的个数为2

(3)因为第一步没有去掉,所有这一步不进行任何操作,最终生成的比特串为00101

0阶指数哥伦布编码可以简化为如下步骤

(1)将codeNum+1,4+1=5

(2)将加1后的数字用二进制表示,5的二进制位101,1后缀=101,后缀位01,长度2

(3)前缀与后缀长度相同,在前面加上2个0

下面对不同codeNum进行编码结果

codeNum codeNum+1 codeNum+1的二进制 需补前缀0的个数 编码后的比特串(红色表示补的前缀0)
0 1 1 0 1
1 2 10 1(0) 010
2 3 11 1(0) 011
3 4 100 2(00) 00100
4 5 101 2(00) 00101
5 6 110 2(00) 00110
6 7 111 2(00) 00111

0阶无符号指数哥伦布编码的解析过程如下

(1)找到第一个不为0的bit,并记录总共找到了0的个数(num),这个时候读到的这个bit肯定是1

(2)然后读num个后缀

(3)1后缀转变成十进制就是原来的codeNum,codeNum = (1 <<i) + 后缀(十进制) - 1;

比如比特串的二进制为:00111,首先找到第一个不为0的比特,前面0的个数为2,然后再读2个后缀11,11十进制为3,这个时候codeNum = (1 << 2) + 3 - 1 = 4 + 3 - 1 = 6

3.1.2 k阶无符号指数哥伦布编码过程

(1)将codeNum加上2^k

(2)将加上2^k的数字用二进制表示

(3)计算二进制的长度len,然后再前面加上len-1-k个0

比特串的格式位"前缀1后缀"。前缀 = 后缀 - k

codeNum k=1 len-1-k 编码后比特串 k=2 len-1-k 编码后比特串
1 1+2^1=3(11) 2-1-1=0 11 1+2^2=5(101) 3-1-2=0 101
2 2+2^1=4(100) 3-1-1=1 0100 2+2^2=6(110) 3-1-2=0 110
3 3+2^1=5(101) 3-1-1=1 0101 3+2^2=7(111) 3-1-2=0 111
4 4+2^1=6(110) 3-1-1=1 0110 4+2^2=8(1000) 4-1-2=1 01000

3.2 有符号指数哥伦布编码

        有符号指数哥伦布编码一般使用se(v)表示,输出可能是负数,有符号指数哥伦布编码解析的过程是在无符号指数哥伦布编码解析过程之上进行的,遇到se(v)需要先调用ue(v)得到codeNum,然后再调用se(v)的过程.

value = (-1)^(codeNum+1) * (codeNum+1)/2;

(-1)^(codeNum+1):表示如果codeNum为奇数那么是1,偶数为-1

3.3 总结

        0的位数代表数据的长度N,从第一个不为0的bit开始读N个后缀;编码+1,解码-1。

例如:

        1.要发送的信号为3,编码前+1为4,二进制为100,1后面为两个0,最终报文前面需要添加两个0作为后补长度,所以报文数据是00100。

        2.解码时前面两个0为第一个不为0的bit开始补两位,解出100数据十进制为4,由于编码+1,解码需要-1,4-1=3为最终解码十进制结果。

猜你喜欢

转载自blog.csdn.net/u010687761/article/details/129776296