can协议基础(2)-can数据链路层
can协议基础(2)-can数据链路层
1 数据链路层的介绍
CAN 总线的数据链路层负责在物理层提供的原始比特流上实现可靠的通信。它包括帧的封装、错误检测、确认机制、仲裁过程等关键功能。以下是数据链路层的主要特点和功能:
- 帧类型
CAN 协议定义了几种不同类型的帧,包括数据帧(用于数据传输)、远程帧(用于请求数据)、错误帧(用于错误通知)、过载帧(用于延迟下一帧的传输)和空闲帧(总线空闲状态)。 - 仲裁
CAN 总线使用非破坏性仲裁方法,允许多个节点同时尝试发送消息。如果两个或更多节点同时开始发送,节点会在发送过程中监听总线,并在检测到冲突时停止发送较低优先级的消息。这是通过帧 ID 的二进制值来实现的,较低的 ID 具有较高的优先级。 - 错误检测
CAN 数据链路层包括多种错误检测机制,如循环冗余检查(CRC)、帧检查、比特监视和确认检查。这些机制确保了数据的完整性和通信的可靠性。 - 确认机制
在数据帧成功传输后,接收节点会发送一个确认位,表明消息已被接收。如果发送节点没有检测到确认,它可能会重新尝试发送消息。 - 流量控制
虽然 CAN 协议本身不直接提供流量控制机制,但通过仲裁和优先级控制,它能够有效管理总线上的通信流量,防止数据丢失。 - 容错机制
CAN 数据链路层设计有容错机制,如自动重传错误帧、错误限制和节点故障隔离,以提高网络的稳定性和可靠性。 - 帧结构
每个 CAN 帧包括几个不同的字段,如起始位、帧 ID、控制字段、数据字段(最多 8 字节)、CRC、确认槽和帧结束位。这种结构化的帧格式有助于数据的有效传输和错误检测。
2 can 的帧类型
之所以将 can 的帧类型放在开头讲,目的是使大家对 can 的功能有所认知,在后续章节的 can 的总线总裁及总线错误处理需要熟悉 can 的帧格式,所以我并未像其他文章一样先讲解 can 的总线仲裁机制-尽管这个十分重要。
数据帧(Data Frame) :
- 用于传输数据从发送节点到一个或多个接收节点。
- 包含一个唯一的标识符(ID),用于标识消息的内容和优先级。
- 数据长度可以从 0 到 8 字节不等。
- 数据帧又分为标准帧和扩展帧
远程帧(Remote Frame) :
- 用于请求数据。
- 远程帧的标识符与它请求的数据帧的标识符相同。
- 不包含数据字段,仅通过其 ID 请求特定的数据帧。
错误帧(Error Frame) :
- 当节点检测到错误时发送。
- 用于通知其他节点在传输过程中检测到错误。
- 错误帧会导致当前传输被中断,并根据协议规定进行错误处理。
过载帧(Overload Frame) :
- 用于指示节点因为内部条件(如缓冲区溢出)而暂时无法处理更多的数据。
- 过载帧会导致网络上的数据传输暂时延迟。
在实际应用中,我们接触到的数据帧和错误帧最多,因此本文会着重讲解该两种类型。
2.1 数据帧
2.1.1 标准数据帧
数据帧是用于在网络上节点之间传输数据的主要帧类型。数据帧的结构设计用于高效且可靠的数据通信,具体包括以下几个关键部分:
SOF 起始位:标志着一帧数据的开始,确保节点同步到消息的起始位置。
标识一个数据帧的开始,固定一个显性位
总线空闲期间的任何隐性到显性的跳变都将引起节点进行硬同步
只有在总线空闲期间节点才能够发送 SOF仲裁字段:
- 标识符(ID) :用于标识消息的内容和优先级。
在 CAN 标准(CAN 2.0A)中,ID 为 11 位;在扩展标准(CAN 2.0B)中,ID 为 29 位。
确定报文的仲裁优先级,ID 数值越小,优先级越高
ID 的高位先发(Bit28….Bit0)
明报文的含义,可以包含报文的源地址和目标地址 - 远程传输请求(RTR)位:区分是数据帧还是远程帧。数据帧的 RTR 位为逻辑 0,远程帧的 RTR 位为逻辑 1。
- 标识符(ID) :用于标识消息的内容和优先级。
控制字段:包含了数据长度代码(DLC),指示数据字段中的字节数(0 到 8 字节)。
- 包含 4 位,表示数据场包含数据的字节数
- 高位先发(DLC3..DLC0)
数据字段:携带实际要传输的数据,长度可以是 0 到 8 字节。
- 具有 0-8 个字节长度,由 DLC 确定
- 包含 CAN 数据帧发送的内容
- 数据场里低字节先发(Byte0….Byte7)
每个字节是高位先发(Bit7….Bit0) - 超过一个字节的数据可以把低有效位放在前(Intel 格式),也可以把高有效位放在前(Motorola 格式)
CRC 字段:包含一个循环冗余校验码,用于检测传输过程中的错误。
在后续的错误检验机制中,会详细说明 can 总线的 crc 校验是怎么进行的CRC 字段界定符 :
界定 CRC 序列
固定格式,1 个隐性位
CRC 界定符之前进行位填充ACK :确定报文被至少一个节点正确接收
ACK 界定符 :
界定 ACK
固定格式,1 个隐性位结束位(EOF):标志着数据帧的结束,确保帧的边界清晰。
表示数据帧结束
固定格式,7 个连续的隐性位ITM: 间歇场,ITM 之后进入总线空闲状态,此时节点可以发送报文
固定格式
3 个连续的隐性位
即确认 11 个隐性位,认为总线进入空闲阶段
- 数据帧的位填充区域SOF 之前的总线空闲区域,不需要同步,无需进行位填充
CRC 之后的位域都是固定格式,不允许位填充操作
2.1.2 拓展数据帧
拓展数据帧格式大致与标准数据帧相同
1 | 拓展帧除了 ID 不同之外,还有些位有不同的区分 |
- SRR 位:代替远程请求位
表明在该位代替了标准帧中的 RTR 位
该位无实际意义
SRR 永远置 1 - IDE 位:标识符扩展位
用于区分标准帧和扩展帧
标准帧,IDE=0(11 位 ID)
扩展帧,IDE=1(29 位 ID) - RTR 位:远程请求位
用于区分数据帧和远程帧
数据帧,RTR=0;
远程帧,RTR=1; - r 0、r1 位
保留位
当前置 0
数据帧的设计允许 CAN 网络上的节点以非破坏性的方式进行通信,即使在网络负载较重的情况下也能保证数据的可靠传输。即使在网络负载较重的情况下也能保证数据的可靠传输。通过仲裁机制,确保了具有最高优先级的消息能够被优先传输,而不会被低优先级的消息阻塞这部分内容会在第三章着重讲解。
3 can 总线的通信模型
can 总线支持多主机发送,并且通讯方式为异步半双工通讯,这样势必会带来一种情况就是两个节点同时发送信息,而少了像 IIC 中的 SCL 地址线、SPI 中的片选信号线,简洁的物理层决定了 CAN 必然要配上一套更复杂的协议。如何用一个信号通道实现同样、甚至更强大的功能呢?答案是对数据或操作命令进行打包,而 can 总线使用的是 CSMA/CA(Carrier Sense Multiple Access with Collision Avoidance,带冲突避免的载波侦听多路访问)通信协议,下面我们先简单学习一下这种通讯机制
3.1 CSMA/CA 通信机制
CSMA/CA 协议的基本工作流程分为以下几点
- 载波侦听:在发送数据之前,设备首先检查通信媒介(如无线信道)是否空闲。这一步被称为“载波侦听”。
- 随机退避:如果信道被检测为忙碌,设备将等待一个随机的退避时间后再次检查信道是否空闲。这个随机退避时间有助于减少多个设备同时尝试访问信道时的冲突。
- 再次侦听:退避时间结束后,设备再次执行载波侦听,以确认信道是否空闲。
- 发送数据:如果信道空闲,设备开始发送数据。
- 确认接收:在一些实现中,接收设备会发送一个确认包(ACK),以通知发送设备数据已成功接收。如果发送设备在一定时间内没有收到 ACK,它可能会重新发送数据。
- 冲突避免:为了进一步减少冲突的可能性,CSMA/CA 在发送数据前可能会使用一个短的等待时间,称为“帧间间隔”(IFS),确保信道在连续传输之间保持空闲状态。
3.2 can 总线的非破坏性仲裁的载波侦听多路访问/冲突避免
CAN 总线使用的非破坏性仲裁机制是一种特殊的载波侦听多路访问/冲突避免(CSMA/CA)技术。这种机制允许多个网络节点几乎同时开始传输消息,但最终只有优先级最高的消息会被成功发送,而不会破坏或中断其他节点的消息,下面是 can 总线的这一技术的工作原理:
- 准备数据:发送节点(或称为 ECU,电子控制单元)准备好要发送的数据。这些数据被封装在一个 CAN 数据帧中,数据帧包括多个字段,如帧 ID、数据长度代码(DLC)、实际数据字节等,这个会在后续的第三章节讲到。
- 开始帧传输:发送节点在总线上发送一个起始位,标志着一个新帧的开始。
- 发送帧 ID:紧接着起始位,发送节点发送帧 ID(也称为标识符)。帧 ID 不仅标识了消息的内容,还决定了消息的优先级。在 CAN 总线上,较低的帧 ID 意味着较高的优先级。
- 仲裁过程:如果有多个节点同时尝试发送数据,CAN 总线上的仲裁机制会根据帧 ID 的优先级解决冲突,确保优先级最高的帧被首先发送。在这个过程中,所有参与发送的节点都会监听总线上的信号,并与自己尝试发送的信号进行比较。如果检测到总线上的信号与自己发送的信号不符,表示有更高优先级的节点在发送数据,节点会立即停止发送。
- 发送剩余帧内容:一旦节点成功通过仲裁,它就会继续发送剩余的帧内容,包括控制字段(如数据长度代码 DLC)、数据字段(最多 8 字节的数据)、CRC 校验序列等。
- 发送结束标志:数据发送完毕后,发送节点会发送一个帧结束标志。
- 接收确认:其他节点在接收到完整的帧后,会进行 CRC 校验,确认数据的完整性和正确性。如果数据无误,接收节点会在确认槽(ACK slot)发送一个确认位,表明数据已被成功接收。
- 错误处理:如果在传输过程中发生错误(如 CRC 校验失败),则会触发错误帧的发送,导致当前帧的传输被中断,并根据 CAN 协议的规定进行重传。
- 空闲状态:数据帧成功发送并确认后,总线回到空闲状态,等待下一个帧的传输。
3.3 CAN 的通信模型
- 报文发送: 节点发送报文时要检测总线状态
只有总线处于空闲,节点才能发送报文
在发送报文过程中,发送节点的 can 控制器进行“回读”,判断送出的位与回读的位是否一致 - “线与”机制
节点确认总线空闲后,发送方发送 can ID,这时候会有多个节点发送 id,通过线与机制来判断优先级“显性”位可以覆盖“隐性”位;
只有所有节点都发送“隐性”位,总线才处于“隐性”状态,如下图,节点 B 优先级最高 - 非破坏性仲裁
发送低优先级报文的节点退出仲裁后,在下次总线空闲时自动重发报文
如下图,节点 A 的 ID 最小,优先级最高,随后发送节点 B、C
高优先级的报文不能中断低优先级报文的发送
当低优先级的报文发送时,高优先级的报文请求发送,并不会中断低优先级的报文发送
这个在实际应用中可以解决总线报文丢失问题,即低优先级报文周期特别频繁的情况下,高优先级的报文依旧无法进行发送,会阻塞在 can 发送器的邮箱中,在遇到单 ECU 报文正常而接入整车后报文丢失情况时,优先考虑这一点
3.4 CAN 的总线访问总结
总线访问—非破坏性仲裁的载波侦听多路访问/冲突避免 CSMA/CA (Carrier Sense Multiple Access/Collision Avoidance)
载波侦听,网络上各个节点在发送数据前都要检测总线上是否有数据传输
网络上有数据暂时不发送数据,等待网络空闲再发
网络上无数据立即发送已经准备好的数据
其实总线上并没有什么“载波”。 “载波侦听”就是用电子技术检测总线上有没有其他节点发送的数据信号。
多路访问,网络上所有节点以多点接入的方式连接在同一根总线上,且发送数据是广播式的
冲突避免,节点在发送数据过程中要不停地检测发送的数据,确定是否与其它节点数据发生冲突,如果有冲突则保证高优先级的报文先发送。
CSMA/CA 与 CSMA/CD(带冲突检测的载波侦听多路访问)最大的不同在于其冲突处理方式。CSMA/CD(主要用于有线网络,如以太网)在检测到冲突时会立即停止发送数据并尝试重新发送,而 CSMA/CA 通过预防措施(如随机退避和帧间间隔)尽量避免冲突的发生,这使得 CSMA/CA 特别适用于无线网络环境,因为在无线环境中检测冲突要比有线环境更困难。
CSMA/CA 可归结为四句话:
发前先侦听,空闲即发送,
边发边检测,冲突时退避。
4 can 的错误检测与错误帧
错误检测
位填充错误(Bit Stuffing Error) :
- 在 CAN 帧中,如果连续出现 5 个相同的位(0 或 1),发送方会自动插入一个相反的位(称为填充位)。
- 接收方在接收数据时会检查这种填充位,如果检测到连续 6 个相同的位,则认为发生了位填充错误。
帧校验错误(Frame Check Error) :
- CAN 帧的结构必须符合特定的格式,包括起始位、控制位、数据位、CRC 校验位、确认位和结束位。
- 如果接收方检测到帧结构不符合规范,则会产生帧校验错误。
ACK 错误(Acknowledgment Error) :
- 在 CAN 帧的确认字段中,发送方会发送一个显性位(0),接收方在正确接收数据后会覆盖这个位为隐性位(1)。
- 如果发送方在确认字段中仍然检测到显性位,则认为发生了 ACK 错误。
CRC 错误(Cyclic Redundancy Check Error) :
- 每个 CAN 帧都包含一个 CRC 校验字段,用于检测数据传输中的错误。
- 发送方根据帧内容计算 CRC 值并附加到帧中,接收方接收数据后重新计算 CRC 值并与接收到的 CRC 值进行比较。
- 如果两者不匹配,则认为发生了 CRC 错误。
格式错误(Form Error) :
- CAN 帧的特定字段(如起始位、结束位等)必须是显性位或隐性位。
- 如果接收方检测到这些字段中的位不符合规范,则会产生格式错误。
位错误(Bit Error) :
- 在数据传输过程中,发送方会实时监控总线上的位状态。
- 如果发送方发送的位与总线上的实际位状态不一致(例如,发送显性位但检测到隐性位),则会产生位错误。
错误帧发送时机
- 错误帧的检测和发送流程为:检测错误-发送错误帧-通知报文错误
- 不同的错误帧的发送时机
在产生位错误、填充错误、格式错误或 ACK 错误时,产生后当前发送的下一位发送错误帧。
产生 CRC 错误时紧随 ACK 界定符后的位发送错误帧。 - 错误帧发送后,总线空闲时自动重发出错的数据帧!
错误计数器与错误状态切换
每个节点都含有 REC 和 TEC,当接收错误产生时,REC 增加,正确接收到数据帧,REC 减少;
当发送错误产生时,TEC 增加,正确发送一帧数据帧,TEC 减少;
REC、TEC 的数值会引发节点状态改变。
REC: Receive Error Counter 接收错误计数器
TEC: Transmit Error Counter 发送错误计数器
总线中,每个节点都有三种主要的错误状态,用于管理和处理通信中的错误。这三种状态是:
错误活动状态(Error Active State) :
- 在此状态下,节点可以正常参与总线通信,并且能够发送和接收数据帧。
- 如果节点检测到错误,它会增加其错误计数器(错误计数器分为发送错误计数器和接收错误计数器)。
- 当错误计数器的值低于一定阈值(通常是 128),节点保持在错误活动状态。
错误被动状态(Error Passive State) :
- 当节点的错误计数器超过一定阈值(通常是 128),节点进入错误被动状态。
- 在此状态下,节点仍然可以参与总线通信,但其发送的错误帧(Error Frame)不会主动干扰总线通信。
- 节点在错误被动状态下发送的帧会有一个特殊的标志,表明它处于错误被动状态。
- 如果错误计数器的值继续增加并超过另一个更高的阈值(通常是 256),节点将进入总线关闭状态。
总线关闭状态(Bus Off State) :
- 当节点的错误计数器超过最高阈值(通常是 256),节点进入总线关闭状态。
- 在此状态下,节点完全停止参与总线通信,既不能发送也不能接收数据帧。
- 节点需要通过特定的复位过程才能重新进入错误活动状态并恢复正常通信。
错误帧的格式
错误帧的格式由两个主要部分组成:错误标志(Error Flag)和错误定界符(Error Delimiter)。
错误标志(Error Flag) :
- 错误标志分为主动错误标志(Active Error Flag)和被动错误标志(Passive Error Flag)。
- 主动错误标志:由 6 个连续的显性位(0)组成。当节点处于错误活动状态时发送。
- 被动错误标志:由 6 个连续的隐性位(1)组成。当节点处于错误被动状态时发送。
错误定界符(Error Delimiter) :
- 错误定界符由 8 个连续的隐性位(1)组成,用于标识错误帧的结束。
错误帧的发送过程
检测到错误:
- 当节点检测到错误时,会立即中止当前帧的传输,并开始发送错误帧。
发送错误标志:
- 如果节点处于错误活动状态,它会发送主动错误标志(6 个显性位)。
- 如果节点处于错误被动状态,它会发送被动错误标志(6 个隐性位)。
发送错误定界符:
- 无论节点处于何种状态,都会发送错误定界符(8 个隐性位)来结束错误帧。
假设一个节点在传输过程中检测到错误,并且该节点处于错误活动状态,那么它会发送如下错误帧:
主动错误标志(6 个显性位) + 错误定界符(8 个隐性位)
如果节点处于错误被动状态,则发送如下错误帧:
被动错误标志(6 个隐性位) + 错误定界符(8 个隐性位)
错误帧的存在使得 CAN 总线能够快速检测和响应通信错误,从而提高系统的可靠性和稳定性。
位错误:
格式错误:
CRC 错误:
错误标志的叠加
当多个节点同时检测到错误并发送错误标志时,会发生错误标志叠加(Error Flag Overlapping)。错误标志叠加的处理方式取决于节点的错误状态(错误活动状态或错误被动状态)。
错误标志叠加的处理:
主动错误标志叠加:
- 当多个处于错误活动状态的节点同时发送主动错误标志(6 个显性位)时,这些显性位会在总线上叠加。
- 由于 CAN 总线是线与(wired-AND)逻辑,总线上只要有一个显性位,总线状态就为显性。因此,多个主动错误标志叠加后,总线仍然保持显性状态。
被动错误标志叠加:
- 当多个处于错误被动状态的节点同时发送被动错误标志(6 个隐性位)时,这些隐性位会在总线上叠加。
- 由于隐性位不会改变总线状态,总线状态保持为隐性。
主动和被动错误标志叠加:
- 如果一个节点发送主动错误标志(显性位),而另一个节点发送被动错误标志(隐性位),则总线状态将由显性位决定。
- 由于显性位优先级高于隐性位,总线状态将保持显性。
示例:
假设有两个节点 A 和 B,它们同时检测到错误并发送错误标志:
- 节点 A 处于错误活动状态,发送主动错误标志(6 个显性位)。
- 节点 B 处于错误被动状态,发送被动错误标志(6 个隐性位)。
在这种情况下,总线状态将由显性位决定,因此总线将保持显性状态。
错误标志叠加的主要效果是确保所有节点都能检测到错误并采取适当的措施。由于显性位优先级高于隐性位,总线上的显性状态可以有效地通知所有节点发生了错误,从而触发错误处理机制。
位定时(Bit Timing)是确保所有节点能够同步并正确解释总线上的数据的关键因素。位定时由几个参数组成,这些参数定义了一个位时间的结构。位时间通常分为四个主要部分:
同步段(Synchronization Segment, Sync_Seg) :
- 用于同步节点的时钟。
- 通常固定为 1 个时间量子(Time Quantum, TQ)。
传播段(Propagation Segment, Prop_Seg) :
- 用于补偿信号在总线上的传播延迟。
- 由若干个时间量子组成。
相位缓冲段 1(Phase Buffer Segment 1, Phase_Seg1) :
- 用于补偿节点间的相位误差。
- 由若干个时间量子组成。
相位缓冲段 2(Phase Buffer Segment 2, Phase_Seg2) :
- 也用于补偿节点间的相位误差。
- 由若干个时间量子组成。




























