本文整理自个人 CAN 总线学习笔记,面向刚接触 CAN 的嵌入式初学者。从"CAN 是什么"讲起,依次梳理总线拓扑与工作过程、物理层差分信号、协议层的帧结构与位时序/仲裁,最后落到 STM32 的 bxCAN 控制器(工作模式、收发流程、接收过滤器)与 HAL 库驱动的基本步骤。基于 STM32 + HAL 库。

一、CAN 是什么
1.1 产生背景与历史
CAN(Controller Area Network,控制器局域网),是一种 ISO 国际标准化的串行通信协议。

它的诞生是为了满足汽车产业的两个需求:

减少线束的数量——汽车电子设备越来越多,线束又重又贵;
通过多个 LAN 进行大量数据的高速通信。
历史脉络:

1986 年:博世(Bosch)公司开发出 CAN 通信协议;
1993 年:ISO 发布标准 ISO11898(高速 CAN) 与 ISO11519(低速 CAN);
2011 年:博世公司开发出 CAN FD;
如今 CAN 已成为汽车网络标准协议之一。
1.2 CAN 的分类
类型 标准 通信速率 总线长度
低速 CAN ISO11519 10 ~ 125 Kbps 可达 1000 米
高速 CAN ISO11898 125 Kbps ~ 1 Mbps ≤ 40 米
CAN FD 兼容经典 CAN(遵循 ISO11898-1 收发) 可达 5 Mbps —
CAN FD 兼容经典 CAN,是对经典 CAN 的高速扩展。

二、CAN 总线拓扑与工作过程
2.1 总线组成
一条 CAN 总线由三个层次组成:

CAN 控制器:MCU 内部的片上外设(STM32 内部就有这个外设),每个节点都要有一个;
CAN 收发器:与其他元器件组成芯片电路,负责电平转换与保护;
总线:由 CANL 和 CANH 两根线组成,允许挂载多个节点(低速 CAN 约 20 个、高速 CAN 约 30 个)。
几个关键点:

低速 CAN 使用开环总线,高速 CAN 使用闭环总线;
总线两端都有匹配电阻(也叫终端电阻),用于阻抗匹配、减少回波反射;
收发器把处理好的电压(差分信号)传递到 CAN 总线上。
一个便于理解的类比:CAN 总线结构类似美国式联邦政府——各州(节点)平时独立处理本地事件,但始终处于"美国"(CAN 总线)这个大框架之下;需要联合行动时,按大框架的规则配合。

2.2 发送过程
CAN 控制器(集成在 MCU 内部)负责处理 CAN 协议的逻辑、数据帧封装/解析,输出逻辑电平信号(TX/RX);
CAN 收发器接收控制器发来的逻辑电平,转换成对应的差分电平输出给总线;
收发器同时具有过压保护和抗干扰的作用。
2.3 接收过程(三步)
总线是双向的,当某个控制器发送的数据最终传到总线上时:

① 收发器反向工作:所有节点的 CAN 收发器都时刻在监听总线。收到总线上的差分电平信号后,利用差分特性过滤掉噪音(抗干扰),再翻译回普通的 0/1 电平,顺着 CAN_RX 引脚传递给 MCU 内部的 CAN 控制器。

② 控制器筛选处理:控制器收到信号后,不会立刻丢给 CPU,而是先做两个判断:

硬件过滤:看一眼数据包的 ID,不是发给自己的,直接在硬件层面丢弃,完全不让 CPU 知道——这是 CAN 省资源的关键;
硬件校验:自己再算一遍 CRC 校验码,和发过来的不一致(说明受到干扰、数据损坏),同样直接丢弃。
③ 触发中断:经判断 ID 匹配且数据完好后,控制器将数据存入缓存,并向 CPU 触发一个硬件中断;CPU 收到中断后,经过中断控制来处理数据并执行对应操作。

2.4 CAN 总线特点
多主控制:每个设备都可以主动发送数据;
系统的柔软性:没有类似"地址"的信息,添加设备不改变原来总线的状态;
通信速度:速度快、距离远;
错误检测 / 错误通知 / 错误恢复:三位一体;
故障封闭:判断故障类型,并且进行隔离;
连接节点多:通常根据实际情况,在速度和数量之间找平衡。
CAN 总线协议已广泛应用在汽车电子、工业自动化、船舶、医疗设备、工业设备等方面。

三、CAN 物理层
3.1 差分信号与总线电平
CAN 使用差分信号进行数据传输,根据 CAN_H 与 CAN_L 上的电位差来判断总线电平:

总线电平分为显性电平(逻辑 0)与隐性电平(逻辑 1),二者必居其一;
显性电平具有优先权;
发送方通过使总线电平发生变化,将消息发送给接收方。
高速 CAN 经典电平值:

电平 CAN_High CAN_Low 电位差
显性电平(0) 3.5V 1.5V 2V
隐性电平(1) 2.5V 2.5V 0V
低速 CAN 经典电平值:

电平 CAN_High CAN_Low 电位差
显性电平(0) 4V 1V 3V
隐性电平(1) 1.75V 3.25V -1.5V
表格及图中的电平值只是经典值,实际上数据手册中提供的是 CAN 总线电平值的范围。

3.2 常见收发器芯片
常见的 CAN 收发器芯片有 TJA1050、TJA1042、SIT1050T。以 SIT1050T 为例:支持高速 CAN,传输速率可达 1Mbps(其 TXD/RXD 引脚分别连接 CAN 控制器的发送/接收引脚)。

四、CAN 协议层
4.1 五种帧
CAN 总线以"帧"的形式进行通信,协议定义了 5 种帧:

帧类型 作用
数据帧(Data Frame) 发送单元向接收单元传输数据(最常用)
遥控帧(Remote Frame) 接收单元向具有相同 ID 的发送单元请求数据(较常用)
错误帧(Error Frame) 检测出错误时向其他单元通知错误
过载帧(Overload Frame) 接收单元通知外部自己尚未做好接收准备
间隔帧(Inter Frame Space) 将数据帧及遥控帧与前面的帧分离开
4.2 数据帧的 7 段结构
数据帧由 7 段组成,又分为标准帧(CAN2.0A)和扩展帧(CAN2.0B),区别主要体现在仲裁段和控制段。

① 帧起始段:仅 1 bit,表示数据帧开始,是显性电平(0)。

② 仲裁段:表示该帧优先级的段。

标准帧的仲裁段只有两部分:
ID(11bit):标识符位,体现优先级信息;
RTR(1bit):远程传输请求位——显性(0)代表此帧是数据帧,隐性(1)代表此帧是遥控帧(之后的各段按遥控帧的格式解析)。
扩展帧的仲裁段有五部分:
基础 ID(11bit):标识符位,体现优先级信息;
SRR(1bit):仅"在意义上替代一下 RTR",并没有什么实际含义,作用是保持仲裁段结构的一致性,在扩展帧中始终为隐性电平(1);
IDE(1bit):扩展标识符位,用于标识当前帧是标准帧还是扩展帧——显性(0)= 标准帧,隐性(1)= 扩展帧;
扩展 ID(18bit):与基础 ID 组合形成完整的 29 位标识符,扩展可用 ID 的数量,同样体现优先级信息;
RTR(1bit):远程传输请求位。
③ 控制段:表示数据的字节数以及保留位的段。

标准帧控制段:IDE(1bit)(含义同上)+ R0 保留位(1bit) + DLC(4bit);
扩展帧控制段:两个保留位(各 1bit) + DLC(4bit)(扩展帧的 IDE 已在仲裁段中出现,故控制段不再有)。
其中保留位是 CAN 协议官方为未来协议升级或功能扩展预留的"空位",当前版本必须设为显性电平(0);DLC(4bit) 是数据长度编码位,其存储的信息表示接下来的数据段内有多少个字节的数据。

④ 数据段:存储数据的具体内容,一帧可发送 0 ~ 8 字节的数据。

⑤ CRC 段:检查帧的传输错误的段。

CRC(15bit):循环冗余校验位。发送节点把每一帧 CRC 段之前的所有数据经特定多项式计算后,赋值到 CRC 部分;接收节点收到数据后用同样的公式重算——结果与收到的 CRC 值不一致,说明数据在传输中出错(比如被电磁干扰),接收方会立即报错并丢弃这帧数据;
DEL(1bit):CRC 界定符,表示 CRC 校验部分结束,必须是隐性电平(1)。
⑥ ACK 段:表示确认正常接收的段,类似于 IIC 中的应答信号。

ACK(1bit):确认位。发送单元先将其置为隐性(1);经过校验准确后,接收单元会主动在总线上将此信号拉低为显性(0);发送单元此时同时在监听总线,就知道传输成功了;
DEL(1bit):界定符,必须是隐性电平(1)。
⑦ 帧结束段:表示数据帧结束,占 7bit,使用 7 个隐性信号(1)表示结束。

4.3 位时序与位同步
CAN 总线以"位同步"机制实现对电平的正确采样。每一位数据都由四个时间段组成:

同步段(SS)
传播时间段(PTS)
相位缓冲段 1(PBS1)
相位缓冲段 2(PBS2)
每段又由多个时间量子 Tq 组成。采样点是指读取总线电平、并将读到的电平作为位值的点。采样的前提条件:节点监测到总线上信号的跳变在自己的 SS 段范围内,表示节点与总线的时序是同步的,此时采样点的电平即该位的电平。

每一位数据对应的位时间并不是固定值,而是有一个范围:8 ~ 25 个 Tq;
根据位数据的位时序数量,可以计算 CAN 通信的波特率。
由于时钟频率误差、传输上的相位延迟会引起偏差,需要进行数据同步。数据同步的主要目标是使采样点同步(或者说采样点正确),分为硬件同步和再同步:

同步方式 触发信号 特点
硬件同步 帧起始信号 只同步一次:把 SS 段平移到监测到边沿的地方
再同步 普通数据位的边沿 持续进行,确保后续数据的同步
硬件同步:节点发送数据一开始会发送帧起始信号,总线上其他节点检测帧起始信号是否落在自己位时间的 SS 段内,判断内部时序与总线是否同步。假如不在 SS 段内,采样点获得的电平状态是不正确的,节点就用硬件同步的方式调整,把自己的 SS 段平移到监测到边沿的地方,获得同步。

再同步:利用普通数据位的边沿信号(帧起始信号是特殊的边沿信号)进行同步,分超前与滞后两种情况:

超前(边沿信号超前于 SS 段,出现在上一位数据的 PBS2 中):硬件逻辑会在上一位数据的 PBS2 缓冲区中丢弃对应长度的时间;
滞后(边沿信号滞后于 SS 段,出现在当前位数据的 PTS 中):硬件逻辑会在当前位数据的 PBS1 缓冲区结尾插入对应长度的空闲时间或重复采样点。
再同步时 PBS1 和 PBS2 中增加或减少的时间称为"再同步补偿宽度(SJW)",范围是 1 ~ 4 Tq。限定了(最大的)SJW 值后,再同步时不能增加限定长度外的 SJW 值。SJW 值较大时吸收误差能力更强,但是通信速度会下降。

4.4 总线仲裁
CAN 总线的仲裁由优先级决定,但不存在"抢占"——优先级的权力只体现在同时发送时:

总线处于空闲状态时,最先开始发送消息的单元获得发送权;
多个单元同时开始发送时,从仲裁段(报文 ID)的第一位开始仲裁:连续输出显性电平最多的单元可继续发送,即首先出现隐性电平的单元失去对总线的占有权、变为接收;
利用 CAN 控制器的回读机制,节点可判断自己是否在总线仲裁中失利;
竞争失败的单元会自动检测总线空闲,在第一时间再次尝试发送。
五、STM32 CAN 控制器(bxCAN)
5.1 bxCAN 简介
STM32 的 CAN 控制器(bxCAN)支持 CAN 2.0A 和 CAN 2.0B Active 版本协议。三者对扩展帧的处理能力不同:

控制器版本 标准帧 扩展帧
CAN 2.0A 可处理 识别为错误
CAN 2.0B Active 可处理 可处理
CAN 2.0B Passive 可处理 忽略
bxCAN 主要特点:

波特率最高可达 1 Mbps;
支持时间触发通信(CAN 的硬件内部定时器可以在 TX/RX 的帧起始位的采样点位置生成时间戳);
具有3 级发送邮箱;
具有 3 级深度的 2 个接收 FIFO;
可变的过滤器组(最多 28 个)。
5.2 工作模式与测试模式
工作模式(三种):初始化模式、正常模式、睡眠模式。

模式 说明
初始化模式 需要对寄存器进行配置(软件初始化)时进入
正常模式 总线同步完成后即可收发,正常通信
睡眠模式 复位后默认进入,总线空闲,优点是降低功耗
测试模式(三种,在初始化模式下进行配置):静默模式、环回模式、环回静默模式。

模式 行为 用途
静默模式 发送端相当于断路、与外界无关联,无法拉低总线电平,只能发送隐性信号 1;接收端正常工作,可接收总线数据 可用来统计总线流量
环回模式 接收端短接到发送端,发送的数据直接到 CAN 控制器的输入;总线能监测到发送的数据,但控制器不能从总线接收数据 可自检
环回静默模式 发送端与接收端短接且都与总线断路:总线监测不到发送的数据,CAN 也不能接收总线上的数据 可进行不影响总线的自检
5.3 控制器框图
以 F1、F4、F7 的框图为例(H7 使用的 CAN FD 有所不同;过滤器组也不是每款 STM32 都有)。

CAN 内核:包含各种控制/状态/配置寄存器,可配置模式、波特率等;其中 CAN1 是主内核,CAN2 是从内核(不是每款 STM32 都有);
发送邮箱:缓存待发送的报文,最多 3 个,配有发送调度装置;
接收 FIFO:缓存接收到的有效报文;
接收过滤器:筛选有效报文。
5.4 发送处理流程
发送数据前,首先选择一个空置邮箱;
设置标识符(ID)、发送长度(DLC)、发送数据(DATA),将数据帧设置完整后放入邮箱(通常是放入编号最小的空置邮箱);
邮箱退出空状态后,会自动请求数据发送,进入挂号状态;
挂号状态下,邮箱等待成为优先级最高的邮箱;
成为最高优先级后,进入预定发送状态,接着等待总线进入空闲状态;
总线空闲时,邮箱进入发送状态,报文发送成功,邮箱重新回到空置状态。
发送优先级由邮箱中报文的标识符(ID)决定:ID 数值越低优先级越高;如果标识符值相同,则邮箱编号小的先被发送。

5.5 接收处理流程
空置的 FIFO 接收到经过滤器过滤后得到的有效报文,进入"挂号_1"状态;
此时读取 FIFO 邮箱中的报文并释放(将对应寄存器的对应位置 1),即可清除该状态,FIFO 的挂起数量减 1(此操作可在任意挂起状态下进行);
否则,FIFO 继续收到有效报文时,进入"挂号_2"状态,接着继续接收会进入"挂号_3"状态(FIFO 中有效报文的数量可从寄存器的 FMP 位得知);
如果在"挂号_3"状态下 FIFO 依然收到有效报文,就会进入溢出状态,出现报文丢失问题(报文是否丢失取决于 FIFO 的锁定功能);
报文全部读取后,FIFO 重新进入空置状态。
有效报文 = 数据帧直到 EOF 段的最后一位都没有错误,且通过过滤器组对标识符的过滤。

5.6 接收过滤器
当总线上报文数据量很大时,总线上的设备会频繁获取报文、占用 CPU。过滤器的存在意义就是选择性接收有效报文,减轻系统负担。

每个过滤器组都有两个 32 位寄存器 CAN_FxR1 和 CAN_FxR2(根据过滤器组的工作模式不同,寄存器的作用不尽相同),位宽可设置为 32 位或 16 位:

32 位宽模式:一个过滤器组(比如 F0)只处理一个完整的 32 位数据,通常用于过滤扩展帧;
16 位宽模式:寄存器由两部分组成,相当于过滤器被拆成两个独立的 16 位过滤器,通常用于同时过滤两个标准帧(其中的 EXTID 即扩展 ID 部分只是占位,标准帧中不存在扩展 ID)。
工作模式可选择屏蔽位模式或标识符列表模式:

屏蔽位模式:R1 存放一帧数据,R2 设置条件(掩码)——位值为 1 表示必须匹配,0 表示不关心(即 R2 中第 a 位是 1,则只有第 a 位与 R1 中数据相同状态的数据才可以通过过滤器)。针对标识符中的一部分做筛选,可选出一组符合条件的报文;
标识符列表模式:针对整个标识符,可以选择出几个特定 ID 的报文。
注意点:

标识符选择位 IDE 和帧类型 RTR 需要一致;
不同过滤器组的工作模式可以设置为不同;
在使能过滤器的情况下,总线上广播的报文 ID 与过滤器的配置都不匹配时,CAN 控制器会丢弃该报文,不会进入接收 FIFO。
5.7 STM32 位时序与波特率
STM32 的 CAN 外设位时序分为三段:

同步段 SYNC_SEG
时间段 1 BS1(= 协议中的 PTS + PBS1)
时间段 2 BS2
波特率的计算:TS1(相位缓冲段 1)、TS2(相位缓冲段 2)都在寄存器中定义,与 BRP 共同决定波特率(对于 F103 来说,BRP 的值是 1/36M,即 CAN 时钟为 36MHz 时不分频):

波特率 = CAN 时钟 / (BRP × (1 + TS1 + TS2))

通信双方波特率需一致才能通信成功。

六、HAL 库驱动基本步骤
CAN 参数初始化:设置工作模式、波特率等 → HAL_CAN_Init;
使能 CAN 时钟 + 初始化相关引脚:GPIO 的模式需设为复用功能模式,这两个操作放到 CAN 初始化回调函数 HAL_CAN_MspInit 中完成;
设置过滤器:通过 HAL_CAN_ConfigFilter 完成过滤器的初始化配置;
CAN 数据接收和发送:HAL_CAN_AddTxMessage 发送数据,HAL_CAN_GetRxMessage 接收数据;
中断(按需):使用 __HAL_CAN_ENABLE_IT 使能 CAN 相关中断,配置 NVIC,编写中断服务函数。
注意事项:

使能 CAN2(从 CAN)时,需要先使能 CAN1(主 CAN);
重要结构体:CAN_InitTypeDef、CAN_FilterTypeDef 和 CAN_TxHeaderTypeDef / CAN_RxHeaderTypeDef。
总结
CAN 是什么:为汽车"减少线束、多 LAN 高速通信"而生的 ISO 标准化串行通信协议,从经典 CAN 一路发展到 CAN FD;
物理层:差分信号按 CAN_H/CAN_L 电位差判电平;显性(0)优先、隐性(1);高速/低速 CAN 电平值不同,以数据手册范围为准;
协议层:5 种帧;数据帧 7 段(帧起始/仲裁/控制/数据/CRC/ACK/帧结束),标准帧 vs 扩展帧的区别主要在仲裁段和控制段;
位时序:SS/PTS/PBS1/PBS2 + Tq;硬件同步(帧起始、只一次)+ 再同步(普通边沿、持续);SJW 越大容错越强、速度越慢;
仲裁:没有"抢占";同时发送时显性连续最多者胜,先出现隐性电平者退出转接收,失败后自动重试;
bxCAN:CAN 2.0B Active 才能完整处理扩展帧;3 级发送邮箱、2 个接收 FIFO、最多 28 个过滤器组;过滤器有 32/16 位宽和屏蔽/列表两种模式;
HAL 上手:Init → MspInit(时钟 + GPIO 复用)→ ConfigFilter → AddTxMessage / GetRxMessage → 中断(按需);CAN2 依赖 CAN1。
待学习(诚实标注):CAN 相关寄存器介绍、CAN 相关 HAL 库驱动细节尚未学完,学完后再补充更新本文。

如果这篇文章对你有帮助,欢迎点赞收藏;如有错误或疑问,欢迎在评论区交流。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐