HAL_CAN
文章目录
- 一、CAN 简介
- 1、CAN 总线
- 2、CAN 核心硬件特点
- 3、CAN 物理信号线详解
- 4、CAN 两大协议标准
- 5、典型应用场景
- 二、CAN 模块详解
- 1、CAN功能框图
- 该芯片内置两路 CAN2.0B 控制器:
- ① 控制 / 状态配置寄存器组(CAN1 主 + CAN2 从两套独立)
- ② 发送邮箱模块(主 CAN1 + 从 CAN2 各 3 个发送邮箱)
- ③ 主接收 FIFO0 / FIFO1(仅 CAN1 拥有双 FIFO)
- ④ 验收筛选器组(CAN1 独占,共 28 组:主 0~27、从 0~27)
- ⑤ 共享 512Byte SRAM & 存储器访问控制器
- 2、CAN基本结构
- 1.基本功能框图
- 2. 接收流程
- 3. 发送流程
- 4.发送和接收配置位
- 3、标识符过滤器
- 1.过滤器能功框图
- 2.过滤顺配置示例
- 4、测试模式
- 1.静默模式
- 2.环回模式
- 3.环回静默模式
- 5、工作模式
- 6、位时间特性
- 1.时钟来源
- 2.单时间TQ时长
- 3.1位总TQ个数
- 4.波特率计算
- 5.常用波特率配置
- 6.位时序图
- 7、中断
- 8、时间触发通信
- 9、错主处理和离线恢复
- 10、CAN 与 UART/SPI/IIC 核心区别
- 三、CubeMX 标准 CAN 配置
- 1、基础配置
- Bit Timings Parameters
- Basic Parameters(工程推荐全开容错)
- Advanced Parameters
- 2、关键模式说明
- 3、配置注意事项
- 四、CAN编程模块
- 1、CAN结构
- 1.CAN_HandleTypeDef 外设句柄(顶层总控)
- 2.CAN_InitTypeDef 初始化时序结构体
- 3.CAN_FilterTypeDef 过滤器结构体(框图过滤器核心)
- 4.CAN_TxHeaderTypeDef 发送报文头(对应 3 个发送邮箱)
- 5.CAN_RxHeaderTypeDef 接收报文头(对应 FIFO 缓存)
- 2、HAL_CAN_API
- 1.初始化 / 反初始化类
- 2.过滤器配置专用
- 3.外设启停控制
- 4.报文发送操作
- 5.报文接收操作
- 6.中断管理
- 7.状态 / 错误查询
- 8.低功耗睡眠模式
- 五、CAN 应用实例
- 1、CubeMX配置
- 1.Bit Timings Parameters(工业标准 500kbps,PCLK1=36M)
- 2.Basic Parameters(工程推荐全开容错)
- 3.Advanced Parameters
- 4.NVIC 中断配置(中断接收必备)
- 5.配置完成在代码生成后使能CAN
- 2、发送代码参考
- 3、过滤器配置代码参考
- 4、接收代码参考
- 5、实验结果
- 六、CAN 核心要点与避坑大全
- 1、核心知识点
- 2、高频坑点
- 3、工程最佳实践
- 4、一句话总结
- 七、全篇总结
一、CAN 简介
1、CAN 总线
CAN(Controller Area Network,控制器局域网),是一种串行、异步、差分、多主、高可靠现场总线,专为复杂电磁环境、多设备组网通信设计,是车载电子、工业控制、机器人、智能家居的核心通信总线。
不同于UART/SPI/IIC板内短距离通信,CAN支持远距离、抗干扰强、多设备无主组网、自动仲裁容错,是唯一可用于工业和车载恶劣环境的低速总线。
2、CAN 核心硬件特点
差分信号传输:CAN_H、CAN_L 差分电压传输,抗电磁干扰能力极强。
多主架构:无固定主机从机,任意节点均可主动发送数据。
总线仲裁机制:多节点同时发数据时,ID优先级自动仲裁,无数据冲突。
自带错误容错:硬件自动重发、错误计数、离线保护。
远距离通信:125Kbps下可通信1000米,远超其他串口。
总线广播机制:一发多收,全网节点均可监听数据。
3、CAN 物理信号线详解
闭环总线网络
开环总线网络:
CAN_H:总线高位差分线。
CAN_L:总线低位差分线。
120Ω、2.2kΩ终端电阻:总线首尾节点必须并联,用于阻抗匹配、防止信号反射。
正常工作电平:显性电平(CAN_H高、CAN_L低,差分压差)、隐性电平(双线电平近似相等,压差为0)。
4、CAN 两大协议标准
CAN 2.0A(标准帧):11位ID,设备少、简单组网使用。
CAN 2.0B(扩展帧):29位ID,海量设备组网、车载设备标配。
5、典型应用场景
车载电子:汽车仪表、电机控制、车身组网、自动驾驶外设。
工业控制:PLC通信、工业传感器、伺服电机组网。
机器人:多舵机、多控制器协同通信。
楼宇智能、无人设备、恶劣电磁环境数据传输。
二、CAN 模块详解
1、CAN功能框图
该芯片内置两路 CAN2.0B 控制器:
CAN1(主):拥有完整硬件资源(发送邮箱、接收 FIFO、28 组验收筛选器),具备筛选器主控权;
CAN2(从):无独立筛选器,复用 CAN1 的验收筛选器,仅自带控制状态寄存器、收发缓存;
两者共用一片 512Byte 片内 SRAM 作为报文存储区,由存储器访问控制器统一调度。
① 控制 / 状态配置寄存器组(CAN1 主 + CAN2 从两套独立)
每套 CAN 都拥有独立寄存器,功能完全一致:
主控制:使能 CAN、睡眠模式、软件复位、自动重发、时间触发模式开关。
主状态:总线空闲 / 发送忙 / 接收忙、总线错误、离线状态标记。
发送状态:3 个发送邮箱空满、发送完成、发送失败标记。
接收 FIFO 0/1 状态:FIFO 满、FIFO 溢出、新报文到达标志。
中断使能:发送完成、接收报文、错误、总线离线中断开关。
错误状态:发送错误计数 TEC、接收错误计数 REC、错误类型位。
位定时:配置波特率、采样点、同步跳转宽度 BS1/BS2。
筛选器专属寄存器(仅 CAN1 有效):筛选器主模式、单 / 双 32 位模式、FIFO 分配、筛选器激活开关。
主从差异:
CAN2 无筛选器配置寄存器,所有报文过滤规则全部由 CAN1 统一配置。
② 发送邮箱模块(主 CAN1 + 从 CAN2 各 3 个发送邮箱)
CAN1:主发送邮箱 0/1/2;CAN2:从发送邮箱 0/1/2;
每个邮箱存储一帧完整 CAN 报文(ID + 数据长度 + 8 字节数据);
内置传输调度程序:硬件自动仲裁 3 个邮箱优先级,按 ID 优先级顺序发送;
发送流程:CPU 填充邮箱 → 置位发送请求 → 调度器竞争总线 → 总线发送完成置中断标志。
③ 主接收 FIFO0 / FIFO1(仅 CAN1 拥有双 FIFO)
两路独立先进先出接收缓冲区,硬件自动分流匹配报文:
FIFO0:分配低序号筛选器报文;FIFO1:分配高序号筛选器报文;
每个 FIFO 内置 3 级缓存,支持连续接收多帧不丢失;
报文匹配筛选器后,硬件自动存入对应 FIFO,产生接收中断;
读取报文后 CPU 释放缓存空间,FIFO 自动移位。
④ 验收筛选器组(CAN1 独占,共 28 组:主 0~27、从 0~27)
核心报文过滤硬件,CAN2 完全复用此模块,是双 CAN 架构核心:
总计 28 个筛选器单元,支持两种模式:
32 位模式:单个筛选器匹配标准 ID + 扩展 ID + 掩码;
16 位双筛选:一个单元拆为两组短 ID 筛选;
每个筛选器可绑定分配到 FIFO0 或 FIFO1;
报文流程:总线接收报文 → 筛选器匹配校验 → 匹配成功送入对应 FIFO,匹配丢弃;
CAN1 为主控,可开启 / 关闭、配置所有筛选器;CAN2 无配置权限,仅共享过滤规则。
⑤ 共享 512Byte SRAM & 存储器访问控制器
存储资源:整片 512 字节 SRAM 由 CAN1、CAN2 共同占用,存放所有发送邮箱、接收 FIFO、筛选器掩码 / ID 表;
存储器访问控制器:硬件仲裁 CPU/CAN1/CAN2 的读写请求,避免 SRAM 访问冲突;
资源分配规则:
CAN1 占用大部分缓存;CAN2 仅占用自身 3 个发送邮箱缓存;
筛选器表、CAN1 接收 FIFO 固定占用 SRAM 前段空间。
2、CAN基本结构
1.基本功能框图
2. 接收流程
CAN 总线差分信号 → CAN 内核位同步 → 报文帧接收 → 筛选器匹配校验 → 匹配成功存入CAN1 FIFO0/FIFO1 → CPU 读取 FIFO 数据。
3. 发送流程
CPU 填充 CAN1/CAN2 发送邮箱(主 / 从邮箱)→ 传输调度程序仲裁发送顺序 → 存储器控制器读取 SRAM 报文 → CAN 内核编码输出到 CAN 总线。
4.发送和接收配置位
NART:
置1,关闭自动重传,CAN报文只被发送1次,不管发送的结果如何(成功、出错或仲裁丢失);置0,自动重传,CAN硬件在发送报文失败时会一直自动重传直到发送成功。
TXFP:
置1,优先级由发送请求的顺序来决定,先请求的先发送;置0,优先级由报文标识符来决定,标识符值小的先发送(标识符值相等时,邮箱号小的报文先发送)。
RFLM:
置1,接收FIFO锁定,FIFO溢出时,新收到的报文会被丢弃;置0,禁用FIFO锁定,FIFO溢出时,FIFO中最后收到的报文被新报文覆盖
3、标识符过滤器
1.过滤器能功框图
每个过滤器的核心由两个32位寄存器组成:R1[31:0]和R2[31:0]。
FSCx:位宽设置
置0,16位;置1,32位。
FBMx:模式设置
置0,屏蔽模式;置1,列表模式。
FFAx:关联设置
置0,FIFO 0;置1,FIFO 1。
FACTx:激活设置
置0,禁用;置1,启用。
2.过滤顺配置示例
4、测试模式
1.静默模式
用于分析CAN总线的活动,不会对总线造成影响。
2.环回模式
用于自测试,同时发送的报文可以在CAN_TX引脚上检测到。
3.环回静默模式
用于热自测试,自测的同时不会影响CAN总线。
5、工作模式
初始化模式:用于配置CAN外设,禁止报文的接收和发送。
正常模式:配置CAN外设后进入正常模式,以便正常接收和发送报文。
睡眠模式:低功耗,CAN外设时钟停止,可使用软件唤醒或者硬件自动唤醒。
AWUM:置1,自动唤醒,一旦检测到CAN总线活动,硬件就自动清零SLEEP,唤醒CAN外设;置0,手动唤醒,软件清零SLEEP,唤醒CAN外设。
6、位时间特性
1.时钟来源
STM32F103 的 CAN 外设挂载 APB1 总线。
系统时钟 SYSCLK=72MHz,APB1 预分频器 = 2 → PCLK1 = 36MHz(工程最常用)。
APB1 预分频 = 1 时,PCLK1=72MHz。
2.单时间TQ时长
TQ = Prescaler/PCLK1。Prescaler:CAN 分频器(CubeMX 参数 Prescaler for Time Quantum)
3.1位总TQ个数
CAN 一位分为 4 段:SYNC_SEG (固定 1TQ) + BS1 + BS2
(TotalTQ = 1 + BS1 + BS2)
4.波特率计算
BaudRate = PCLK1/Prescaler/(1+BS1+BS2)
5.常用波特率配置
| 目标波特率 | Prescaler | BS1 | BS2 | TotalTQ | 采样点 |
|---|---|---|---|---|---|
| 1000 kbps | 2 | 13 | 2 | 16 | 87.5% |
| 750 kbps | 3 | 13 | 2 | 16 | 87.5% |
| 500 kbps | 4 | 13 | 2 | 16 | 87.5% |
| 250 kbps | 8 | 13 | 2 | 16 | 87.5% |
| 125 kbps | 16 | 13 | 2 | 16 | 87.5% |
| 50 kbps | 40 | 13 | 2 | 16 | 87.5% |
| 20 kbps | 100 | 13 | 2 | 16 | 87.5% |
6.位时序图
SS = 1Tq。
BS1 = 1~16Tq。
BS2 = 1~8Tq。
SJW=1~4Tq。
波特率 = APB1时钟频率 / 分频系数 / 一位的Tq数量
= 36MHz / (BRP[9:0]+1) / (1 + (TS1[3:0]+1) + (TS2[2:0]+1))
7、中断
CAN外设占用4个专用的中断向量:
发送中断:发送邮箱空时产生。
FIFO 0中断:收到一个报文/FIFO 0满/FIFO 0溢出时产生。
FIFO 1中断:收到一个报文/FIFO 1满/FIFO 1溢出时产生。
状态改变错误中断:出错/唤醒/进入睡眠时产生。
8、时间触发通信
TTCM:置1,开启时间触发通信功能;置0,关闭时间触发通信功能。
CAN外设内置一个16位的计数器,用于记录时间戳。
TTCM置1后,该计数器在每个CAN位的时间自增一次,溢出后归零。
每个发送邮箱和接收FIFO都有一个TIME[15:0]寄存器,发送帧SOF时,硬件捕获计数器值到发送邮箱的TIME寄存器,接收帧SOF时,硬件捕获计数器值到接收FIFO的TIME寄存器。
发送邮箱可配置TGT位,捕获计数器值的同时,也把此值写入到数据帧数据段的最后两个字节,为了使用此功能,DLC必须设置为8。
9、错主处理和离线恢复
TEC和REC根据错误的情况增加或减少。
ABOM:
置1,开启离线自动恢复,进入离线状态后,就自动开启恢复过程;
置0,关闭离线自动恢复,软件必须先请求进入然后再退出初始化模式,随后恢复过程才被开启。
10、CAN 与 UART/SPI/IIC 核心区别
| 通信总线 | CAN | UART | SPI | IIC |
|---|---|---|---|---|
| 传输方式 | 差分异步 | 单端异步 | 单端同步 | 单端同步 |
| 组网方式 | 多主多从、无冲突仲裁 | 一对一 | 一主多从(片选) | 一主多从(地址) |
| 抗干扰 | 极强(差分传输) | 弱 | 中 | 弱 |
| 传输距离 | 最远1000米 | 几十米 | 板内短距离 | 板内短距离 |
| 容错能力 | 硬件自动容错重发 | 无硬件容错 | 无硬件容错 | 无硬件容错 |
三、CubeMX 标准 CAN 配置
1、基础配置
Parameter Settings 位时序 & 基础参数(工业标准 500kbps,PCLK1=36M)
Bit Timings Parameters
| 参数 | 标准配置 | 说明 |
|---|---|---|
| Prescaler (for Time Quantum) | 4 | 时钟分频 |
| Time Quanta in Bit Segment 1 | 13 | BS1,保证高采样点 |
| Time Quanta in Bit Segment 2 | 2 | BS2 |
| ReSynchronization Jump Width(SJW) | 1 | 同步宽度 |
Basic Parameters(工程推荐全开容错)
Time Triggered Communication Mode:Disable。
Automatic Bus-Off Management:Enable(总线短路自动恢复)。
Automatic Wake-Up Mode:Disable。
Automatic Retransmission:Enable(发送失败自动重发)。
Receive Fifo Locked Mode:Disable。
Transmit Fifo Priority:Disable(硬件按 ID 仲裁优先级)。
Advanced Parameters
Test Mode:
Normal(正常总线模式)
Loopback:内部自测;
Silent:仅监听不发送
2、关键模式说明
Normal 正常模式:真实总线收发,工程正式使用。
Loopback 回环模式:内部自收自发,无需外接设备,纯代码调试。
Silent 静默模式:只接收不发送,总线监听专用。
3、配置注意事项
总线两端必须焊接120Ω终端电阻,否则通信乱码、丢包。
所有CAN节点波特率、时序参数必须完全一致。
未配置过滤器或过滤器屏蔽错误,会接收不到数据。
调试优先使用回环模式,无需外接硬件即可验证代码。
四、CAN编程模块
1、CAN结构
1.CAN_HandleTypeDef 外设句柄(顶层总控)
typedef struct { CAN_TypeDef *Instance; // CAN寄存器基地址(CAN1/CAN2) CAN_InitTypeDef Init; // 时序、工作模式配置 CAN_FilterTypeDef FilterConfig; // 过滤器配置缓存 HAL_LockTypeDef Lock; // 互斥锁,多任务防冲突 __IO HAL_StateTypeDef State; // 外设运行状态 __IO uint32_t ErrorCode; // 硬件错误标志 } CAN_HandleTypeDef;2.CAN_InitTypeDef 初始化时序结构体
对应框图位定时、总线基础功能开关 typedef struct { uint32_t Prescaler; // 波特率分频TQ uint32_t Mode; // 工作模式:正常/自测/监听 uint32_t SyncJumpWidth; // SJW同步跳转宽度 uint32_t TimeSeg1; // BS1时间段 uint32_t TimeSeg2; // BS2时间段 FunctionalState TimeTriggeredMode; // TTCAN时间触发关闭/开启 FunctionalState AutoBusOff; // 总线离线自动恢复 FunctionalState AutoWakeUp; // 总线唤醒睡眠 FunctionalState AutoRetransmission; // 发送失败自动重发 FunctionalState ReceiveFifoLocked; // FIFO满锁定不覆盖旧数据 FunctionalState TransmitFifoPriority; // 邮箱ID优先级发送 } CAN_InitTypeDef;3.CAN_FilterTypeDef 过滤器结构体(框图过滤器核心)
HAL_CAN_ConfigFilter() 入参,对应硬件 0~27 组 Filter Bank typedef struct { uint32_t FilterBank; // 过滤器编号0~27 uint32_t FilterMode; // 模式:掩码匹配/列表匹配 uint32_t FilterScale; // 位宽:32位(单ID)/16位(双ID) uint32_t FilterIdHigh; // ID寄存器高16位 uint32_t FilterIdLow; // ID寄存器低16位 uint32_t FilterMaskHigh; // 掩码寄存器高16位 uint32_t FilterMaskLow; // 掩码寄存器低16位 uint32_t FilterFIFOAssignment; // 匹配报文送入FIFO0/FIFO1 uint32_t FilterActivation; // 过滤器使能/关闭 uint32_t SlaveFilterBank; // 双CAN时分配给CAN2的过滤器段 } CAN_FilterTypeDef;4.CAN_TxHeaderTypeDef 发送报文头(对应 3 个发送邮箱)
填充后调用HAL_CAN_AddTxMessage()写入发送邮箱 typedef struct { uint32_t StdId; // 标准ID 0~0x7FF uint32_t ExtId; // 扩展ID 0~0x1FFFFFFF uint32_t IDE; // 帧类型:标准帧CAN_ID_STD / 扩展帧CAN_ID_EXT uint32_t RTR; // 远程帧CAN_RTR_REMOTE / 数据帧CAN_RTR_DATA uint32_t DLC; // 数据长度0~8字节 FunctionalState TransmitGlobalTime; // 时间触发时间戳 } CAN_TxHeaderTypeDef;5.CAN_RxHeaderTypeDef 接收报文头(对应 FIFO 缓存)
HAL_CAN_GetRxMessage() 读取 FIFO 报文输出参数 typedef struct { uint32_t StdId; // 接收报文标准ID uint32_t ExtId; // 接收报文扩展ID uint32_t IDE; // 标准/扩展帧标识 uint32_t RTR; // 数据帧/远程帧标识 uint32_t DLC; // 接收数据长度 uint32_t FilterMatchIndex; // 匹配的过滤器编号 } CAN_RxHeaderTypeDef;2、HAL_CAN_API
1.初始化 / 反初始化类
HAL_CAN_Init(CAN_HandleTypeDef *hcan):根据句柄 Init 配置初始化 CAN 外设时序与模式。 HAL_CAN_DeInit(CAN_HandleTypeDef *hcan):复位 CAN 外设,清空运行状态。 HAL_CAN_MspInit(CAN_HandleTypeDef *hcan):底层 MSP 初始化,开启时钟、配置 TX/RX 引脚复用。 HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan):释放 CAN 底层资源,关闭外设时钟、恢复 GPIO。2.过滤器配置专用
HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig):配置 ID 过滤器,设置匹配规则与绑定 FIFO。3.外设启停控制
HAL_CAN_Start(CAN_HandleTypeDef *hcan):使能 CAN 内核,退出睡眠,进入正常收发状态。 HAL_CAN_Stop(CAN_HandleTypeDef *hcan):关闭 CAN 内核,进入睡眠,停止总线收发。4.报文发送操作
HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pTxHeader, const uint8_t *pData, uint32_t *pTxMailbox):填充空闲发送邮箱,载入待发报文,返回使用的邮箱号。 HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailbox):取消指定邮箱未发送报文,释放邮箱缓存。 HAL_CAN_GetTxMailboxesFreeLevel(CAN_HandleTypeDef *hcan):查询当前空闲发送邮箱数量(0~3)。 HAL_CAN_IsTxMessagePending(CAN_HandleTypeDef *hcan, uint32_t TxMailbox):查询指定邮箱是否存在待发送报文。5.报文接收操作
HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pRxHeader, uint8_t *pData):从指定 FIFO 读取一帧完整接收报文。 HAL_CAN_GetRxFifoFillLevel(CAN_HandleTypeDef *hcan, uint32_t RxFifo):查询 FIFO 内缓存的未读报文数量(0~3)。 HAL_CAN_ClearRxFifoOverrunFlag(CAN_HandleTypeDef *hcan, uint32_t RxFifo):清除 FIFO 报文溢出标志,代表存在丢帧。6.中断管理
中断开关: HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs):开启指定 CAN 中断(接收 / 发送 / 故障)。 HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs):关闭指定 CAN 中断 中断底层入口: HAL_CAN_IRQHandler(CAN_HandleTypeDef *hcan):CAN 中断服务总入口,解析中断标志并分发对应回调 发送完成回调(用户重写): void HAL_CAN_TxMailbox0CompleteCallback(CAN_HandleTypeDef *hcan):邮箱 0 报文发送完成回调。 void HAL_CAN_TxMailbox1CompleteCallback(CAN_HandleTypeDef *hcan):邮箱 1 报文发送完成回调。 void HAL_CAN_TxMailbox2CompleteCallback(CAN_HandleTypeDef *hcan):邮箱 2 报文发送完成回调。 FIFO 接收回调(用户重写): void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan):FIFO0 收到新报文中断回调。 void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan):FIFO1 收到新报文中断回调。 FIFO 状态异常回调(用户重写): void HAL_CAN_RxFifo0FullCallback(CAN_HandleTypeDef *hcan):FIFO0 缓存已满中断回调。 void HAL_CAN_RxFifo1FullCallback(CAN_HandleTypeDef *hcan):FIFO1 缓存已满中断回调。 void HAL_CAN_RxFifo0OverrunCallback(CAN_HandleTypeDef *hcan):FIFO0 报文溢出丢帧回调。 void HAL_CAN_RxFifo1OverrunCallback(CAN_HandleTypeDef *hcan):FIFO1 报文溢出丢帧回调。 总线故障回调(用户重写): void HAL_CAN_BusOffCallback(CAN_HandleTypeDef *hcan):总线离线 BusOff 严重故障回调。 void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan):通用硬件错误中断回调(位错 / 仲裁丢失等)。7.状态 / 错误查询
HAL_StateTypeDef HAL_CAN_GetState(CAN_HandleTypeDef *hcan):获取 CAN 外设当前运行状态(就绪 / 忙 / 错误)。 uint32_t HAL_CAN_GetError(CAN_HandleTypeDef *hcan):读取 CAN 硬件错误标志位。 HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan):清除硬件错误计数 TEC/REC 与错误标志。8.低功耗睡眠模式
HAL_CAN_EnterSleepMode(CAN_HandleTypeDef *hcan):控制 CAN 进入低功耗睡眠模式。 HAL_CAN_WakeUpFromSleepMode(CAN_HandleTypeDef *hcan):软件唤醒睡眠中的 CAN 外设,恢复通信。五、CAN 应用实例
1、CubeMX配置
1.Bit Timings Parameters(工业标准 500kbps,PCLK1=36M)
| 参数 | 标准配置 | 说明 |
|---|---|---|
| Prescaler (for Time Quantum) | 4 | 时钟分频 |
| Time Quanta in Bit Segment 1 | 13 | BS1,保证高采样点 |
| Time Quanta in Bit Segment 2 | 2 | BS2 |
| ReSynchronization Jump Width(SJW) | 1 | 同步宽度 |
2.Basic Parameters(工程推荐全开容错)
Time Triggered Communication Mode:Disable(TTCAN 时间触发模式)
Automatic Bus-Off Management:Enable(总线短路自动恢复)
Automatic Wake-Up Mode:Disable(总线自动唤醒)
Automatic Retransmission:Enable(发送失败自动重发)
Receive Fifo Locked Mode:Disable(FIFO 满锁定)
Transmit Fifo Priority:Disable(硬件按 ID 仲裁优先级)
3.Advanced Parameters
Test Mode:
Normal(正常总线模式)
Loopback(内部自测)
Silent(仅监听不发送)
4.NVIC 中断配置(中断接收必备)
5.配置完成在代码生成后使能CAN
//使能CAN HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan);2、发送代码参考
CAN_TxHeaderTypeDef can_Tx; uint8_t sendBuf[5] = {"hello"}; uint32_t box; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_CAN_Init(); HAL_CAN_Start(&hcan); can_Tx.StdId = 0x123; can_Tx.ExtId = 0; can_Tx.IDE = CAN_ID_STD; can_Tx.RTR = CAN_RTR_DATA; can_Tx.DLC = 5; can_Tx.TransmitGlobalTime = DISABLE; while (1) { HAL_CAN_AddTxMessage(&hcan, &can_Tx, sendBuf, &box); HAL_Delay(100); } }3、过滤器配置代码参考
//1.配置为CAN总线上所有的报文都会被接收,并存入FIFO0中。 CAN_FilterTypeDef can_Filter = {0}; can_Filter.FilterIdHigh = 0; can_Filter.FilterIdLow = 0; can_Filter.FilterMaskIdHigh = 0; can_Filter.FilterMaskIdLow = 0; can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; can_Filter.FilterBank = 0; can_Filter.FilterMode = CAN_FILTERMODE_IDMASK; can_Filter.FilterScale = CAN_FILTERSCALE_32BIT; can_Filter.FilterActivation = CAN_FILTER_ENABLE; HAL_CAN_ConfigFilter(&hcan, &can_Filter); //2.配置仅接收标准ID为0x0的数据帧和遥控帧,并存入FIFO0中。 /* CAN_FilterTypeDef can_Filter = {0}; can_Filter.FilterIdHigh = 0; can_Filter.FilterIdLow = 0; can_Filter.FilterMaskIdHigh = 0; can_Filter.FilterMaskIdLow = 2; can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; can_Filter.FilterBank = 0; can_Filter.FilterMode = CAN_FILTERMODE_IDLIST; can_Filter.FilterScale = CAN_FILTERSCALE_32BIT; can_Filter.FilterActivation = CAN_FILTER_ENABLE; HAL_CAN_ConfigFilter(&hcan, &can_Filter); */4、接收代码参考
使能CAN外设中断函数:
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
实例代码:
#include <stdio.h> CAN_RxHeaderTypeDef can_Rx; uint8_t recvBuf[8]; uint8_t uartBuf[64]; int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_CAN_Init(); MX_USART1_UART_Init() CAN_FilterTypeDef can_Filter = {0}; can_Filter.FilterIdHigh = 0; can_Filter.FilterIdLow = 0; can_Filter.FilterMaskIdHigh = 0; can_Filter.FilterMaskIdLow = 0; can_Filter.FilterFIFOAssignment = CAN_FILTER_FIFO0; can_Filter.FilterBank = 0; can_Filter.FilterMode = CAN_FILTERMODE_IDMASK; can_Filter.FilterScale = CAN_FILTERSCALE_32BIT; can_Filter.FilterActivation = CAN_FILTER_ENABLE; HAL_CAN_ConfigFilter(&hcan1, &can_Filter); HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING); HAL_CAN_Start(&hcan); while (1) { } } void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) { uint16_t len = 0; HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &can_Rx, recvBuf); if(can_Rx.IDE == CAN_ID_STD) { len += sprintf((char *)&uartBuf[len], "标准ID:%#X; ", can_Rx.StdId); } else if(can_Rx.IDE == CAN_ID_EXT) { len += sprintf((char *)&uartBuf[len], "扩展ID:%#X; ", can_Rx.ExtId); } if(can_Rx.RTR == CAN_RTR_DATA) { len += sprintf((char *)&uartBuf[len], "数据帧; 数据为:"); for(int i = 0; i < can_Rx.DLC; i ++) { len += sprintf((char *)&uartBuf[len], "%X ", recvBuf[i]); } len += sprintf((char *)&uartBuf[len], "\r\n"); HAL_UART_Transmit(&huart, uartBuf, len, 100); } else if(can_Rx.RTR == CAN_RTR_REMOTE) { len += sprintf((char *)&uartBuf[len], "遥控帧\r\n"); HAL_UART_Transmit(&huart, uartBuf, len, 100); } }5、实验结果
六、CAN 核心要点与避坑大全
1、核心知识点
CAN为差分异步多主总线,抗干扰强、支持远距离组网。
ID越小优先级越高,硬件自动仲裁,无总线冲突。
总线首尾必须120Ω终端电阻,是通信成功的前提。
单帧最大8字节数据,超长数据需分包传输。
必须配置过滤器,否则无法正常接收总线数据。
支持自动重发、错误计数、总线离线保护。
2、高频坑点
未接120Ω终端电阻,导致信号反射、乱码、丢包严重。
多设备波特率、时序参数不统一,总线通信失败。
忘记配置过滤器或过滤器屏蔽全部ID,接收不到数据。
单帧发送数据超过8字节,触发传输错误。
总线干扰严重导致报错、离线,未开启自动恢复。
混淆标准帧与扩展帧ID,数据收发不匹配。
3、工程最佳实践
调试阶段使用回环模式,快速验证代码逻辑。
正式工程开启自动重发、自动总线离线恢复。
统一使用500Kbps标准波特率,设备兼容性最强。
采用中断方式接收,实时响应总线数据。
超长数据自定义分包协议,规避8字节单帧限制。
增加总线错误检测与重连机制,提升工业稳定性。
4、一句话总结
CAN是差分异步多主现场总线,依靠CAN_H/CAN_L差分传输实现强抗干扰,通过ID优先级硬件仲裁避免总线冲突,自带错误容错与自动重发机制,支持多设备远距离组网,是车载与工业控制的核心通信总线。
七、全篇总结
CAN 是嵌入式工业与车载领域的核心总线,区别于普通板级通信总线,具备高抗干扰、多主组网、硬件容错、远距离传输的核心优势。
掌握 CAN 时序原理、仲裁机制、过滤器配置、CubeMX工程配置、中断收发实战代码,即可独立完成工业组网、车载设备、机器人多机通信项目开发,是嵌入式高薪进阶的必备核心技能。