CAN通信详解

        CAN 是 Controller Area Network 的缩写,是ISO国际标准化的串行通信协议。1986 年德国电气商博世公司开发出面向汽车的 CAN 通信协议。此后,CAN 通过 ISO11898(高速通讯标准) 及 ISO11519(低速通讯标准)进行了标准化,现在在欧洲已是汽车网络的标准协议。

CAN总线特点

①.多主模式:可以在一根总线挂载多个设备。在总线空闲时,所有的单元都可开始发送消息。最先访问总线的单元可获得发送权。多个单元同时开始发送时,发送高优先级 ID 消息的单元可获得发送权。 ID 并不是表示发送的目的地址,而是表示访问总线的消息的优先级。两个以上的单元同时开始发送消息时,对各消息 ID 的每个位进行逐个仲裁比较。仲裁获胜(被判定为优先级最高)的单元可继续发送消息,仲裁失利的单元则立刻停止发送而进行接收工作。

③.与总线相连的单元没有类似于“地址”的信息。因此在总线上增加单元时,连接在总线上的其它单元的软硬件及应用层都不需要改变。

④.所有的单元都可以检测错误(错误检测功能)。检测出错误的单元会立即同时通知其他所有单元(错误通知功能)。正在发送消息的单元一旦检测出错误,会强制结束当前的发送。强制结束发送的单元会不断反复地重新发送此消息直到成功发送为止(错误恢复功能)。

⑤.CAN 可以判断出错误的类型是总线上暂时的数据错误(如外部噪声等)还是持续的数据错误(如单元内部故障、驱动器故障、断线等)。由此功能,当总线上发生持续数据错误时,可将引起此故障的单元从总线上隔离出去。

⑥.CAN 总线是可同时连接多个单元的总线。可连接的单元数受总线上的时间延迟及电气负载的限制。降低通信速度,可连接的单元数增加;提高通信速度,则可连接的单元数减少。

总线电平

        单片机想要进行CAN通讯需要用到CAN收发芯片,他会将单片机输出的高低电平信号转换为差分信号,就是用两根线表示一个信号,分为CAN_H和CAN_L,当单片机输出低电平时,经过CAN收发器,CAN_H为3.5V,CAN_L为1.5V,电压差为2V,此时为显性电平,也就是逻辑0。当单片机输出高电平时,经过CAN收发器,CAN_H和CAN_L都为2.5V,电压差为0V,此时为隐性电平,也就是逻辑1。采用差分信号是为了减小干扰,如果是普通信号只有一条线,某一点受到干扰会导致电平跳变,导致数据出错,不适合长距离传输。而CAN通信采用差分信号,而且是双绞线缠绕,即使受到干扰也是两条线同时干扰,不会影响电压差。

        总线上执行逻辑上的线“与”,显性电平的逻辑值为“0”,隐性电平为“1”。“显性”具有“优先”的意味,只要有一个单元输出显性电平,总线上即为显性电平。并且,“隐性”具有“包容”的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平。(显性电平比隐性电平更强。)在CAN总线的起止端都有一个120Ω的终端电阻,来做阻抗匹配,减小回波反射

 帧的种类

        CAN通信通过以下五种类型的帧进行,数据帧和遥控帧有标准格式和拓展格式两种,标准格式ID为11位,拓展格式的ID为29位。

数据帧 

数据帧由七个段组成:(下图中D表示显性电平,R表示隐性电平)

①.帧起始:1bit,为显性电平,也就是逻辑0,表示起始。

②.仲裁段:表示该帧优先级的段,在总线仲裁章节中讲解。

③.控制段:控制段由 6 个位构成,表示数据段的字节数。标准格式和扩展格式的构成有所不同。         IDE为标识符选择位,为0代表标准标识符,为1代表拓展标识符,扩展标识符的IDE在仲裁段中,应该为1。 保留位(r0、r1):保留位必须全部以显性电平发送。但接收方可以接收显性、隐性及其任意组合的电平。 数据长度码(DLC):数据长度码与数据的字节数的对应关系如表所示(就按照数字来确定字节数)。数据的字节数必须为 0~8 字节。但接收方对 DLC = 9~15 的情况并不视为错误。

④.数据段:数据段可包含 0~8 个字节的数据。从 MSB(最高位)开始输出。标准格式和拓展格式相同。

⑤.CRC段:CRC 段是检查帧传输错误的帧。由 15 个位的 CRC 顺序和 1 个位的 CRC 界定符(用于分隔的位)构成,CRC界定符固定为隐性电平1。标准格式和拓展格式相同。CRC 顺序是根据多项式生成的 CRC 值,CRC 的计算范围包括帧起始、仲裁段、控制段、数据段。接收方以同样的算法计算 CRC 值并进行比较,不一致时会通报错误。  

⑥.ACK段:ACK 段用来确认是否正常接收。由 ACK 槽(ACK Slot)和 ACK 界定符 2 个位构成。发送单元在 ACK 段发送 2 个位的隐性位。接收到正确消息的单元在 ACK 槽(ACK Slot)发送显性位,通知发送单元正常接收结束。这称作“发送 ACK”或者“返回 ACK”。发送 ACK 的是在既不处于总线关闭态也不处于休眠态的所有接收单元中,接收到正常消息的单元(发送单元不发送 ACK)。所谓正常消息是指不含填充错误、格式错误、CRC 错误的消息。标准格式和拓展格式相同。

⑦.帧结束:帧结束是表示该该帧的结束的段。由 7 个位的隐性位构成。检测到11个连续的隐性位后认为总线空闲。

 遥控帧

        遥控帧由 6 个段组成,也叫远程帧。遥控帧没有数据帧的数据段。

①.帧起始:与数据帧相同。

②.仲裁段:与数据帧不同点在于RTR远程请求位,遥控帧的RTR位为1,数据帧的RTR位为0。

③.控制段:IDE位和保留位与数据帧相同,数据长度码为所请求数据帧的数据长度码。

④.CRC段:与数据帧相同。

⑤.ACK段:与数据帧相同。

⑥.帧结束:与数据帧相同。 遥控帧主要用来请求其他设备发送相应数据信息。

        假设车门信号不是周期发送的,如果想知道某时刻车门开关状态,就可以发送一个含有车门ID的遥控帧到总线,车门就会将此时的开关状态发送到总线。

过载帧

过载帧是用于接收单元通知其尚未完成接收准备的帧。过载帧由过载标志和过载界定符构成。

过载标志:6 个位的显性位。过载标志的构成与主动错误标志的构成相同。

过载界定符: 8个位的隐性位。过载界定符的构成与错误界定符的构成相同。

由于存在多个节点同时过载且过载帧发送有时间差,可能出现过载标志叠加后超过六位的现象。 有3种情况会引起过载帧:

①.接收节点自身原因。接收节点由于某种原因需要延迟接收下一个数据帧或者遥控帧。

②.在帧间隔的间歇段的第一位和第二位检测到一个显性位(正常的间歇段都是隐性位)。帧间隔的间隔段本应是三个连续的隐性位,如果接收节点在间隔段检测到显性位,那么就意味着此时有报文发向接收节点,但这个时候是不应该有报文发来的,于是接收节点发送过载帧。

③.CAN节点在错误界定符或过载界定符的第八位(最后一位)听到一个显性位0,节点会发送一个过载帧,且错误计数器不会增加。接收节点在错误界定符和过载界定符的最后一位听到显性位,也意味着有报文发向接收节点,但这个时候是不应该有报文发来的,于是接收节点发送过载帧。

帧间隔 

        帧间隔是用于分隔数据帧和遥控帧的帧。数据帧和遥控帧可通过插入帧间隔将本帧与前面的任何帧(数据帧、遥控帧、错误帧、过载帧)分开。过载帧和错误帧前不能插入帧间隔。

间隔:3个位的隐性位。

总线空闲:隐性电平,无长度限制(0 亦可)。本状态下,可视为总线空闲,要发送的单元可开始访问总线。

延迟传送(发送暂时停止): 8个位的隐性位。只在处于被动错误状态的单元刚发送一个消息后的帧间隔中包含的段。

        这里为什么需要延迟传送段呢? 首先,考虑主动错误状态的节点A,发送主动错误标志之后,随之就要重新发送刚刚发送失败的报文,但是为了与前面刚刚发送的错误帧间隔开,总线在错误帧之后就会插入3个隐形位的帧间隔,在这3个隐形位期间,其它的节点不足以判定总线空闲(需要连续11个隐性位才能判定),所以节点A仍然占据着总线的控制权,于是在帧间隔之后,节点A能够接着发送报文。现在节点A转入到被动错误状态了,说明它已经不是很可靠了,这个时候如果没有延迟传送段,在节点A发出被动错误标志之后,它仍然能够在3位的帧间隔之后立即重新发送报文,这是不符合我们对被动错误状态的处理要求的当然也是不符合CAN协议的,于是乎对于发送出被动错误标志的节点,总线在帧间隔中加入了8个连续隐性位的延迟传送段,这样的3+8=11个连续隐性位。就能让节点A在这个帧间隔期间失去对总线的控制权,从而优先保证其它正常(处于主动错误状态)节点能够使用总线,而不必等着一个已经不可靠的节点A占据总线。

错误帧 

在后续错误章节中讲解

总线仲裁

        总线仲裁主要指数据帧中对仲裁段的优先级判别,当多个设备同时发送消息时,需要通过总线仲裁判断优先级。即判断数据帧仲裁段中的显性电平来判断优先级,ID越小,优先级越高,在CAN总线通信中,有一种回读机制:指的是节点在向总线上发送报文的过程中,同时也对总线上的二进制位进行“回读”。通过这种机制,节点就可以判断出本节点发出的二进制位与总线上当前的二进制位是否一致。还有一种叫做线与机制:指的是在总线上,显性位能够覆盖隐性位。当结点回读到的信号与自己发出的不一致就知道自己仲裁失败了,就会自动转入接收模式,不会破坏仲裁成功的信号传输。可见CAN总线是半双工通信,节点不能在自己发送报文的时候,同时接收其他节点发送来的报文。 这是显然的,一个节点正在发送报文时,已经占据了总线的发送权,其他节点肯定不能向总线上发送报文。

数据帧和遥控帧的优先级 

        标准格式的 ID 有 11 个位。从 ID28 到 ID18 被依次发送。禁止高 7 位都为隐性。(禁止设定:ID=1111111XXXX)扩展格式的 ID 有 29 个位。基本 ID 从 ID28 到 ID18,扩展 ID 由 ID17 到 ID0 表示。基本 ID 和标准格式的 ID 相同。禁止高 7 位都为隐性。(禁止设定:基本 ID=1111111XXXX)RTR为远程请求位,为0代表数据帧,为1代表远程帧,如果两个节点ID相同,会仲裁RTR位,所以将数据帧的RTR位设置为0是为了让同ID的数据帧比遥控帧优先级更高

标准格式和拓展格式的优先级 

        SRR为替代远程请求位,设置为1,扩展帧中的SRR位与标准帧中的RTR在同一位置,这保证了在前11位ID相同的情况下,标准数据帧的优先级大于拓展数据帧。IDE为标识符选择位,拓展格式中IDE为1,在标准格式中IDE被放在了控制段,应该为0,这样保证了前11位ID相同的情况下标准遥控帧优先级高于拓展遥控帧

位填充机制

        位填充是为了减少消息帧在传送过程中出错。CAN总线规定信号的跳变沿为同步信号。只要信号发生变化了,节点时钟就会被同步。如果有连续相同的信号发送,没有跳变发生,就有可能出现发送和接收节点不同步,导致信号异常。所以CAN协议规定当检测到五个连续相同的位信号时,会自动插入一个补码发送,然后再接着发送后面的信号,位填充区域在帧起始到CRC段之间,帧起始之前总线空闲不需要填充,CRC之后都是固定格式,不允许位填充。 ​

        假设要发送的数据有连续10个0和8个1,那实际发送出去会多三个填充位,五个0后添加一个1,五个1后添加一个0,接收方收到带有填充位的信号后,会去掉填充位,再向主控芯片传输。

位时序及同步 

        位定时是指CAN总线上一个数据位的持续时间,主要用于CAN总线上各个节点的波特率设置,同一总线上的波特率必须相同,位时间等于1/波特率,1Mbit/s的波特率,一个位的发送时间就是1微秒,汽车常用的波特率是512kbit/s。由于CAN通信没有时钟线,所以随着时间推移,信号误差累积会变大,就需要进行同,CAN总线上一位数据可以分为同步段、传播段、相位缓冲段1和相位缓冲段2四部分。同步段用于同步总线内不同节点,该段需要有一个跳变沿,传播段用于补偿物理延迟,相位缓冲段用于补偿相位误差,可以通过重同步加长或缩短。CAN收发器采样时间通常位于两个相位缓冲段之间。

         同步有两种,发生在帧起始位的叫硬同步,发送节点发送帧起始位时,帧起始位的下降沿和接收节点的下降沿不同步,接收节点会强行将自己的同步段拉到和帧起始位的同步段保持一致。        

        另一种同步发生在其他位,叫重同步,发送节点发送帧起始位以外的位数据时,发送节点和接收节点的同步段不同步,接收节点会通过延长或缩短相位缓冲段来保证采样时间相同。  

错误 

        CAN通讯中有以下几种错误类型:

        检测到错误后,要提示总线上其他节点,就会发送错误帧。错误帧分为主动错误帧和被动错误帧。主动错误帧由六个显性电平,错误叠加标志位和八个隐形电平的错误界定符表示。被动错误帧由六个隐形电平,错误叠加标志位和八个隐性电平的错误界定符表示。错误标志叠加位是同时监测到两个错误,这两个错误可能错开也可能重合,完全重合就不需要错误标志叠加,错开的几位需要在叠加标志位表示。与过载帧原理相同。  

         CAN节点有两个错误计数器,发送错误计数器TEC和接收错误计数器REC,CAN节点根据这两个计数器值大小来判断处于什么状态 CAN节点有三种错误状态:

①.主动错误状态:TEC和REC都小于128时为主动错误状态。该状态下节点检测到错误就会发送主动错误帧,因为主动错误帧有连续六个显性位,会覆盖其他位信号,这样总线上之前传输的报文就会被破坏,相当于发生错误的节点站出来告诉其他节点刚才的信号有问题,让其他节点不要接收。

②.被动错误状态:如果某个节点发送错误帧较多,导致REC或TEC大于127,该节点就处于被动错误状态,该状态下节点检测到错误就会发送被动错误帧,因为被动错误标志是六个隐性位,所以总线上传输的报文不会受到该被动错误的影响。

③.总线关闭状态:已经处于被动错误状态的节点仍然多次发送被动错误帧,使得计数值大于256,就会进入总线关闭状态,该状态下节点无法收发报文,从总线上离线,等检测到128次11个连续隐性位时,TEC和REC才会重新置零,节点回到主动错误状态

        节点错误是一个循序渐进的过程,当错误次数较少时,总线还是信任该节点,可以正常收发报文,当错误次数达到128,总线就不再信任该节点,只允许听,不允许说,说的东西都会被覆盖掉,当错误次数太多就会被总线踢开。

相关推荐

  1. gd32F470配置CAN通信

    2024-05-13 13:30:06       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-05-13 13:30:06       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-13 13:30:06       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-13 13:30:06       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-13 13:30:06       20 阅读

热门阅读

  1. 解锁 Linux 网络配置:从入门到精通 ip 命令

    2024-05-13 13:30:06       11 阅读
  2. 【vim 学习系列文章 5.1 -- vim ctags 使用】

    2024-05-13 13:30:06       10 阅读
  3. 相似文本清洗

    2024-05-13 13:30:06       16 阅读
  4. Python如何传送我的世界Spigot服务器中的玩家

    2024-05-13 13:30:06       13 阅读
  5. 前端video标签播放第三方外链地址报错403

    2024-05-13 13:30:06       11 阅读
  6. 02-SpringApplication.run

    2024-05-13 13:30:06       12 阅读
  7. Map、Set和Object的区别

    2024-05-13 13:30:06       11 阅读
  8. Vue3知识总结-3

    2024-05-13 13:30:06       10 阅读
  9. del删除脚本的“无效开关”

    2024-05-13 13:30:06       8 阅读
  10. TypeScript 类型系统深度解析:类型全览

    2024-05-13 13:30:06       13 阅读
  11. vue的生命周期

    2024-05-13 13:30:06       10 阅读
  12. day5.12 leetcode80 删除有序数组重复项

    2024-05-13 13:30:06       14 阅读
  13. Leetcode 3148. Maximum Difference Score in a Grid

    2024-05-13 13:30:06       13 阅读
  14. 即将研究生入学,记录一些遇到的疑问

    2024-05-13 13:30:06       10 阅读
  15. linux的Wget命令下载文件示例

    2024-05-13 13:30:06       13 阅读
  16. 如何在Python中自定义异常?

    2024-05-13 13:30:06       9 阅读