跳到主要内容

CAN通信协议

1. CAN协议简介

CAN(控制器局域网)总线是一种为可靠、高效、实时通信而生的串行通信协议。它最初由博世公司于1980年代为汽车开发,旨在减少车辆内复杂的线束,因此被誉为车辆的"神经系统"。

1991年CAN总线技术规范(Version2.0)制定并发布。这份技术规范分A/B两部分,A部分规定了CAN报文标准格式,B则给出了标准和扩展两种格式。

CAN总线协议是一种ISO 国际标准化的串行通信协议,有 ISO-11898 和 ISO-11519两个系列。

  • ISO-11898 是高速CAN总线协议,速率125 kbps~1Mbps,最高1Mps,总线长度较短,≤40m,属于闭环总线。

  • ISO-11519则是一种低速CAN总线协议。速率10~125 kbps,总线长度较长,可达1000m,属于开环总线。

两种都是双线通信。

信息

其实还存在一种单线CAN标准,适用于33.3 kbps~83.3 kbps的通信设备,它就是SAE J2411。通常,需要在信号线与地之间接9kΩ电阻。它是一种车载标准,市面上用的最多的就是通用汽车GM-LAN。

危险

并不是高速CAN降速之后就能变成低速CAN,这两种标准的电气特性就不一样。

不是坏了一根线的CAN就可以变成单线CAN,刚刚也说了单线CAN是一种标准,它有自己的电气特性。

不是所有的CAN transceiver IC都可以支持网络唤醒和睡眠功能。

CAN通信就像一个电话会议。你也可以理解为一个X讯会议或者X书会议。

这个会议会有这些情况:

  1. 一个人说,其他人听。
  2. 两个人要说,但是一个人让另一人先说,其他人听。
  3. 一个人要求另一个人回答。
  4. 有人掉线了。
  5. 都不说话。
  6. ...

两种速率下的CAN标准都遵循双线结构,也就是传输差分信号CAN_H以及CAN_L,这两条线通常以双绞线的形式缠绕。

每个节点都有CAN收发器(transceiver)和CAN控制器(controller)。集成到芯片里或者独立芯片都存在。

物理层ISO 11898 (High speed)ISO 11519-2 (Low speed)
通信速度*1**最高 1Mbps最高 125kbps
总线最大长度*2**40m / 1Mbps1km / 40kbps
连接单元数最大 30最大 20
总线拓扑*3**闭环总线开环总线
电气特性隐性显性
MinNom
CAN_High (V)2.002.50
CAN_Low (V)2.002.50
电位差 (H-L) (V)-0.50
传输介质双绞线(屏蔽/非屏蔽)双绞线(屏蔽/非屏蔽)
电缆参数阻抗 (Z): 120Ω (Min. 85Ω Max. 130Ω)
总线电阻率 (r): 70mΩ/m
总线延迟时间: 5ns/m
阻抗 (Z): 120Ω (Min. 85Ω Max. 130Ω)
总线电阻率 (r): 90mΩ/m
总线延迟时间: 5ns/m
终端电阻120Ω (Min. 85Ω Max. 130Ω)2.20kΩ (Min. 2.09kΩ Max. 2.31kΩ)
对地电容CAN_L与GND间静电容量 30pF/mCAN_L与GND间静电容量 30pF/m
CAN_H与GND间静电容量 30pF/m

CAN的优势:

  1. 多主通信。总线上的任何节点都可以主动发起通信,无需中央控制器。
  2. 工业级的可靠性。使用差分信号(CAN_H和CAN_L双绞线)传输,抗电磁干扰能力极强,非常适合 noisy 的车载和工业环境。
  3. 高效的仲裁机制。当多个节点同时发送数据时,优先级最高的报文(标识符ID数值最小)能继续发送,而其他节点会自动退出发送并转为接收,整个过程不破坏数据也不浪费带宽。

2. CAN信号

2.1 CAN信号传输

CAN_L和CAN_H是CAN总线中的两根信号线,它们通过差分信号传输数据,是以电压差形式表现的,分为显性电平(dominant)和隐性电平(recessive)。显性电平规定为逻辑0,隐性电平规定为逻辑1。

  • 高速CAN中,电压差为0V时表示逻辑1(隐性电平),电压差为2V时表示逻辑0(显性电平)。

  • 低速CAN中,电压差为-1.5V时表示逻辑1(隐性电平),电压差为3V时表示逻辑0(显性电平)。

我们就这张图讲一讲,首先当CAN_H和CAN_L的电压均为2.5V时,电压差为0,规定信号为隐性电平;当CAN_H的电压为3.5V,而CAN_L的电压为1.5V时,电压差为2V,规定信号为显性电平。

电压差满足定义的一定范围,就可以认为是显性电平或者隐性电平。

在网上找了一张图,读者可以看一下CAN的真实波形。

我们来了解一下发送过程。控制器需要把CPU传来的信号转换为逻辑电平,收发器接收逻辑电平后,再转为差分电平输出到总线。

在接收过程中,接收器需要把总线上的差分信号转换为逻辑电平,控制器接收逻辑电平后,再转为CPU信号。

可以看出,差分电平是由CAN收发器实现的。

不妨看看CAN收发器的内部结构。

Details
  1. 接收器 (Receiver)

    位置:连接在 CANH、CANL 和 RXD 之间。

    作用:差分信号接收器。

    原理:实时监测 CANH 和 CANL 上的电压差。

    如果差压在 0.9V 到 5V 之间(显性),比较器翻转,RXD 输出低电平(0)。

    如果差压在 -1V 到 0.5V 之间(隐性),RXD 输出高电平(1)。

    抗干扰:因为读取的是两者的差值,所以外部的电磁干扰(同时影响两根线)会被抵消掉。

  2. 驱动器 (Driver)

    位置:连接在 TXD 和 CANH/CANL 之间。

    作用:将 TXD 的逻辑信号转换成差分电压。

    原理:

    隐性 (TXD = 1):驱动器的输出级被关闭(或处于高阻态),两个 25 kΩ 的内部电阻将 CANH 和 CANL 都拉到 0.5 * VCC(约 2.5V)。此时 CANH 和 CANL 电压几乎相等,差分电压为 0V。

    显性 (TXD = 0):驱动器内部的晶体管打开,将 CANH 拉到约 3.5V(或更高),CANL 拉到约 1.5V(或更低),形成约 2V 的差分电压。

  3. 显性超时定时器 (Dominant Time-out Timer)

    位置:串联在 TXD 路径上。

    作用:这是TJA1050的一个保护机制。

    原理:如果由于硬件或软件故障,TXD 引脚长时间保持低电平(显性状态),总线会一直处于显性状态,导致通信瘫痪(占用总线)。如果这个低电平持续时间超过了规定的阈值(通常约 1ms 到 2ms),定时器会强制禁用驱动器,释放总线,让它回到隐性状态。这可以防止某个故障节点卡死整个网络。

  4. 斜率控制 (S)

    位置:引脚8旁边的 S(实际上标准TJA1050的引脚8是 S,用于选择高速模式或静音模式)。

    作用:控制输出级的上升和下降斜率。在低速率或对电磁兼容性要求高的场合,可以降低斜率来减少EMI(电磁干扰)。

  5. 参考电压 (Reference Voltage) 和 偏置电阻 (25kΩ)

    位置:两个 25 kΩ 精密电阻分压出 0.5 * VCC。

    作用:

    为接收器和驱动器提供稳定的中点参考电压。

    在隐性状态时,通过这两个电阻将 CAN 总线稳定在 2.5V 的共模电压上,确保总线空闲时处于确定状态,并准备被拉低或拉高。

它的工作流程:

2.2 CAN报文解析

首先我们要了解到,CAN的一大特点是多主通信。实际上,多主通信的实现依赖于非破坏性逐位仲裁(Non-Destructive Bitwise Arbitration)技术和CAN收发器的特殊电气特性。

只要总线处于空闲状态,那么任意节点都可以往总线上发消息。

但是总线只有一条,如何做到可靠的传输?

最先发送消息的那个节点获得总线的发送权,而优先级越高的节点,就越快获得总线的发送权。

提示

比如,节点1发送消息,节点2和节点3没有发送消息,那么节点1就获得总线的发送权。节点1和节点4同时要发送消息,此时如果节点4优先级高于节点1,那么节点4就获得总线的发送权。

如何判断优先级大小?

2.3 非破坏性仲裁机制

这是一种既不会造成已发送数据的延迟,也不会破坏已经发送的数据的仲裁机制,依赖线与机制、载波监听以及与帧结构有关的仲裁域。

信息

“线与”逻辑:显性位(逻辑0)可以覆盖隐性位(逻辑1)。任何节点只要输出显性位,总线就呈现显性;只有当所有节点都输出隐性位时,总线才呈现隐性。这一特性是由收发器的开漏/推挽输出结构决定的。

也就是说,只有当所有输出都是高电平(逻辑1)时,总线上才会呈现高电平;只要有一个输出是低电平(逻辑0),总线就被拉低为低电平。

CAN的线与与I²C的线与在原理上类似,但有两点重要区别:

  • I²C:使用单线(SDA、SCL)开漏输出,靠外部上拉电阻实现线与,速率较低。

  • CAN:使用差分双线(CAN_H、CAN_L),隐性时内部偏置电阻使两线等电位,显性时强力驱动差分电压,既能实现线与,又能提供高抗干扰能力和高速传输。

每个CAN节点在发送每一位的同时,都会通过接收器实时读取总线上的实际电平。发送器将发送的位与读取的位进行比较:

  1. 如果两者一致,节点继续发送下一位。

  2. 如果节点发送的是隐性位(1),但读取到的是显性位(0),则说明有其他节点发送了显性位,即存在更高优先级的报文。该节点立即失去仲裁,停止发送,转为接收模式,同时不再干扰总线。

  3. 如果节点发送的是显性位(0),即使读取到显性位(0),也可能有其他节点也发送显性位,此时所有发送显性位的节点继续参与下一位的仲裁。

仲裁只发生在帧起始(SOF)和标识符(ID)(以及扩展帧中的SRR、IDE位,远程帧的RTR位)期间。一旦某节点赢得仲裁并开始发送控制段和数据段,其他节点就不再尝试竞争,直到下一次总线空闲。

提示

仲裁例子:两个节点同时发送

假设一个CAN网络中,节点A和节点B同时开始发送数据帧,它们的11位标准标识符(ID)分别为:

  1. 节点A ID:0x7A0(二进制:111 1010 0000)

  2. 节点B ID:0x7E8(二进制:111 1110 1000)

按照CAN协议,ID值越小,优先级越高。这里节点A的ID(0x7A0)小于节点B的ID(0x7E8),因此节点A应该赢得仲裁。让我们逐位分析仲裁过程。

位序节点A发送位节点B发送位总线实际状态节点A读回节点B读回仲裁结果
SOF0 (显性)0 (显性)0一致一致继续
ID101 (隐性)1 (隐性)1一致一致继续
ID91 (隐性)1 (隐性)1一致一致继续
ID81 (隐性)1 (隐性)1一致一致继续
ID71 (隐性)1 (隐性)1一致一致继续
ID61 (隐性)1 (隐性)1一致一致继续
ID50 (显性)1 (隐性)0 (显性)一致 (发送0读回0)发送1读回0 → 失去仲裁节点B退出,节点A继续
  • 从SOF到ID6,所有位相同,总线状态一致,两节点继续。
  • 在ID5位,节点A发送显性0,节点B发送隐性1。总线被节点A拉为显性0。节点B发送1却读到0,判定自己失去仲裁,立即停止发送并转为接收。节点A发送0读到0,继续发送剩余位。

节点A赢得总线后,继续发送控制段、数据段、CRC、ACK等,完整地发送其数据帧。节点B在检测到总线空闲后(节点A发送结束),会重新尝试发送。

因为ID越小,其二进制表示中在高位出现0的位置越靠前。在逐位仲裁中,第一个输出0的节点会赢得总线。所以:

ID = 0x100(二进制 0001 0000 0000) vs ID = 0x200(0010 0000 0000)

比较最高位(ID10):第一个是0,第二个是1 → 第一个获胜。

这正好符合直觉:数字越小,优先级越高。

注意

仲裁过程中,赢家并没有从头开始重新发送,而是:

从帧起始(SOF)到仲裁场的最后一位相同位(ID6),总线信号由两个节点共同塑造(数据一致所以无冲突);从出现差异的第一位(ID5)开始,总线信号完全由赢家(节点A)塑造。整个帧是“共同开头 + 赢家独续”的连续数据流,中间没有任何断裂或重发。

扩展帧与远程帧的仲裁

扩展帧中的额外位: 对于29位扩展ID的帧,仲裁过程还包括SRR位和IDE位。扩展帧的SRR位在标准帧的RTR位位置,为隐性;而标准帧的RTR位在数据帧中为显性。因此,如果同时发送标准帧和扩展帧且ID基相同,标准帧会因RTR显性而赢得仲裁。

远程帧的RTR位: 远程帧的RTR位为隐性,数据帧的RTR位为显性。因此,具有相同ID的数据帧和远程帧同时发送时,数据帧总是赢得仲裁。这个设计使得数据帧总是比远程帧优先。

系统的“柔软性”

这里要说说CAN通信系统的“柔软性”———它既能在物理层容忍一定的故障,又能在应用层灵活地扩展节点。

首先,CAN总线上的节点是即插即用的。任何节点在任何时刻都可以尝试发送数据,不需要主机轮询。这使得新节点可以随时加入网络,并主动上报信息。节点可以设置为只接收感兴趣的ID。即使总线上有很多新节点加入发送新ID的数据,原本不关心这些ID的节点完全不受影响,它们的硬件过滤器会直接忽略这些数据,CPU负载不会增加。如果要在总线上增加一个新功能(例如增加一个电池管理系统),只需要确认新节点的ID不与现有节点冲突即可,无需修改其他节点的硬件。

总线会根据ID的大小自动分配使用权。如果系统中突然出现紧急事件(如安全气囊触发),对应的节点可以设置很小的ID(高优先级)。它不需要等当前低速的报文发送完,只需要等当前帧结束(或者直接在下一帧仲裁中获胜)。这种特性让系统在面对突发事件时表现出极高的反应柔软性。

由于错误计数器和错误帧的存在,CAN系统不会因为一个节点坏了就导致全网瘫痪,它有一套自我疗愈的机制。

通过发送错误计数器(TEC)和接收错误计数器(REC),CAN控制器能判断自身是否经常出错。

  • 当计数器值在127以下时,节点是“主动错误”状态,可以正常通信,出错时发主动错误帧(显性)。

  • 当计数器值在128到255之间时,节点进入“被动错误”状态。它虽然还能收发数据,但当它检测到错误时,只能发送隐性的错误标志(不会干扰总线)。这就像一个人生病了,自己悄悄咳嗽,但不影响大家开会。

  • 当计数器值超过255时,节点自动进入“总线关闭”状态。它会把自己从总线上完全隔离,不再进行任何通信,既不发数据也不收数据。这防止了一个彻底坏掉的节点持续占用总线,发出大量垃圾数据。

2.4 CAN总线帧结构

帧类型作用关键特征结构/长度概要
数据帧从发送节点向其他节点传输数据携带0~8字节数据;具有标识符决定优先级;分为标准帧(11位ID)和扩展帧(29位ID)SOF + 仲裁场 + 控制场 + 数据场 + CRC场 + ACK场 + EOF (共44~108位+填充)
远程帧(遥控帧)请求其他节点发送具有相同ID的数据帧无数据场;RTR位为隐性(1),因此优先级低于相同ID的数据帧;标识符指定所需数据SOF + 仲裁场 + 控制场 + CRC场 + ACK场 + EOF (无数据场,长度固定)
错误帧检测到总线错误的节点主动通知所有节点发生错误由错误标志(6个相同位,主动错误为显性,被动错误为隐性)和错误界定符(8个隐性)组成错误标志(6位) + 错误界定符(8位) (总14位)
过载帧接收节点未准备好接收下一帧时请求延迟结构与错误帧类似,但由过载标志(6个显性)和过载界定符(8个隐性)组成过载标志(6位) + 过载界定符(8位) (总14位)
帧间空间分隔数据帧/远程帧与后续帧,使总线恢复空闲并允许节点执行内部处理由间歇场(3个隐性位)和总线空闲(任意长隐性)组成;错误帧和过载帧前无帧间空间间歇场(3位隐性) + 总线空闲(任意长度)

2.5 CAN同步机制

2.5.1 位速率(比特率)

位速率也称为比特率,表示单位时间内总线上传输的信息量,即每秒能够传输的二进制位的数量,R=1TR=\frac{1}{T},单位是bps(比特每秒)。位速率越高,通信速度越快。

注意

位速率和波特率是两个不同的概念,位速率是单位时间内总线上传输的二进制位的数量,波特率是单位时间内总线上传输的符号的数量,符号是二进制位的一种表示方式,可以是1个或多个二进制位。

什么时候位速率会等于波特率?当一个符号只包含两种可能,即一个事件两种可能,那么此时1baud=1bit。

如果一个事件有2+种可能,那么此时1baud>1bit。比如一个事件有4种可能,一个符号中包含四个电平,那么此时1baud=2bit。

2.5.2 位时序

一帧数据由多个位组成,每个位由一个时钟周期组成,时钟周期由位速率决定。如何使得接收方能够准确接收数据?这就需要位时序。

实际上,数据的接收是逐位进行的。

将一个位分为4段时间,分别是:同步段传播段相位缓冲段1相位缓冲段2

每个段又由若干个Tq构成,这称为位时序。tq是Time Quantum的缩写,表示时间量子,即最小的时间单位。

位时序可以被任意设定。通过设定位时序,可以使得多个单元同时采样。采样点也是可以任意设定的。

Image

采样点是读取总线电平,并将读到的电平作为位值的点。一般设置在PBS1段结束点。

  • 同步段(SS): 多个连接在总线上的单元通过此段实现时序调整,同步进行接收和发送的工作。由隐性电平到显性电平的边沿或由显性电平到隐性电平边沿最好出现在此段中。

  • 传播时间段(PTS): 用于吸收网络上的物理延迟。所谓网络物理延迟指发送单元的输出延迟、总线上信号的传播延迟、接收单元的输入延迟。这个段的时间为以上各延迟时间的和的两倍。

  • 相位缓冲段 1(PBS1): 当信号边沿不能被包含于 SS 段中时,可在此段进行补偿。

  • 相位缓冲段 2(PBS2): 由于各单元以各自独立的时钟工作,细微的时钟误差会累积起来,PBS 段可用于吸收此误差。通过对相位缓冲段加减 SJW 吸收误差。SJW 加大后允许误差加大,但通信速度下降。

  • 再同步补偿宽度(SJW): 因时钟频率偏差、传送延迟等,各单元有同步误差。SJW 为补偿此误差的最大值。

CAN各个位都没有附加同步信息,是靠位时序同步的(NRZ)。接收单元以总线上电平的变化进行同步,进行接收。发送单元和接收单元存在的时钟频率误差及传输路径上的(电缆/驱动器等)相位延迟会引起同步偏差,因此接收单元通过硬件同步或者再同步的方法调整时序进行接收。

2.5.3 位填充

这里要补充一下位填充的概念。

位填充是指在 CAN 帧的某些字段中,当发送器连续发送 5 个相同极性(全 0 或全 1)的位时,自动在 第 5 位之后插入一个相反极性的位。接收器在接收到时会自动将其删除。

仅在帧的特定位置有效(从 SOF 到 CRC 段,不包括 CRC 界定符、ACK 段和帧结束)。

如果数据中包含连续多个相同电平,长时间没有跳变沿,接收器的时钟漂移会导致采样点偏移,造成位错误。位填充可以解决这个问题。通过强制插入相反电平,这样总线上最多只有 5 个相同位,从而提供足够的边沿用于同步。

如果接收器检测到 连续 6 个相同位(即违反填充规则),则认为发生了填充错误,会立即发出错误帧。状态寄存器的TEC计数器会存储填充错误。

2.5.4 位同步(硬同步)

我们以一次检测为例。空闲状态下,接收节点检测出帧起始(SOF位)时,会调整当前位的同步段,调整宽度不限。假设这时检测的是SOF位。

节点A的下降沿在SS段,节点B接收发现当前位的SS段和发送的SS段不同步,于是立即重置位时间计数器,强制将自己当前位的SS段拉到与SOF位的SS段同步。

2.5.5 位采样

在 CAN 协议中,位采样 是指接收节点在一个位时间内的某个时刻对总线电平进行读取,以确定该位的逻辑值(显性 0 或隐性 1)。采样点(Sampling Point)的选择直接影响通信的可靠性和抗干扰能力。

采样点通常位于相位缓冲段 1(PBS1) 的末尾和 相位缓冲段 2(PBS2) 的开始处。

Possample=(1+PTS+PBS1)tqPos_{sample} = (1 + PTS + PBS1) tq
提示

推荐采样点范围:75%~85% 的位时间。

太靠前(<70%):可能无法容忍振荡器误差和传输延迟。

太靠后(>90%):可能没有足够时间完成 PBS2 的处理,导致下一个位采样偏差。

CAN 控制器通常支持两种采样模式:单次采样 和 三次采样。STM32中也是支持的,推荐选用三次采样。

  • 单次采样:在采样点读取一次总线电平,确定该位的逻辑值。优点:快速,对边沿抖动不敏感,适合高波特率。缺点:抗瞬时干扰能力较弱(若采样瞬间有尖峰,可能导致误判)。

  • 三次采样:在一个位时间中,连续采样三次(通常以采样点为中心,间隔一个 tq 或一定时间),然后通过 多数表决(3 取 2)确定最终电平。优点:给总线去毛刺,增强抗噪声能力,适合低波特率或干扰严重的环境。缺点:会轻微增加延迟,且对边沿位置更敏感(需要边沿稳定在采样窗口内)。

位时序寄存器 CAN_BTR:

BRP:预分频器(决定 tq 长度)。

TS1:时间段 1(包含 PTS + PBS1,值 = 实际 tq 数 - 1)。

TS2:时间段 2(PBS2,值 = 实际 tq 数 - 1)。

SJW:再同步跳转宽度。

采样点位置计算公式:

Possample=1+TS1+11+TS1+1+TS2+1=TS1+2TS1+TS2+3Pos_{sample} = \frac{1 + TS1 + 1}{1 + TS1 + 1 + TS2 + 1} = \frac{TS1 + 2}{TS1 + TS2 + 3}

其中分子分母均为 tq 数。例如,TS1=13TS1=13TS2=2TS2=2,则采样点 = 13+213+2+3=151883.3%\frac{13+2}{13+2+3}=\frac{15}{18}\approx83.3\%

接收器通过 硬同步(SOF 边沿)和 重同步(帧内边沿)调整采样点位置。每次重同步会根据边沿相位误差,在 SJW 范围内增减 PBS1 或 PBS2 的长度。

2.5.6 再同步(重同步)

再同步(Resynchronization)是 CAN 协议中用于在帧传输过程中保持节点与总线位流同步的机制。它不同于硬同步(仅在 SOF 边沿发生),而是在帧内的每个边沿都可能触发,通过微调位时间计数器来补偿时钟漂移和传播延迟,确保采样点始终位于正确位置。

CAN 总线没有独立的时钟线,每个节点使用自己的晶振工作,晶振频率存在微小误差(如 ±0.3%)。同时,信号在总线上传播也有延迟。如果不做再同步,随着时间累积,节点的位边界会逐渐偏离总线实际位流,导致采样点错位,引发位错误。

再同步的作用就是在帧内检测到边沿时,根据该边沿相对于预期位置的偏移量,动态调整相位缓冲段的长度,使采样点重新对齐。

再同步由 总线上的隐性到显性边沿显性到隐性边沿 触发。但并不是每个边沿都会引起调整,而是根据边沿与预期位置的关系决定。

CAN 协议定义每个位时间内的 同步段(SS) 是理想的边沿位置。如果检测到的边沿出现在 SS 之后(即迟于预期),说明节点时钟较慢,需要 缩短 PBS1 或 延长 PBS2;如果边沿出现在 SS 之前(即早于预期),说明节点时钟较快,需要 缩短 PBS2 或 延长 PBS1。具体调整量受 再同步跳转宽度(SJW) 限制。

信息

SJW(再同步跳转宽度)是一个可配置参数(通常 1~4 tq)。它决定了节点容忍时钟漂移和传播延迟的能力:

  • SJW 越大,节点能补偿的误差越大,对振荡器精度要求越低,但会牺牲抗噪声能力(因为允许的调整幅度大,可能使采样点偏离最优位置)。

  • SJW 越小,节点同步更精确,但对时钟精度要求更高。

配置SJW需满足以下两个条件:

  1. SJW必须小于PBS1和PBS2的最小值;

  2. SJW最大值不能超过4。

再同步分为两种情况:

  1. PSB1段加长

这种情况是接收节点的SS段在发送节点的SS段前产生,也就是发晚了,收早了。

这个时候需要加长PBS1段,使接收节点的SS段和发送节点的SS段对齐。接收节点加长PBS1段2个tq。

此时即可同步。

  1. PBS2段缩短

这种情况是接收节点的SS段在发送节点的SS段后产生,也就是发早了,收晚了。

这个时候需要缩短PBS2段,使接收节点的SS段和发送节点的SS段对齐。接收节点缩短PBS2段2个tq。

此时即可同步。

2.5.7 位时间计算设置

假设需要设置波特率500Kbps,时钟频率170MHz。

时钟频率转换为时间表示:T=1/170MHz=5.882nsT = 1/170MHz=5.882ns,NBT=16(1个位16个tq)。

波特率换算成时间表示:1/500Kbps=2us=2000ns1/500Kbps=2us=2000ns。传输一个位的时间是2000ns.16个tq就等于2000ns,即tq=125ns。

又因为:

tq=BRT+1fCAN(ifDIV8=0)tq=8BRT+1fCAN(ifDIV8=1)tq = \frac{BRT+1}{f_{CAN}} (if DIV8=0)\\\\ tq = \frac{8*BRT+1}{f_{CAN}} (if DIV8=1)

DIV8:时钟分频因子为 8

STM32F4xx 系列中,CAN1 和 CAN2 的时钟源可以选择 PCLK1 直接 或 PCLK1 / 8,这个选择通过 RCC 时钟配置寄存器(如 RCC_DCKCFGR)的某一位控制,该位通常命名为 CAN1SEL 或类似。当这一位设置为 1 时,CAN 的输入时钟就是 PCLK1 / 8,即 DIV8 生效。

tqT=125ns5.882ns=21.25\frac{tq}{T} = \frac{125ns}{5.882ns} = 21.25

因为BRP只能为整数,所以取DIV8=0,BRP=20。

假设我们采样点取在50%处:

50%=TSeg2NBT=(TSEG2+1)tq16tq=TSEG2+11650\% = \frac{T_{Seg2}}{NBT}= \frac{(TSEG2+1)*tq}{16*tq}=\frac{TSEG2+1}{16}

推出TSEG2=7TSEG2=7

TSeg1=NBTTseg2Tsync=1681=7TSeg1 = NBT-Tseg2-Tsync = 16-8-1 = 7

有:TSEG1=6TSEG1 = 6

最后计算SJW:

直接假设TSJW=3tqTSJW=3*tq使得下两式成立:

TSJW=(SJW+1)tqT_{SJW} = (SJW+1)*tqTSeg1TSJWTpropT_{Seg1} \ge T_{SJW}*T_{prop}TSeg2TSJWT_{Seg2} \ge T_{SJW}

故:

SJW=2SJW = 2

最终结果:

DIV8=0, BRP=20,TSEG1=6,TSEG2=7,SJW=2。

根据以上结果即可进行寄存器配置。

3. CAN数据帧

字段名称标准帧 (11位ID)扩展帧 (29位ID)值/说明作用/描述
帧起始SOF (1位)SOF (1位)显性 (0)同步所有节点,标志帧开始。
仲裁场ID (11位) + RTR (1位)基ID (11位) + SRR (1位) + IDE (1位) + 扩展ID (18位) + RTR (1位)标识符决定优先级;RTR区分数据/远程帧(数据帧显性0,远程帧隐性1)确定帧优先级和类型,实现非破坏性仲裁。
SRR:隐性(1);IDE:扩展帧中为隐性(1),标准帧中位于控制场为显性(0)SRR替代远程请求;IDE标识是否存在扩展ID。
控制场IDE (1位) + r0 (1位) + DLC (4位)r1 (1位) + r0 (1位) + DLC (4位)IDE显性0;保留位必须为显性0;DLC表示数据字节数0~8指明数据长度,保留位供未来扩展。
数据场0~8字节0~8字节由DLC指定长度携带实际发送的数据。
CRC场CRC序列 (15位) + CRC界定符 (1位)同标准帧CRC序列根据SOF至数据场计算;界定符为隐性1检测传输错误,保证数据完整性。
ACK场ACK槽 (1位) + ACK界定符 (1位)同标准帧发送器输出隐性1,正确接收节点覆盖为显性0;界定符为隐性1确认帧被至少一个节点正确接收。
帧结束EOF (7位)EOF (7位)全部为隐性1标志帧结束,之后进入间歇场。

补充说明

  • 位填充:从SOF到CRC场之间,若出现连续5个相同电平,自动插入一个相反电平的填充位(接收时删除),以保证时钟同步。
  • 帧间空间:数据帧结束后需有至少3位隐性间歇场,然后总线进入空闲。
信息

事实上,CAN的数据帧也经历过变迁:CAN 1.2时期,仅存在标准格式,IDE位当时仍为保留位r1。

CAN 2.0时期,ID不够用,出现了扩展格式,增加了ID的位数,为了区分标准格式与扩展格式,协议将标准格式中的r1赋予了新功能—IDE。

4. CAN遥控帧

遥控帧的作用是请求数据。本身不带数据,RTR位是隐性(1), 帧长度固定较短。仲裁优先级较小。

例子:

节点A发送遥控帧,ID=0x123,请求数据。

节点B恰好同时发送数据帧,ID=0x123,携带数据。

在仲裁场的最后一位(RTR位),数据帧发送显性0,遥控帧发送隐性1,总线呈现显性0,因此数据帧获胜,继续发送,遥控帧失去仲裁并转为接收。这样,节点A可以直接收到节点B的数据,而不需要再单独发送遥控帧,一举两得。

提示

一个典型的遥控帧应用场景如下:

  1. 节点A(请求者) 需要某些数据(例如发动机转速),它知道该数据对应的CAN ID(如0x200)。

  2. 节点A 构造一个遥控帧,ID=0x200,DLC设置为请求的数据长度(例如8字节),然后发送到总线上。

  3. 所有节点 都接收到该遥控帧,检查ID是否与自己相关。

  4. 节点B(数据持有者) 识别出ID=0x200是自己的数据,于是根据DLC准备对应长度的数据,并发送一个数据帧(ID相同,RTR=0,数据场包含所需数据)。

  5. 节点A 接收到节点B发来的数据帧,完成一次数据请求。

主节点轮询从节点数据,或按需获取特定信息时,用到遥控帧。频繁的遥控帧请求会增加总线负载,尤其在多节点请求同一数据时。通常更高效的做法是让数据源定期发送数据(如周期性发送),而不是靠请求触发。

遥控帧的DLC必须与响应节点实际发送的数据长度一致。如果不一致,可能导致数据截断或接收方解析错误。

如果发送遥控帧后,总线上没有节点响应(即没有节点发送对应ID的数据帧),请求节点可能需要设计超时重传或错误处理机制。

5. CAN错误帧

错误帧的作用是向总线上所有节点通报当前帧无效,并强制发送节点重传,从而保证数据的一致性。错误帧不是由用户主动发送的,而是由CAN控制器硬件在检测到总线错误时自动发出的。

错误帧由两个部分组成:错误标志(Error Flag) 和 错误界定符(Error Delimiter)。

总线上所有设备都会监督总线的数据,一旦发现“位错误”或“填充错误”或“CRC错误”或“格式错误”或“应答错误” ,这些设备便会发出错误帧来破坏数据,同时终止当前的发送设备

5.1 错误标志(Error Flag)

长度:6位

值:取决于检测到错误的节点状态:

  • 主动错误状态(Error Active):发送 6个显性位(000000)

  • 被动错误状态(Error Passive):发送 6个隐性位(111111)

作用:故意违反CAN协议的位填充规则(连续6个相同位),从而强制其他节点也检测到错误。

节点状态错误计数器值错误标志内容行为特点
主动错误状态0~1276个显性位能够主动破坏总线,通知所有节点
被动错误状态128~2556个隐性位只能“弱弱地”提示,不能干扰总线
总线关闭状态≥256不发送任何帧完全离线,不参与通信

5.2 错误界定符(Error Delimiter)

长度:8位

值:全部为 隐性位(11111111)

作用:标志错误帧的结束,让总线恢复隐性状态,以便开始后续的帧重传或新帧发送。

错误的种类错误的内容错误的检测帧(段)检测单元
位错误比较输出电平和总线电平(不含填充位),当两电平不一样时所检测到的错误。数据帧(SOF~EOF)
遥控帧(SOF~EOF)
错误帧
过载帧
发送单元
接收单元(发送单元在发送时检测,接收单元在接收时也可能检测,但严格来说位错误主要是发送单元检测)
填充错误在需要位填充的段内,连续检测到6位相同的电平时所检测到的错误。数据帧(SOF~CRC顺序)
遥控帧(SOF~CRC顺序)
接收单元
CRC错误从接收到的数据计算出的CRC结果与接收到的CRC顺序不同时所检测到的错误。数据帧(CRC顺序)
遥控帧(CRC顺序)
接收单元
格式错误检测出与固定格式的位段相反的格式时所检测到的错误。数据帧
(CRC界定符、ACK界定符、EOF)
遥控帧
(CRC界定符、ACK界定符、EOF)
错误界定符
过载界定符
接收单元
ACK错误发送单元在ACK槽(ACK Slot)中检测出隐性电平时所检测到的错误(ACK没被传送过来时所检测到的错误)。数据帧(ACK槽)
遥控帧(ACK槽)
发送单元

6. CAN过载帧

过载帧用于接收节点向发送节点指示“我还没准备好处理下一帧,请稍后再发”。它由两个部分组成:过载标志(Overload Flag, 全部为显性位) 和 过载界定符(Overload Delimiter, 全部为 隐性位)。

过载帧也是由硬件自动触发的,但它不是由于总线错误,而是由于接收节点内部条件(如缓冲区满、CPU未及时取走数据)导致的延迟请求。

一个节点最多可以连续发送两个过载帧来延迟总线。如果两个过载帧后它仍然没准备好,它只能丢弃后续帧(或设计上层协议处理)。

过载帧是一种底层的、临时的延迟机制,不适合做复杂的流量控制。在应用层(如CANopen)中,通常有专门的协议(如PDO的同步、阻止)来管理数据流。

随着微控制器性能提升和缓冲区增大,接收节点因缓冲区满而触发过载帧的情况越来越少。更多情况下,节点会直接丢弃来不及处理的帧,或依赖上层协议处理。

过载帧只在以下两种情况下被触发:

6.3 显性过载条件(接收节点未就绪)

最常见的触发情况:

一个节点正确接收了一帧数据(通过了CRC校验、ACK已发),但它的内部缓冲区已满,或者CPU还没处理完上一帧数据,无法接收新的帧。

此时,该节点会在帧间空间(Interframe Space)的第一个位(即间歇场的第一个位)发送一个过载帧,告诉总线:“请等一下,我还没准备好。”

6.4 隐性过载条件(检测到非法显性位)

在帧间空间的间歇场(3个隐性位) 期间,如果某个节点检测到了显性位(正常情况下间歇场应为全隐性),它会认为这是一个非法状态,于是发送过载帧来重新同步。

这种触发方式其实是一种错误处理机制,用于恢复总线状态。

注意:过载帧只能在一帧结束后的帧间空间开始发送,不能像错误帧那样在帧内任意位置触发。

提示

假设节点A正在发送数据帧给节点B,节点B接收完一帧后发现自己缓冲区满了:

  1. 正常接收:节点B正确接收了节点A发来的数据帧,并在ACK场发送了显性位确认。

  2. 检测到需要过载:节点B检查内部缓冲区,发现已满,无法接收下一帧。

  3. 等待帧间空间:当前帧结束后,总线进入帧间空间(3位隐性间歇场 + 总线空闲)。

  4. 发送过载帧:节点B在间歇场的第一个位(本该是隐性)发送一个显性位,这6个显性位构成过载标志。

  5. 其他节点响应:其他节点检测到间歇场出现显性位,也会跟着发送自己的过载标志(产生叠加)。

  6. 过载界定符:所有节点发送完过载标志后,等待8个隐性位(过载界定符)结束。

  7. 恢复通信:过载帧结束后,总线重新进入帧间空间,然后节点A可以尝试再次发送下一帧(或节点A检测到过载后自动延迟重发)。

7. CAN帧间隔

帧间隔(又叫帧间空间)用于分隔数据帧或远程帧的一段特定总线空闲时间。它使得总线在连续两帧之间有明确的间隙,让节点有时间处理刚接收到的帧,并为下一帧的发送做好准备。

哪些帧后面需要帧间隔?

  • 数据帧和远程帧:必须跟随帧间隔。

  • 错误帧和过载帧:不需要帧间隔。它们直接结束(错误界定符/过载界定符之后)就进入总线空闲,下一帧可以紧随其后。

为什么需要帧间隔?

  1. 总线恢复:让总线从可能的连续显性状态(如ACK槽显性)回到稳定的隐性电平,确保下一帧起始能被正确检测。

  2. 节点处理时间:接收节点需要时间将接收到的数据从移位寄存器移至缓冲区、更新错误计数器、准备下一帧接收。间歇场的3位提供了最小处理窗口。

  3. 公平访问:间歇场强制所有节点等待,避免某个节点紧跟着连续发送,给其他节点竞争机会。

  4. 过载帧触发点:如果接收节点未准备好,可以在间歇场的第一位发送过载帧,从而延迟下一帧。

注意

回忆一下刚刚讲过的过载帧。

过载帧只能在间歇场的第一位被触发。当某个接收节点在间歇场检测到显性位时,它会发送过载标志。此时,间歇场被中断,过载帧开始,之后再过载界定符结束,总线再次进入帧间隔(间歇场+总线空闲)。因此,过载帧实际上是在帧间隔期间插入的特殊帧。

7.1 间歇场(Intermission)

3个连续的隐性位。

所有节点在间歇场期间必须保持总线隐性。如果在此期间检测到显性位,则会触发过载帧(如前所述)。

间歇场的作用是让总线从活跃状态(可能有连续显性位)恢复隐性,并给节点一个短暂的准备窗口。

7.2 总线空闲(Bus Idle)

任意长度的隐性位。

只要总线保持隐性,就处于空闲状态。任何节点在检测到至少连续11个隐性位(间歇场3位 + 空闲至少8位)后,就可以开始发送下一帧(实际硬件只要检测到总线空闲即可开始发送,不一定等满11位,但规范推荐至少等待3位间歇后)。

总线空闲一直持续到有节点开始发送帧起始(SOF,显性位)为止。

7.3 被动错误节点的额外结构

如果发送节点处于被动错误状态(Error Passive),它在发送完一帧后,需要在间歇场之后额外插入一个暂停场(Suspend Transmission),然后再进入总线空闲。

[被动错误节点发送的帧] → [间歇场] → [暂停场] → [总线空闲] → [下一帧]

暂停场:8个连续的隐性位。

被动错误节点在发送完自己的帧后,必须等待这8位额外时间才能开始发送下一帧。这给其他节点(尤其是主动错误节点)更多机会占用总线,防止被动错误节点过度占用总线资源。

在此期间,其他节点可以在间歇场之后立即开始发送(因为总线空闲对它们来说是正常的),但被动错误节点必须多等8位。

8. 总线仲裁

8.1 仲裁过程

为了便于看懂,我们将总线上的节点简化到2个,分别是节点1和节点2。

当节点1发出一条报文到总线上时,节点2会监听到这条报文,并且会进行仲裁。其实节点1也会读取这条报文,称之为“回读”机制。这是为了自检发出去的报文有没有问题。

对比节点1发出的二进制位与总线上当前的二进制位是否一致,就可以知道报文是否被正确接收。

仲裁中我们主要考虑两种情况:

  1. 仲裁在前11位id结束。

线与机制,逐位比较。谁先比较出显性位,谁就赢了仲裁。

  1. 仲裁在前11位id未结束。

这说明前11位ID相同。

这种情况下需要回顾上表(或跳转至3.CAN数据帧查看帧结构),根据该表进一步分为4种情况:

注意

注意显性是0,隐性是1。

  1. 都是标准帧,对比数据帧与遥控帧:对比RTR位。标准帧的RTR位为0,扩展帧的RTR位为1。
  2. 都是扩展帧,对比数据帧与遥控帧:对比RTR位。注意,前11位ID和后18位ID需要相同。
  3. 数据帧中,对比标准帧和扩展帧格式:标准帧永远比扩展帧优先。对比标准格式的RTR位与扩展格式的SRR位,标准格式的RTR位恒为显性0,扩展格式的SRR位恒为隐性1。
  4. 遥控帧中,对比标准帧和扩展帧格式:标准帧永远比遥控帧优先。对比IDE位,扩展格式的IDE位恒为隐性1,标准格式的IDE位在控制段,恒为显性0。
注意

从这里可以得知,标准帧的优先级永远比扩展帧高。

9. 报文过滤

我们前面已经知道CAN总线没有地址这个概念,所有节点都能收到消息,但并不是所有节点都要知悉执行。由此我们需要报文过滤。所以报文过滤实际上是为每个节点筛选它感兴趣的CAN报文。这是基于ID进行过滤的。

要实现报文过滤,我们需要在CAN控制器中设置过滤器。你可以理解为设置一个白名单,只有白名单上的ID才能通过过滤器。并且这个白名单上会要求严格匹配某些位,其他可以忽略。

在STM32的CAN控制器中,我们可以设置掩码模式进行过滤。

9.1 报文过滤方式

我整理了大概6种过滤方式:

  1. 列表模式(List Mode / Exact Match Mode)

原理: 将滤波器配置为一个精确值的列表。只有当接收到的报文ID与列表中任意一个预设值完全相等时,报文才被接收。

特点:

  • 严格匹配:不支持通配符,每一位都必须相同。
  • 资源占用:每个滤波器只能指定一个ID。如果需要接收N个不同的ID,就需要占用N个滤波器(或占用多个滤波器槽位)。
  • 适用场景:节点只需要与几个固定的、离散的节点通信(点对点),或者需要严格过滤特定诊断ID。

示例(STM32 bxCAN): 配置为32位列表模式,两个寄存器分别存放两个完整的29位扩展ID。报文ID必须等于其中一个才能通过。

  1. 范围模式(Range Check / Dedicated Address Filter)

原理: 利用两个滤波器寄存器(或一个起始地址寄存器加一个结束地址寄存器)定义一个ID的连续区间。只要报文ID落在该区间内(包括端点),即被接收。

特点:

  • 区间接收:非常适合接收一组连续的ID(例如,传感器数据流地址范围 0x100~0x1FF)。
  • 硬件实现:有些CAN控制器通过两个掩码模式组合来实现(如ID1 < ID < ID2),有些则提供专门的“范围匹配”硬件。

示例(某些NXP FlexCAN): 支持“ID 区间匹配”,通过配置两个寄存器,硬件自动判断接收ID是否在 [ID_MIN, ID_MAX] 之间。

  1. 哈希表/内容寻址内存(CAM,Content-Addressable Memory)

原理: 这是一种硬件上的高级过滤方式。CAM是一种特殊的存储器,输入一个报文ID,硬件能在单个时钟周期内并行查找所有预设的ID值,并返回匹配结果。

特点:

  • 并行匹配:与掩码或列表模式的“串行遍历”不同,CAM是硬件级并行查找,速度极快且延迟固定。
  • 灵活性与数量:通常支持大量的条目(如64个、128个),每个条目可以是精确ID、带掩码的ID或范围。
  • 常见于:高端汽车MCU(如Infineon AURIX系列、Renesas RH850系列)中的CAN模块,或独立的CAN控制器。
  1. 基于优先级的过滤(Priority-Based Acceptance)

原理: 某些CAN控制器允许滤波器不仅基于ID,还基于报文优先级(即ID数值大小)来决策。例如,只接收ID数值小于某个阈值的报文。

特点:

  • 阈值过滤:常用于网关节点,只转发高优先级报文,丢弃低优先级报文,以防止总线负载过重。
  • 实现方式:通常是通过比较器将接收ID与预设的“最高允许ID”进行比较。
  1. 帧类型与远程帧过滤

原理: 除了对ID进行过滤,CAN控制器还可以针对帧格式(标准帧 vs. 扩展帧)和帧类型(数据帧 vs. 远程帧)进行独立过滤。

特点:

  • 精确控制:可以设置为“只接收标准数据帧,忽略扩展帧和远程帧”。
  • 实现方式:通常在验收滤波器的比较位中,将帧格式位(IDE)和远程帧位(RTR)作为ID扩展位的一部分参与匹配,或者由单独的寄存器控制。
  1. 软件/应用层过滤

当硬件滤波器资源不足(例如,需要接收数百个不同的ID,但控制器只有14个滤波器)时,硬件过滤无法完全满足需求,此时需配合软件过滤。

实现方式:

  1. 硬件粗筛:将硬件滤波器设置为“放行一大类报文”(例如,掩码模式允许所有ID高8位为0x7F的报文通过)。
  2. 中断处理:报文进入接收缓冲区后触发中断。
  3. 软件精筛:在中断服务程序或任务中,读取报文ID,通过查找表(LUT,Look-Up Table)、哈希映射或条件判断,进一步筛选出真正需要的报文;其余报文丢弃。

特点:

  • 灵活性高:可以实现复杂的过滤逻辑(如基于信号值、基于时间戳)。
  • CPU开销:会占用CPU资源,如果无关报文过多,可能导致中断频繁,影响系统实时性。

9.2 报文过滤示例

/**
* @brief 配置 FDCAN 掩码模式过滤器,接收指定范围内的标准 ID 报文
* @param hfdcan FDCAN 句柄指针
* @param filter_index 过滤器索引(0 ~ 27,取决于具体芯片)
* @param filter_id1 基准 ID(期望匹配的 ID 值)
* @param filter_id2 掩码(位=0 表示必须匹配,位=1 表示忽略)
* @return HAL 状态(HAL_OK 表示成功)
*
* @note 掩码模式过滤逻辑:
* (接收到的 ID & ~filter_id2) == (filter_id1 & ~filter_id2)
* 即:filter_id2 中为 0 的位必须与 filter_id1 完全相同,为 1 的位任意。
*
* @note 标准帧 ID 占用 11 位,filter_id1/filter_id2 只需使用低 11 位。
* 扩展帧需要 29 位,此时需写入完整的 29 位值。
*/
HAL_StatusTypeDef FDCAN_ConfigMaskFilter(FDCAN_HandleTypeDef *hfdcan,
uint32_t filter_index,
uint32_t filter_id1,
uint32_t filter_id2)
{
FDCAN_FilterTypeDef filter_config;

/* 1. 停止 FDCAN 外设(进入初始化模式) */
HAL_FDCAN_Stop(hfdcan);

/* 2. 配置过滤器参数 */
filter_config.IdType = FDCAN_STANDARD_ID; // 标准帧(11位 ID)
filter_config.FilterIndex = filter_index; // 使用的过滤器组索引
filter_config.FilterType = FDCAN_FILTER_MASK; // 掩码模式
filter_config.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; // 匹配的报文存入接收 FIFO0

/* 3. 设置基准 ID 和掩码
* - FilterID1: 基准 ID
* - FilterID2: 掩码(0 表示必须匹配,1 表示忽略)
*/
filter_config.FilterID1 = filter_id1;
filter_config.FilterID2 = filter_id2;

/* 4. 应用过滤器配置到硬件 */
if (HAL_FDCAN_ConfigFilter(hfdcan, &filter_config) != HAL_OK)
{
Error_Handler();
return HAL_ERROR;
}

/* 5. 重新启动 FDCAN(退出初始化模式,进入正常模式) */
if (HAL_FDCAN_Start(hfdcan) != HAL_OK)
{
Error_Handler();
return HAL_ERROR;
}

return HAL_OK;
}

/**
* @brief 示例:配置 FDCAN 接收 ID 0x321 和 0x322(标准帧)
* @retval 无
*/
void Example_FDCAN_MaskFilter(void)
{
uint32_t filter_id1 = 0x321; // 基准 ID
uint32_t filter_id2 = 0x001; // 掩码(仅忽略最低位)

FDCAN_ConfigMaskFilter(&hfdcan2, 0, filter_id1, filter_id2);
}

10. CAN控制器寄存器

分为控制寄存器和状态寄存器两种,分别用于设置和读取CAN控制器的寄存器。

10.1 控制/状态寄存器

以下是对STM32 CAN外设寄存器的分类总结,以表格形式呈现。基于常见的STM32系列(如F103、F405等),寄存器偏移地址均以CAN外设基地址(例如CAN1基址:0x40006400)为基准。

偏移地址寄存器名称功能描述关键位域
0x00CAN_MCR主控制寄存器控制CAN模块的工作模式、初始化、自动重传等INRQ:初始化请求SLEEP:睡眠模式请求TXFP:发送FIFO优先级RFLM:接收FIFO锁定模式NART:禁止自动重传AWUM:自动唤醒模式ABOM:自动总线关闭管理TTCM:时间触发通信模式
0x04CAN_MSR主状态寄存器反映CAN模块的状态INAK:初始化确认SLAK:睡眠确认ERRI:错误中断标志WKUI:唤醒中断标志SLAKI:睡眠确认中断TXM:发送模式RXM:接收模式
0x08CAN_TSR发送状态寄存器显示发送邮箱的状态及发送结果RQCPx:请求完成标志(x=0..2)TXOKx:发送成功标志ALSTx:仲裁丢失标志TERRx:传输错误标志ABRQx:中止发送请求CODE:发送邮箱代码TME:发送邮箱空闲
0x0CCAN_RF0R接收FIFO 0寄存器管理接收FIFO 0的填充状态FMP0:FIFO 0中消息数量FULL0:满标志FOVR0:溢出标志RFOM0:释放FIFO 0输出
0x10CAN_RF1R接收FIFO 1寄存器管理接收FIFO 1的填充状态同RF0R(对应位域)
0x14CAN_IER中断使能寄存器使能各类中断源TMEIE:发送邮箱空闲中断FMPIE0:FIFO0消息挂起中断FFIE0:FIFO0满中断FOVIE0:FIFO0溢出中断FMPIE1/FFIE1/FOVIE1:对应FIFO1EWGIE:错误警告中断EPVIE:错误被动中断BOFIE:总线关闭中断LECIE:错误码中断ERRIE:错误中断WKUIE:唤醒中断SLKIE:睡眠中断
0x18CAN_ESR错误状态寄存器记录错误计数器和错误代码TEC:发送错误计数器REC:接收错误计数器EWGF:错误警告标志EPVF:错误被动标志BOFF:总线关闭标志LEC:最后错误代码(位错误、填充错误等)
0x1CCAN_BTR位时序寄存器配置波特率和采样点BRP:波特率预分频器TS1:时间段1TS2:时间段2SJW:再同步跳转宽度SILM:静默模式(只监听)LBKM:环回模式(自测)

10.2 邮箱寄存器

CAN控制器包含3个发送邮箱(0~2)和2个接收FIFO(0和1),每个邮箱都有独立的标识符、数据长度和数据寄存器。

10.2.1 发送邮箱寄存器(每组对应一个邮箱 x=0..2)

偏移地址寄存器名称功能描述关键位域
0x180 + 0x10*xCAN_TIxR发送邮箱标识符寄存器存放待发送消息的ID和帧格式STID:标准标识符(11位)EXID:扩展标识符(18位,与STID拼接成29位)IDE:标识符扩展位(0=标准帧,1=扩展帧)RTR:远程帧请求
0x184 + 0x10*xCAN_TDTxR发送邮箱数据长度和时间戳寄存器数据长度、时间戳及发送控制DLC:数据长度(0~8)TGT:时间戳触发使能TIME:时间戳(仅在时间触发模式下有效)
0x188 + 0x10*xCAN_TDLxR发送邮箱低字节数据寄存器存放数据字节0~3DATA0~DATA3
0x18C + 0x10*xCAN_TDHxR发送邮箱高字节数据寄存器存放数据字节4~7DATA4~DATA7

10.2.2 接收FIFO邮箱寄存器(每组对应一个FIFO y=0..1)

偏移地址寄存器名称功能描述关键位域
0x1B0 + 0x10*yCAN_RIyR接收FIFO邮箱标识符寄存器存放接收到的消息ID和帧格式CAN_TIxR
0x1B4 + 0x10*yCAN_RDTyR接收FIFO邮箱数据长度和时间戳寄存器接收消息的数据长度及时间戳DLC:数据长度FMI:过滤器匹配索引TIME:时间戳
0x1B8 + 0x10*yCAN_RDLyR接收FIFO邮箱低字节数据寄存器存放接收的数据字节0~3CAN_TDLxR
0x1BC + 0x10*yCAN_RDHyR接收FIFO邮箱高字节数据寄存器存放接收的数据字节4~7CAN_TDHxR

10.3 过滤器寄存器

STM32 CAN控制器支持最多28个过滤器组(具体数量取决于型号,如F103为14组),每组可配置为32位或16位模式,用于报文过滤。

偏移地址寄存器名称功能描述关键位域
0x200CAN_FMR过滤器主控寄存器全局控制过滤器的初始化和工作模式FINIT:过滤器初始化模式CAN2SB:CAN2起始组(用于双CAN设备)
0x204CAN_FM1R过滤器模式寄存器配置每组过滤器的模式(列表模式或掩码模式)FBMx:x=0..27,0=掩码模式,1=列表模式
0x20CCAN_FS1R过滤器位宽寄存器配置每组过滤器的位宽(32位或16位)FSCx:x=0..27,0=2×16位,1=1×32位
0x214CAN_FFA1R过滤器FIFO关联寄存器指定每组过滤器关联的接收FIFO(FIFO0或FIFO1)FFAx:x=0..27,0=FIFO0,1=FIFO1
0x21CCAN_FA1R过滤器激活寄存器使能或禁用每组过滤器FACTx:x=0..27,1=激活,0=禁用
0x240 + 8*iCAN_FiR1过滤器组i寄存器1存放过滤器的ID值或掩码(取决于模式)对于32位模式: - 掩码模式:IDMASK各占32位 - 列表模式:两个32位ID对于16位模式: - 掩码模式:四个16位ID+MASK - 列表模式:四个16位ID
0x244 + 8*iCAN_FiR2过滤器组i寄存器2同上FiR1配合使用

  • 过滤器组的索引 i 从 0 开始,最多到 27(实际支持数量取决于芯片)。
  • 在双CAN设备中,CAN2的过滤器起始组由CAN_FMRCAN2SB设定。
  • 每个过滤器组必须先在CAN_FMR中置FINIT=1进入初始化模式后才能配置,配置完成后清除FINIT激活过滤。

11. CAN FD

CAN FD是灵活数据率CAN,2011年由Bosch推出,解决了CAN带宽不足、数据传输效率低的问题。遵循ISO 11898-1 (2015)协议版本。

危险

CAN FD并不是CAN扩展帧,它是新的协议标准。

CAN FD最大支持64字节,仲裁段与数据段可设置为不同波特率,支持 BRS(位速率切换)标志,CRC相比于CAN的15位提升到了17/21位从而提升了可靠性。

CAN FD可以兼容经典CAN,但反之无法兼容。他们同样支持标准帧格式和扩展帧格式。

Image

帧结构直观对比:

CAN:

SOF | 仲裁场 | 控制场 | 数据场(0-8) | CRC场 | ACK场 | EOF

CAN FD:

SOF | 仲裁场 | 控制场(BRS标志) | 数据场(0-64) | CRC场 | ACK场 | EOF
└─ 速率1 ──┘ └─ 速率2(更快)─┘

与传统CAN相比,CAN FD取消了对远程帧(遥控帧)的支持,用RRS位替换了RTR位,为常显性。

注意

RRS位为常显性,而不是隐性。如果这一位被定义为隐性,那么接收方会按传统CAN来处理。

CAN FD在控制场中新添加了FDF位、BRS位、ESI位。与CAN相同,IDE位表示扩展帧标志,res位为预留位。

FDF位:当FDF为隐形位(1)时,表示使用CAN FD协议,而不是传统CAN协议。

BRS位:当BRS为隐形位(1)时,表示转换可变速率,即发送节点在BRS位的采样点,将会切换到高速传输的时钟模式,其他接收节点也必须转换位时钟模式。在CRC界定符的采样点,所有节点的波特率将会再切换回仲裁场的波特率。也就是说,所有CAN FD节点都有两种类型的波特率。

  • BRS = 0:数据段仍使用仲裁段速率(兼容模式)

  • BRS = 1:数据段切换到更高的波特率(如 2Mbps、5Mbps、8Mbps)

ESI(Error State Indicator) 位:用于指示发送节点的错误状态。

在STM32的CANFD控制器的CCCR寄存器中有一个FDOE位,用于启用或禁用 CAN FD模式。

关于CRC,经典 CAN 使用 15 位 CRC,在长数据场下检错能力有限。

FDCAN是可以选用不同位数的,CAN FD 根据数据场长度选择:

  1. 数据场 ≤ 16 字节:CRC 17 位

  2. 数据场 > 16 字节:CRC 21 位

并且 CRC 计算覆盖了填充位计数器,进一步降低漏检率。

11.1 CAN FD 控制寄存器

11.1.1 CCCR (Clock Control Register)

功能: 控制FDCAN的时钟、初始化、模式和协议设置

名称描述参数/值
0INIT初始化模式1=初始化模式,0=正常操作
1CCE配置更改使能1=允许配置更改
2ASMASM受限操作模式0=正常模式,1=受限模式
3CSA时钟停止确认硬件只读,1=时钟已停止
4CSR时钟停止请求1=请求停止时钟
5MON总线监控模式1=只监听模式
6DAR禁用自动重传1=禁用,0=启用
7TEST测试模式使能1=启用测试模式
8FDOEFD操作使能1=启用FD模式,0=经典CAN
9BRSE位速率切换1=启用数据段不同速率
12PXHD协议异常处理禁用1=禁用,0=启用
13EFBI总线集成期间边沿滤波1=启用,0=禁用
14TXP两个CAN位时间暂停1=启用,0=禁用
15NISO非ISO操作1=非ISO模式,0=ISO兼容

11.1.2 NBTP (Nominal Bit Timing and Prescaler Register)

功能: 配置标称位定时参数

位域名称范围描述
0-6NTSEG20-127采样点后时间段 (TSEG2)
8-15NTSEG10-255采样点前时间段 (TSEG1)
16-24NBRP0-511位速率预分频器 (BRP)
25-31NSJW0-127同步跳转宽度 (SJW)

位时间计算:

  • 位时间 = (BRP+1) × (TSEG1+1 + TSEG2+1 + 3) × tq
  • 采样点位置 = (TSEG1+1) / (TSEG1+1 + TSEG2+1 + 3)
  • 项目配置:500Kbps @ 170MHz时钟

11.1.3 DBTP (Data Bit Timing and Prescaler Register)

功能: 配置FD模式数据段位定时参数

位域名称范围描述
0-3DSJW0-15数据段同步跳转宽度
4-7DTSEG20-15数据段TSEG2
8-12DTSEG10-31数据段TSEG1
16-20DBRP0-31数据段位速率预分频器
23TDC0-1收发器延迟补偿

11.1.4 TXBC (Tx Buffer Configuration Register)

功能: 配置发送缓冲区操作模式

名称描述参数项目配置
24TFQMTx FIFO/Queue模式0=FIFO模式,1=Queue模式0 (FIFO模式)

11.1.5 TXBCR (Tx Buffer Cancellation Request Register)

功能: 请求取消待发送消息

位域名称描述参数
0-2CR取消请求位n=1表示取消缓冲区n的消息

11.1.6 TXBCIE (Tx Buffer Cancellation Finished Interrupt Enable Register)

功能: 使能发送取消完成中断

位域名称描述参数
0-2CFIE取消完成中断使能位n=1表示缓冲区n的取消完成中断使能

11.1.7 TXBCF (Tx Buffer Cancellation Finished Register)

功能: 显示取消操作完成状态

位域名称描述参数
0-2CF取消完成标志位n=1表示缓冲区n的取消操作已完成

11.1.8 RXGFC (Rx FIFO/Gateway Configuration Register)

功能: 配置接收FIFO和网关操作

位域名称描述参数
0RRFE拒绝远程帧扩展1=拒绝,0=接受
1RRFS拒绝远程帧标准1=拒绝,0=接受
2-3ANFE接受不匹配帧扩展0=不接受,1=存入FIFO0,2=存入FIFO1,3=拒绝
4-5ANFS接受不匹配帧标准0=不接受,1=存入FIFO0,2=存入FIFO1,3=拒绝
8F1OMFIFO1操作模式0=阻塞模式,1=覆盖模式
9F0OMFIFO0操作模式0=阻塞模式,1=覆盖模式
16-20LSS标准帧列表大小0-31
24-27LSE扩展帧列表大小0-15

11.1.9 IE (Interrupt Enable Register)

功能: 使能各种中断源

名称描述
0RF0NERx FIFO0新消息使能
1RF0FERx FIFO0满使能
2RF0LERx FIFO0消息丢失使能
3RF1NERx FIFO1新消息使能
4RF1FERx FIFO1满使能
5RF1LERx FIFO1消息丢失使能
6HPME高优先级消息使能
7TCE发送完成使能
8TCFE发送取消完成使能
9TFEETx FIFO空使能
10TEFNETx事件FIFO新条目使能
11TEFFETx事件FIFO满使能
12TEFLETx事件FIFO元素丢失使能
13TSWE时间戳回绕使能
14MRAFE消息RAM访问失败使能
15TOOE超时发生使能
16ELOE错误日志溢出使能
17EPE错误被动使能
18EWE警告状态使能
19BOE总线关闭状态使能
20WDIE看门狗中断使能
21PEAE仲裁阶段协议错误使能
22PEDE数据阶段协议错误使能
23ARAE访问保留地址使能

11.1.10 ILE (Interrupt Line Enable Register)

功能: 将中断分配到不同的中断线

名称描述参数项目配置
0EINT0使能中断线01=使能,0=禁用根据需要
1EINT1使能中断线11=使能,0=禁用根据需要

11.2 状态寄存器

11.2.1 PSR (Protocol Status Register)

功能: 显示FDCAN协议的当前状态

位域名称范围描述硬件属性
0-2LEC0-7最后一个错误代码 (Last Error Code)只读
3-4ACT0-3当前活动状态 (0=同步,1=接收,2=发送)只读
5EP0-1错误被动标志 (1=错误被动)只读
6EW0-1警告状态 (1=错误计数器达到96)只读
7BO0-1总线关闭状态 (1=总线关闭)只读
8-10DLEC0-7数据段最后错误代码只读
11RESI0-1最后接收消息的ESI标志只读
12RBRS0-1最后接收消息的BRS标志只读
13REDL0-1最后接收消息是FDCAN消息标志只读
14PXE0-1协议异常事件标志只读
16-22TDCV0-127收发器延迟补偿值只读

11.2.2 ECR (Error Counter Register)

功能: 显示CAN错误计数器状态

位域名称范围描述硬件属性
0-7TEC0-255发送错误计数器只读
8-14REC0-127接收错误计数器只读
15RP0-1接收错误被动标志只读
16-23CEL0-255CAN错误日志计数器只读

11.2.3 IR (Interrupt Register)

功能: 显示中断事件标志(写1清除)

名称描述
0RF0NRx FIFO 0新消息
1RF0FRx FIFO 0满
2RF0LRx FIFO 0消息丢失
3RF1NRx FIFO 1新消息
4RF1FRx FIFO 1满
5RF1LRx FIFO 1消息丢失
6HPM高优先级消息
7TC发送完成
8TCF发送取消完成
9TFETx FIFO空
10TEFNTx事件FIFO新条目
11TEFFTx事件FIFO满
12TEFLTx事件FIFO元素丢失
13TSW时间戳回绕
14MRAF消息RAM访问失败
15TOO超时发生
16ELO错误日志溢出
17EP错误被动
18EW警告状态
19BO总线关闭
20WDI看门狗中断
21PEA仲裁阶段协议错误
22PED数据阶段协议错误
23ARA访问保留地址

11.2.4 ILS (Interrupt Line Select)

功能: 将中断事件分配到两条中断线

名称描述参数
0RXFIFO0Rx FIFO 0事件中断线选择0=INT0,1=INT1
1RXFIFO1Rx FIFO 1事件中断线选择0=INT0,1=INT1
2SMSG发送消息事件中断线选择0=INT0,1=INT1
3TFERRTx FIFO事件中断线选择0=INT0,1=INT1
4MISC杂项事件中断线选择0=INT0,1=INT1
5BERR总线错误事件中断线选择0=INT0,1=INT1
6PERR协议错误事件中断线选择0=INT0,1=INT1

11.2.5 RXF0S (Rx FIFO 0 Status Register)

功能: 显示Rx FIFO 0的填充状态和索引

位域名称范围描述硬件属性
0-3F0FL0-15FIFO 0填充级别 (元素数量)只读
8-9F0GI0-3FIFO 0读出索引只读
16-17F0PI0-3FIFO 0写入索引只读
24F0F0-1FIFO 0满标志只读
25RF0L0-1FIFO 0消息丢失标志只读/写1清

11.2.6 RXF0A (Rx FIFO 0 Acknowledge Register)

功能: 更新FIFO 0的读出指针

位域名称范围描述硬件属性
0-2F0AI0-7FIFO 0确认索引读/写

11.2.7 RXF1S (Rx FIFO 1 Status Register)

功能: 显示Rx FIFO 1的填充状态和索引

位域名称范围描述硬件属性
0-3F1FL0-15FIFO 1填充级别只读
8-9F1GI0-3FIFO 1读出索引只读
16-17F1PI0-3FIFO 1写入索引只读
24F1F0-1FIFO 1满标志只读
25RF1L0-1FIFO 1消息丢失标志只读/写1清

11.2.8 TXFQS (Tx FIFO Queue Status Register) - 0x4000A490

功能: 显示Tx FIFO队列的填充状态

位域名称范围描述硬件属性
0-2TFFL0-7FIFO空闲级别只读
8-9TFGI0-3FIFO读出索引只读
16-17TFQPI0-3FIFO/Queue写入指针只读
21TFQF0-1FIFO/Queue满标志只读

11.2.9 HPMS (High Priority Message Status Register)

功能: 显示高优先级消息状态

位域名称范围描述硬件属性
0-2BIDX0-7缓冲区索引只读
6-7MSI0-3消息存储指示 (0=未存储,1=FIFO0,2=FIFO1,3=Buffer)只读
8-12FIDX0-31过滤器索引只读
15FLST0-1过滤器列表 (0=标准,1=扩展)只读

References

[1]. 谦益行,一篇易懂的CAN通讯协议指南1.EB/OL[2026-03-26].https://zhuanlan.zhihu.com/p/162708070