从底层驱动到车载通信:CAN与CAN-FD协议详解及实战调试

发布时间:2026/10/18 10:48:26
从底层驱动到车载通信:CAN与CAN-FD协议详解及实战调试 1. 为什么一个做底层驱动的人最后都绕不开CAN总线从沙子到车辙这个系列名字起得挺有意思从硅砂到车轮印说的其实就是芯片从原材料到最终跑在路上的完整链路。而到了4.3这个节点聊CAN和CAN-FD说明前面已经把MCU内核、时钟、电源、基础外设这些地基打完了现在开始碰车载通信的主动脉了。我最早接触CAN是在一个车身控制模块的项目上当时用的是一个带CAN控制器的MCU外挂了一颗收发器。第一次用示波器看CAN_H和CAN_L的差分波形时说实话有点懵——这玩意儿跟UART、SPI完全不是一个思路。UART是点对点SPI是主从加片选而CAN是多主、广播、带仲裁的总线。你往总线上一挂谁都能说话但谁先说话是靠ID优先级硬碰硬抢出来的。这个设计在车载环境里极其关键因为车上几十个ECU共享两条线如果没有一套可靠的仲裁和错误处理机制数据早就乱成一锅粥了。CAN-FDFlexible Data-rate是CAN的升级版核心变化就两个数据段速率可以往上拉单帧数据长度从8字节扩展到64字节。别小看这两个变化它直接决定了你能不能在一个帧里塞下一整块标定数据或者一段诊断报文而不需要拆成七八帧去发。对于现在动辄上百个信号的车载网络来说这是实打实的效率提升。这篇文章主要面向已经有一定嵌入式基础、准备上手CAN/CAN-FD的开发者或者已经在用但想搞清楚底层细节的人。我会从协议核心机制讲起然后落到实际配置和调试最后把我在项目里踩过的坑整理出来。你不需要事先精通CAN但至少得知道什么是中断、什么是寄存器、示波器怎么用。2. CAN协议的核心机制拆解2.1 差分信号与显性隐性CAN的物理层逻辑CAN总线用两根线CAN_H和CAN_L。它们传输的是差分信号也就是说接收端看的是两根线之间的电压差而不是单根线对地的电压。这个设计的好处非常直接——共模干扰会被抵消掉。车上电机、继电器、点火线圈一大堆噪声源单端信号早就被淹没了差分传输是唯一靠谱的选择。具体电平定义是这样的当CAN_H和CAN_L电压差接近0V时总线状态为隐性Recessive逻辑上对应1当CAN_H拉高、CAN_L拉低压差大约2V时状态为显性Dominant逻辑上对应0。注意这个命名——显性就是强势的意思只要有一个节点发显性位总线就是显性。这个特性是后面仲裁机制的基础。我见过有新手把CAN_H和CAN_L接反了结果就是完全通信不上示波器上看波形也是反的。所以接线之前一定要确认收发器的引脚定义不同厂家的收发器标注方式可能不一样。终端电阻是另一个必须提的点。CAN总线两端各需要一个120Ω的终端电阻并联之后总线等效阻抗是60Ω。这个电阻的作用是吸收信号反射保证波形干净。如果你只接了一个节点做实验不加终端电阻可能也能通信但波形会有明显的振铃一旦线拉长或者节点增多通信就会变得不稳定。我一般建议不管什么情况先把终端电阻焊上再说。2.2 帧结构逐字段拆解从SOF到EOF一帧标准CAN数据帧的结构从前往后依次是SOFStart of Frame1位显性告诉总线上所有节点我要开始发了。仲裁段包含11位标识符标准帧或29位标识符扩展帧加上RTR位。这一段决定了帧的优先级。控制段包含IDE位、保留位r0和4位DLCData Length Code。DLC告诉你后面跟几个字节的数据经典CAN里有效值是0到8。数据段0到8字节的实际数据。CRC段15位CRC校验加1位界定符用来检测传输错误。ACK段发送方发隐性接收方如果正确接收就拉显性表示确认。EOFEnd of Frame7位隐性标志帧结束。这里面有几个细节值得展开说。DLC和实际数据长度不一致是一个经典陷阱。比如你DLC写了8但实际只填了4个字节的数据接收方会读到4个字节的垃圾数据。有些CAN控制器会检查这个有些不检查所以发送前一定要确保DLC和实际数据长度匹配。ACK段的机制也很有意思。发送方在ACK槽发隐性任何一个正确接收到这帧的节点都会拉显性。所以发送方只要看到ACK槽是显性就知道至少有一个节点收到了。注意这里说的是正确接收如果接收方CRC校验失败它不会拉显性发送方就会检测到ACK错误然后触发重传。2.3 非破坏性仲裁ID越小优先级越高CAN最精妙的设计之一就是非破坏性仲裁。原理是这样的多个节点同时开始发送时它们先发SOF然后逐位发送仲裁段。每个节点在发送每一位的同时也在监听总线。如果某个节点发的是隐性1但总线上是显性0它就知道自己输了立刻退出仲裁转为接收模式。赢的那个节点完全感知不到冲突继续正常发送。这意味着ID数值越小优先级越高。因为ID越小二进制里前面的0越多越容易在仲裁中胜出。在实际项目里这个优先级分配是有讲究的。安全相关的报文比如刹车、转向ID要分配得小一些舒适性相关的比如车窗、空调ID可以大一些。我见过一个项目因为把安全气囊的报文ID分配得比娱乐系统的还大导致碰撞时气囊报文被延迟了几十毫秒虽然最后没出大事但这个设计是绝对不合格的。2.4 错误处理与故障界定CAN的容错哲学CAN有一套相当完善的错误检测和恢复机制。每个节点内部有两个错误计数器TEC发送错误计数器和REC接收错误计数器。检测到错误时对应的计数器加1或加8取决于错误类型成功发送或接收时计数器减1。根据计数器的值节点会在三种状态之间切换状态TEC/REC范围行为错误主动TEC128且REC128正常通信检测到错误时发主动错误帧错误被动TEC≥128或REC≥128仍能通信但检测到错误时只发被动错误帧总线关闭TEC≥256完全脱离总线不再发送任何帧这个机制的意义在于故障隔离。如果一个节点因为硬件问题疯狂发错误帧它会先进入错误被动状态减少对总线的干扰最终进入总线关闭状态彻底闭嘴。其他正常节点不受影响。这比某些总线一出错就全网瘫痪的设计高明得多。我在实际调试中遇到过一次总线关闭的情况原因是一个节点的收发器供电不稳导致它持续检测到位错误。排查的时候先看TEC计数器发现它在飞速上涨基本就能定位到是哪个节点的问题了。3. CAN-FD带来了什么实质变化3.1 速率切换仲裁段慢数据段快CAN-FD最核心的变化是引入了可变速率。一帧CAN-FD里仲裁段包括SOF、ID、控制段的前半部分仍然用标准速率发送通常是500kbps或1Mbps。但到了数据段通过BRS位Bit Rate Switch的切换速率可以提升到2Mbps、5Mbps甚至8Mbps。为什么要这样设计因为仲裁需要总线上所有节点都能正确采样速率太高的话线束延迟和收发器延迟会导致采样点偏移仲裁就不可靠了。而数据段不涉及仲裁只有发送方和接收方参与速率可以拉高。这个速率切换对收发器的要求也更高了。普通CAN收发器在5Mbps下波形已经明显退化需要用CAN-FD专用的收发器。我在选型的时候一般会看收发器的环路延迟参数这个值越小能支持的最高速率越高。3.2 数据长度扩展从8字节到64字节经典CAN一帧最多8字节发一个64字节的标定数据需要拆成8帧加上帧间隔和仲裁开销实际有效吞吐率很低。CAN-FD把DLC扩展到了4位可以表示0到15对应数据长度0、1、2、3、4、5、6、7、8、12、16、20、24、32、48、64字节。注意这里不是线性的DLC9对应12字节DLC10对应16字节以此类推。这个映射关系在配置寄存器的时候要特别注意写错了就会导致收发双方对数据长度的理解不一致。64字节的单帧能力在诊断和标定场景下非常实用。UDS诊断里的TransferData服务经典CAN需要多帧传输CAN-FD可以一帧搞定。标定协议XCP on CAN-FD也是同理效率提升非常明显。3.3 CRC多项式变化与填充位计数CAN-FD的CRC多项式跟经典CAN不一样。经典CAN用15位CRCCAN-FD根据数据长度不同用17位或21位CRC。具体来说数据长度小于16字节用17位CRC大于等于16字节用21位CRC。这个变化是为了应对更长数据段带来的更高误码率风险。还有一个细节是填充位计数。经典CAN里填充位是每5个相同极性位后插入一个相反位接收方直接丢弃填充位。但CAN-FD的CRC计算包含了填充位的计数值也就是说接收方需要统计填充位的数量把它作为CRC校验的一部分。这个设计是为了防止填充位被恶意篡改导致CRC失效。3.4 兼容性与共存CAN-FD节点能否挂在经典CAN总线上这个问题我被问过很多次。答案是CAN-FD节点可以接收经典CAN帧但经典CAN节点无法接收CAN-FD帧。因为CAN-FD帧里用了经典CAN中保留的位比如EDL位、BRS位经典CAN控制器看到这些位会认为是格式错误然后发错误帧。所以如果你要把一个CAN-FD节点接入现有的经典CAN网络必须把它的FD功能关掉让它以经典CAN模式工作。或者整个网络全部升级到CAN-FD。混搭是可以的但FD节点必须能识别并兼容经典帧格式。4. 从零配置一个CAN节点的完整流程4.1 硬件选型与原理图检查要点假设我们要在一个车载控制器上实现CAN通信硬件层面需要确认这几样东西MCU是否内置CAN控制器现在大多数车规MCU都内置了比如常见的几个系列。如果没有需要外挂SPI转CAN的控制器。收发器选型经典CAN用普通收发器就行CAN-FD必须用支持FD的收发器。选型时关注最大速率、环路延迟、共模电压范围、ESD等级。终端电阻确认总线两端是否有120Ω电阻。如果是节点设备一般不需要自己加如果是测试设备或者总线末端必须加。共模电感在收发器和连接器之间加共模电感可以有效抑制共模噪声。很多参考设计里都有但新手容易漏掉。原理图检查的时候重点看收发器的TXD和RXD是否跟MCU的CAN_TX和CAN_RX正确连接。有些收发器的TXD内部有上拉有些没有这会影响MCU引脚的配置。另外收发器的STB或EN引脚如果没接对收发器可能一直处于待机模式通信不上。4.2 位时序计算采样点到底设在哪里位时序是CAN配置里最容易出错的地方。一个位时间被分成四个段同步段Sync_Seg固定1个Tq。传播段Prop_Seg补偿总线延迟和收发器延迟。相位缓冲段1Phase_Seg1用于重新同步。相位缓冲段2Phase_Seg2用于重新同步。采样点位于Phase_Seg1和Phase_Seg2之间。采样点的位置非常关键一般建议设在位时间的75%到80%之间。设得太早信号还没稳定设得太晚留给Phase_Seg2的余量不够重新同步能力差。举个例子假设CAN时钟是8MHzTq125ns目标波特率500kbps位时间就是2μs也就是16个Tq。如果采样点设在75%那么Sync_Seg1TqProp_SegPhase_Seg111TqPhase_Seg24Tq。具体怎么分配Prop_Seg和Phase_Seg1要看总线长度和收发器延迟。总线越长Prop_Seg要越大。注意同一个总线上所有节点的采样点位置必须一致否则会出现采样错误。如果你在一个已有网络里加节点先问清楚现有节点的位时序配置。4.3 过滤器配置怎么只收我想要的帧CAN控制器的过滤器决定了哪些帧会被接收到接收FIFO里哪些会被丢弃。过滤器配置得好可以大幅减轻CPU负担。过滤器一般有两种模式掩码模式和列表模式。掩码模式是指定一个ID和一个掩码掩码为1的位必须匹配为0的位不关心。列表模式是列出一组精确的ID只有完全匹配的才接收。我一般这样分配安全相关的报文用列表模式精确接收保证不漏诊断报文用一个掩码模式接收一段ID范围其他不关心的报文直接过滤掉不让它们进FIFO。有个坑是过滤器数量有限。一般MCU的CAN控制器只有十几个到几十个过滤器如果网络里报文太多可能需要用掩码模式来覆盖多个ID。这时候就要仔细规划ID分配把相关的报文放在连续的ID段里。4.4 中断与FIFO管理别在中断里处理数据CAN控制器的接收中断触发后正确的做法是尽快把数据从硬件FIFO搬到软件缓冲区然后在主循环或者任务里处理。千万不要在中断里做协议解析、数据计算这些耗时操作否则会阻塞其他中断导致丢帧。我通常的做法是中断里只做一件事——把帧数据拷贝到一个环形缓冲区然后设置一个标志位。主循环检测到标志位后从环形缓冲区取数据并处理。环形缓冲区的大小要根据总线负载来定负载高的时候缓冲区要相应加大。发送方向也类似。不要在主循环里直接写发送寄存器然后等发送完成这样会阻塞。正确的做法是把要发送的帧放入发送队列中断里检查发送完成标志然后从队列里取下一帧发送。5. 调试实录那些让我熬夜的CAN问题5.1 通信完全不通的排查顺序遇到CAN通信不上我一般按这个顺序排查量电压CAN_H对地大约2.5VCAN_L对地大约2.5V两者压差接近0V。如果电压不对检查收发器供电和接线。看波形用示波器看CAN_H和CAN_L应该有明显的差分波形。如果没有波形说明发送方根本没发出来。查终端电阻断电测量CAN_H和CAN_L之间的电阻应该是60Ω左右。如果是120Ω说明只接了一个终端电阻如果是无穷大说明一个都没接。确认波特率用CAN分析仪监听看是否有帧。如果没有可能是波特率不匹配。检查过滤器如果分析仪能看到帧但MCU收不到大概率是过滤器配置问题。这个顺序是从物理层到协议层从简单到复杂能快速缩小问题范围。5.2 偶发丢帧从示波器上找线索偶发丢帧是最难查的问题之一。我的经验是先用CAN分析仪长时间抓包统计错误帧的数量和类型。如果错误帧集中在某个ID或者某个时间段就能定位到问题节点。有一次我遇到一个偶发丢帧的问题分析仪显示每隔几分钟就会出现一次位错误。后来用示波器抓波形发现是某个节点的收发器在温度升高后输出波形的高电平幅度下降导致采样出错。换了收发器之后问题就消失了。这种问题靠看代码是永远找不到的必须上仪器。5.3 总线关闭的恢复策略总线关闭状态是CAN节点最严重的故障状态。进入总线关闭后节点完全脱离总线不再发送任何帧。恢复策略一般有两种自动恢复检测到总线关闭后等待一段时间比如100ms然后自动重新初始化CAN控制器尝试重新接入总线。手动恢复需要上层软件显式调用恢复函数。我一般用自动恢复但会加一个恢复次数限制。如果短时间内反复进入总线关闭说明硬件有问题这时候应该停止恢复上报故障码让诊断系统去处理。5.4 CAN-FD速率切换失败的典型原因CAN-FD调试中最常见的问题就是速率切换失败。表现是仲裁段能收到但数据段全是错误帧。原因通常有这几个收发器不支持FD这是最常见的。普通CAN收发器的环路延迟太大在数据段高速率下采样错误。采样点配置不对数据段的采样点位置需要单独配置不能直接沿用仲裁段的配置。Tq配置不合理数据段的Tq通常比仲裁段小需要重新计算。线束质量差CAN-FD对线束阻抗和长度更敏感如果线束不是双绞线或者屏蔽不好高速率下误码率会很高。排查的时候先用示波器看数据段的波形如果波形明显畸变基本就是硬件问题如果波形正常但通信失败就是配置问题。6. 几个容易被忽略的实战细节6.1 总线负载率的计算与控制总线负载率是衡量CAN网络健康度的重要指标。计算方法很简单负载率 单位时间内总线上实际传输的位数 / 总线总带宽。举个例子500kbps的总线1秒内最多传输500000位。如果实际传输了200000位负载率就是40%。一般建议负载率不要超过50%留出余量应对突发流量。如果超过70%延迟会明显增加安全相关的报文可能无法及时送达。控制负载率的方法有几种减少周期报文的发送频率、合并信号到同一帧、用CAN-FD提高单帧数据量。我一般会在设计阶段就用Excel或者脚本估算负载率不要等到测试的时候才发现总线跑满了。6.2 报文周期与超时监控每个周期报文都应该有超时监控。接收方如果在预期时间内没有收到某个报文应该触发超时故障。超时时间一般是报文周期的3到5倍。比如一个100ms周期的报文超时时间设为300ms到500ms。超时监控的实现方式是在接收中断里更新一个计数器或者时间戳在主循环里检查。如果超时置故障标志同时可以触发降级策略。比如刹车报文超时可能就需要进入安全状态。6.3 网络管理报文的处理很多车载网络都有网络管理报文用来协调各个节点的睡眠和唤醒。网络管理报文通常有特定的ID和格式需要按照协议栈的要求处理。如果你自己从零实现要注意唤醒帧的发送时机和睡眠条件的判断。搞错了会导致网络无法正常休眠或者节点被意外唤醒。6.4 与诊断协议的配合CAN只是物理层和数据链路层上面还要跑诊断协议比如UDS或者标定协议比如XCP。这些协议对CAN的使用有自己的要求比如多帧传输的流控帧、时间参数等。在配置CAN的时候要预留足够的缓冲区和过滤器给诊断报文不要被周期报文占满了。7. 常见问题速查表现象可能原因排查方法完全通信不上接线错误、收发器供电异常、终端电阻缺失量电压、看波形、测电阻偶发丢帧电磁干扰、收发器温漂、采样点偏移长时间抓包统计错误帧、示波器看波形质量进入总线关闭硬件故障导致持续错误、TEC超限读TEC/REC计数器、检查收发器和线束CAN-FD数据段错误收发器不支持FD、采样点配置错误换FD收发器、重新计算位时序过滤器不生效过滤器模式配置错误、ID掩码写错用分析仪确认帧ID、检查过滤器寄存器发送阻塞在中断里处理数据、发送队列满优化中断处理、增大发送队列8. 我个人在实际操作中的几点体会CAN这个东西入门不难但要用好真的需要时间积累。我刚开始做的时候觉得配置几个寄存器就能跑后来才发现真正的功夫在调试和优化上。硬件设计阶段多花一小时检查原理图可能省掉后面一周的调试时间。位时序的计算不要凭感觉老老实实按公式算算完用示波器验证采样点位置。CAN-FD虽然快但不要为了追求速率而牺牲稳定性速率和可靠性之间要找到平衡点。还有一点文档和注释一定要写清楚。CAN网络的ID分配、报文周期、信号定义这些东西如果不在设计阶段文档化后面维护的时候就是灾难。我接手过一个项目前任工程师走了之后没人知道某个ID是干什么的最后只能把整个网络抓包分析了一遍才搞清楚。这种教训一次就够了。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询