CAN通信学习笔记

帧格式

1. 数据帧 (Data Frame - 携带数据)

  • 目的: 发送实际数据(如车速、温度、开关状态等)。

  • 结构 (标准帧为例):

    • SOF (Start of Frame - 1位 - 显性0): 标志帧的开始,同步所有节点。

    • 仲裁场 (Arbitration Field):

      • Identifier (ID - 11位): 消息的唯一标识符。值越小,优先级越高。决定哪个节点在总线冲突时赢得发送权(仲裁)。

      • RTR (Remote Transmission Request - 1位 - 显性0): 固定为显性0,表示这是数据帧 (与远程帧区分)。

    • 控制场 (Control Field - 6位):

      • IDE (Identifier Extension - 1位 - 显性0): 固定为显性0,表示这是标准帧 (11位ID)。

      • 保留位 (r0 - 1位 - 显性0): 保留位,必须发显性0

      • DLC (Data Length Code - 4位): 指定数据场包含的数据字节数 (0-8字节)。

    • 数据场 (Data Field - 0-8字节): 实际要传输的数据内容。长度由DLC指定。

    • CRC场 (CRC Field - 16位):

      • CRC (Cyclic Redundancy Check - 15位): 根据帧内容计算的校验码,用于接收方检查传输错误。

      • CRC 界定符 (1位 - 隐性1): 标志CRC字段结束。

    • ACK场 (Acknowledge Field - 2位):

      • ACK 槽 (ACK Slot - 1位): 发送方发送隐性1所有正确接收到该帧的节点(无论是否需要该数据)会在此时刻发送一个显性0覆盖它,表示“收到了,没错误”。

      • ACK 界定符 (1位 - 隐性1): 标志ACK场结束。

    • EOF (End of Frame - 7位 - 隐性1): 标志帧的结束。

2. 远程帧 (Remote Frame - 请求数据)

  • 目的: 请求具有特定ID的节点发送其对应的数据帧本身不携带数据

  • 结构 (标准帧为例): 与数据帧非常相似,关键区别有两点:

    • RTR位 (1位 - 隐性1): 固定为隐性1,表示这是远程帧

    • DLC (4位): 可以包含请求者希望收到的数据长度(0-8),但被请求的节点通常忽略此值,按自己的数据长度发送。有时用于请求特定格式。

    • 无数据场: 远程帧没有数据场。

  • 工作原理: 节点A发送一个ID=X, RTR=1的远程帧。拥有ID=X数据帧的节点B看到这个请求后,会尽快发送一个ID=X, RTR=0的数据帧作为响应。

3. 错误帧 (Error Frame - 报告错误)

  • 目的: 任何节点检测到错误(如CRC校验失败、格式错误、位填充错误等)时,立即主动打断当前总线传输,向所有节点报告错误

  • 结构 (两部分):

    • 错误标志 (Error Flag):

      • 主动错误标志 (6位显性0): 由检测到错误且处于主动错误状态的节点发出。

      • 被动错误标志 (6位隐性1): 由检测到错误但处于被动错误状态的节点发出。

      • 无论哪种,这6个连续的相同位都违反了CAN的位填充规则(每5个相同位后必须插入一个相反位),从而强制总线上的所有其他节点也检测到错误并参与发送错误标志。

    • 错误界定符 (Error Delimiter - 8位隐性1): 在错误标志之后,由所有节点发送8个隐性1位,提供一个恢复期,标志错误帧结束。总线随后恢复空闲。

4. 过载帧 (Overload Frame - 请求暂停)

  • 目的: 当一个节点内部处理不过来(如缓冲区满、CPU太忙),无法及时处理接收到的帧时,在帧间间隔(IFS)期间发送,请求延迟发送下一个数据帧或远程帧。使用相对较少

  • 结构: 与错误帧非常相似

    • 过载标志 (Overload Flag - 6位显性0): 由需要延迟的节点发出(主动错误状态节点发6个0,被动节点发6个1)。

    • 过载界定符 (Overload Delimiter - 8位隐性1): 标志过载帧结束。

5. 帧间隔 (Interframe Space - IFS - 帧间休息区)

  • 目的: 分隔连续的数据帧或远程帧。提供节点处理时间,并包含总线空闲期。错误帧和过载帧后没有IFS,它们之后可以直接跟新的帧。

  • 结构:

    • 间隔段 (Intermission - 3位隐性1): 强制的最小间隔。

    • 总线空闲 (Bus Idle - 任意长度隐性1): 真正的空闲时间,任何节点都可以在此后尝试发送(以SOF开始)。

    • 对于刚刚成功发送帧的节点,IFS还包含一个额外的“挂起传输”段(3位隐性1),使其在发送下一帧前有更长的延迟。

关键概念补充:

  • 显性位 (0) vs. 隐性位 (1):

    • 显性位 (0): 逻辑“0”。在总线上表现为低电平。具有总线访问优先权0会覆盖1)。

    • 隐性位 (1): 逻辑“1”。在总线上表现为高电平。当总线上没有节点驱动显性位时,表现为隐性位。

  • 仲裁: 多个节点同时开始发送时,通过逐位比较ID(从最高位MSB开始)决定谁赢。节点发送ID位时,同时监听总线。如果它发送了隐性1但监听到显性0,说明有更高优先级(ID值更小)的节点在发送,它立即停止发送转为接收模式。赢得仲裁的节点继续完成帧发送。

  • 位填充 (Bit Stuffing): 为了保证同步,避免长时间相同电平导致时钟漂移。在SOF到CRC界定符之间,每当连续出现5个相同位(5个0或5个1)后,发送方自动插入一个相反的位(在5个0后插1,在5个1后插0)。接收方会删除这些填充位。错误帧和过载帧的设计利用了违反位填充规则来快速通知所有节点。

位同步

核心目标: 确保总线上所有节点都能在正确的时间点读取总线上的电平(0或1)。想象大家围着桌子传纸条,必须同时低头看纸条内容,否则就乱了。

为什么需要同步?

  1. 时钟不同步: 每个节点都有自己的内部时钟(晶振),不可能100%精确相同,总有微小差异(误差)。

  2. 信号延迟: 信号在长长的总线电缆上传输需要时间,距离控制器远的节点会稍晚一点看到信号变化。

  3. 位长度: CAN总线上的每一位(0或1)占据一个固定时间段(称为位时间)。节点必须在这个时间段内的最佳位置采样总线电平,才能准确判断是0还是1。

1.硬同步 (Hard Synchronization) - “大复位”

  • 时机: 只发生在帧的开头,即检测到SOF(起始帧)的下降沿(从隐性1变显性0)时。

  • 作用: 像一声发令枪!所有节点接收方一检测到这个下降沿,立即重置自己的内部位定时计数器,从零开始计时当前位时间。

  • 效果: 确保所有节点(无论是接收方还是发送方)对第一位(SOF位)的计时起点完全对齐,同时对其相同的计时器起始点

  • 缺陷:每个接收设备的秒表都会存在误差,即使是进行了硬同步,秒表在后续计时的过程中也会存在不同步的情况,导致采样点逐渐偏离,所以要进行再同步(重同步)。

2.重同步 (Resynchronization) - “小调整”(接收方调整时钟)

  • 时机: 发生在帧传输过程中,每次检测到从隐性位(1)到显性位(0)的跳变沿时(除了SOF那个边沿)。

  • 作用: 不是完全重置,而是进行微调。节点计算检测到的边沿与自己内部时钟预期的边沿位置之间的偏差(相位误差)。

  • 怎么调? 根据这个偏差是提前了还是落后了,节点会稍微延长或缩短当前位时间(通过调整相位缓冲段即同步补偿宽度值(SJW)的长度),让内部时钟的预期边沿位置向实际检测到的边沿位置靠拢一点。

  • 效果: 在整个帧传输过程中,持续不断地纠正因时钟误差和传输延迟造成的微小偏移,防止误差累积导致采样点错位。

3.位填充 (Bit Stuffing) - “保证有跳变”

  • 规则: 在数据帧/远程帧的SOFCRC之间,如果连续出现5个相同极性的位(5个0或5个1),发送节点必须自动插入一个相反极性的位(第6位)。

  • 目的: 强制制造跳变沿!确保数据流中至少每6位就有一个边沿(从0变1或1变0)。

  • 重要性: 为重同步提供“抓手”!如果没有位填充,发送一长串0或1,中间就没有边沿,节点就失去了进行重同步调整的机会,时钟误差会累积直到采样出错。

  • 接收端: 接收节点在接收过程中会自动删除这些插入的填充位,恢复原始数据。

位时间结构 (理解调整的基础):

  1. 同步段 (Sync_Seg): 期望边沿发生的位置。硬同步和重同步的基准点。

  2. 传播段 (Prop_Seg): 补偿信号在物理总线上的传播延迟时间。

  3. 相位缓冲段1 (Phase_Seg1) & 相位缓冲段2 (Phase_Seg2): 重同步发生的地方! 检测到边沿时:

    • 如果边沿出现在Phase_Seg1之前(比预期早),说明节点内部时钟慢了,就延长Phase_Seg1(增加当前位时间)。

    • 如果边沿出现在Sync_Seg之后但在Phase_Seg2结束之前(比预期晚),说明节点内部时钟快了,就缩短Phase_Seg2(减少当前位时间)。

  4. 采样点 (Sample Point): 通常位于Phase_Seg1结束处。这是节点实际读取总线电平(决定是0还是1)的关键时刻!所有同步机制的核心目标就是让采样点对准总线电平最稳定的位置。

       问题: 时钟不准 + 线路延迟 = 大家容易看错位。

  • 方案:

    • 硬同步 (发令枪): 开头强制所有人对齐。

    • 重同步 (微调师): 过程中遇到跳变就微调时钟,跟紧节奏。

    • 位填充 (节奏制造者): 强制插入跳变,保证有足够多的机会让“微调师”工作。

  • 目标: 让每个节点的采样点都精准地落在每位数据的稳定区域,确保读到的0/1是正确的。

 仲裁

核心目标: 当多个节点同时想发送信息时,决定谁先发,谁后发,避免数据在总线上撞车(冲突),并且让最重要的信息(高优先级)优先通过

关键原理:

  1. “线与”逻辑 (物理基础):

    • CAN总线是“线与”逻辑:显性电平 (0) 是强信号隐性电平 (1) 是弱信号

    • 结果:只要有一个节点发送显性0整个总线就被拉成显性0。只有所有节点都发送隐性1时,总线才是隐性1

    • 简单说:0能覆盖1 这是仲裁能进行的物理基础。

  2. 优先级由ID决定:

    • 每条消息都有一个唯一的标识符 (ID)ID值越小,优先级越高! (例如,ID=0x100 比 ID=0x200 优先级高)。

    • 为什么? ID在数据帧/远程帧的仲裁场最先发送,且从最高位(MSB) 开始逐位发送,因此才能判断ID是否为最小,如果提前检测到有隐形1的话,就拉低这个节点的电平,直到总线空闲。

  3. 边发边听,愿赌服输 (仲裁过程):
    想象多个节点在SOF(起始位)后同时开始发送它们的ID:

    • 每个节点一边发送自己的ID位,一边监听总线上的实际电平。

    • 当某个节点发送了一个隐性位(1),但监听到总线是显性位(0)时:

      • 立刻明白:总线上有另一个节点在发送更高优先级(ID值更小) 的消息(因为对方在相同位置发的是0,覆盖了我的1)。

      • 立即、优雅地停止发送,转为接收模式,准备接收胜出者的完整消息。

    • 这个过程从ID的最高位(MSB)开始,逐位比较,直到决出胜负。

    • 赢得仲裁的节点感觉不到任何冲突,继续完成它整个数据帧的发送。

举个简单例子 (假设2个节点):

  • 节点A 想发送消息,ID = 0x201 (二进制: 0010 0000 0001)

  • 节点B 想发送消息,ID = 0x202 (二进制: 0010 0000 0010)

  • 优先级:0x201 (更小) > 0x202

为什么叫“非破坏性”仲裁?

  • 只有ID参与竞争,在仲裁阶段就决出胜负。

  • 输掉的节点在数据部分开始前就退出了,没有发生真正的数据碰撞(不会像以太网那样碰撞后要重传碎片)。

  • 赢得仲裁的节点不受任何影响,它的帧被完整无损地发送出去。

  • 总线时间没有被浪费在冲突后的恢复上。

仲裁阶段的关键点:

  1. 发生在哪里? 在仲裁场,主要是ID字段(和RTR、IDE位,它们也参与优先级比较)。

  2. 何时结束? 当某个节点发送一个隐性位(1) 但监听到显性位(0) 时,它立即退出。如果所有位都相同(罕见,ID需唯一),先发送RTR/IDE等控制位的节点也可能胜出(显性位优先)。

  3. 谁赢? ID值最小的节点赢得仲裁(最高优先级)。

  4. 输家怎么办? 输家默默退出,等总线空闲后重新尝试发送

注意

1、当节点A发送数据帧时,总线状态在忙,即使是优先级更高的节点B想要进来总线进行仲裁也要等节点A发送完才可以。只有两个节点都在仲裁场才可以进行ID优先级仲裁。

2、ID号相同时,数据帧优先级高于遥控帧。

3、标准格式11位ID号和扩展格式29位ID号的高11位一样时,标准格式的优先级高于扩展格式

错误处理

1. 强大的错误检测能力

CAN能在位级、帧级、报文级检测多种错误:

  • 位错误 (Bit Error): 节点发送一个位后,回读总线电平。如果发送的是显性0但读到隐性1(被别人覆盖),或发送隐性1但读到显性0(本应没人覆盖),立即报错(仲裁期间发送隐性位1但读到显性0不算错,那是仲裁输了)

  • 位填充错误 (Stuff Error): 在不允许出现连续6个相同位的区域(SOF到CRC界定符之间),如果检测到连续6个相同位,报错! (位填充规则被破坏)

  • CRC错误 (CRC Error): 接收节点根据收到的数据重新计算CRC,与发送节点发来的CRC值比较。如果不匹配,报错! (数据传输过程有误)

  • 格式错误 (Form Error): 检测到固定格式位出现非法值(如ACK界定符、CRC界定符、EOF必须是隐性1,但实际读到了显性0),报错!

  • ACK错误 (Acknowledgment Error): 发送节点在ACK槽位发送隐性1,但没有监听到任何节点发来的显性0(表示无人正确接收),报错! (消息无人应答)

2. 错误帧 (Error Frame) 

  • 作用: 任何节点检测到以上任何一种错误时,立即(在下一个位时间)发出错误帧,强行打断当前的总线传输。

  • 结构:
    错误标志 (Error Flag): 发出 6个连续的显性位0 (主动错误状态) 或 6个连续的隐性位1 (被动错误状态)。这直接破坏了位填充规则!
    错误界定符 (Error Delimiter): 接着发出 8个连续的隐性位1,提供一个“冷静期”,标志错误帧结束。

  • 效果:
    * 所有节点看到6个连续相同位(违反规则),都意识到有错误发生所有节点(无论是否检测到原始错误)都会参与发送错误界定符
    * 当前传输被强制中止。发送节点知道出错,稍后会自动重传该帧。
    广播式警报: 瞬间通知全网错误发生。

3. 自动重传 (Automatic Retransmission) - 再来一次!

  • 触发: 发送节点如果因为自己检测到错误(如位错误、ACK错误)或接收到错误帧而发送失败

  • 动作: 发送节点不会等待指令,一旦总线恢复空闲,会立即自动尝试重新发送同一帧数据。

  • 优点: 快速恢复,提高数据最终送达的可能性。

4. 错误计数器 & 错误状态管理

  • 目的: 区分偶尔犯错的好节点持续捣乱的坏节点,限制坏节点的影响。

  • 机制:
    * 每个节点有两个计数器:发送错误计数器 (TEC) 和 接收错误计数器 (REC)
    检测到错误/发出错误帧: 相应计数器增加(增加量取决于错误类型和节点角色)。
    成功发送/接收帧: 相应计数器减少(降到0为止)。

5. 故障界定 (Fault Confinement) - 隔离坏节点

  • 通过错误计数器状态转换,能有效识别并隔离持续故障的节点:
    被动错误状态: 限制其发送破坏性错误标志的能力(只能发弱弱的被动标志)。
    总线关闭状态: 彻底将其物理隔离在通信之外,防止其持续发送错误破坏总线。

错误处理全过程示例 (节点A发送数据):

  1. 发送中出错: 节点A发送数据时,节点B检测到一个CRC错误。

  2. 拉响警报: 节点B(主动状态)立即发出错误帧(6个连续的0)。

  3. 集体响应: 所有节点收到警报,都参与发送错误界定符(8个1)。

  4. 传输中断: 节点A的发送被强行中止。

  5. 计数变化:

    • 节点B (检测者):REC可能+1 (检测到错误)。

    • 节点A (发送者):TEC大幅增加 (如+8,因为发送失败且收到错误帧)。

  6. 自动重传: 总线空闲后,节点A自动重发同一帧。

  7. 状态管理:

    • 如果节点A只是偶尔出错:重传成功,TEC逐渐减少,保持主动状态。

    • 如果节点A持续故障(如硬件损坏):

      • 连续发送失败导致其TEC持续飙升

      • 当TEC >= 128:进入被动错误状态(发错误帧时只能发6个1,影响小)。

      • 当TEC >= 256:进入总线关闭状态(被踢出总线,网络恢复平静)。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值