主题 | 内容 | 教学目的/扩展视频 |
---|---|---|
CAN总线重点课程 | 电路原理,跳线设置。协议分析。驱动程序。自检模式,其他CAN总线通信。 | 会设置CAN模式,会收发数据。 |
师从洋桃电子,杜洋老师
📑文章目录
▲ 回顾上期🔍STM32 CAN总线原理与应用开发指南(上) | 零基础入门STM32第六十一步
▲ 回顾上期🔍STM32 CAN总线原理与应用开发指南(中上) | 零基础入门STM32第六十二步
▲ 回顾上期🔍STM32 CAN总线原理与应用开发指南—数据发送全解析(中下) | 零基础入门STM32第六十三步
一、CAN接收核心架构图解
1.1 数据接收全流程
1.2 FIFO邮箱结构
FIFO0邮箱结构:
+-----------------+
| 报文1(最早) | <-- 读取位置
+-----------------+
| 报文2 |
+-----------------+
| 报文3(最新) |
+-----------------+
特性:
- 3层深度缓冲
- 先进先出管理
- 溢出自动覆盖(可配置锁定)
二、过滤器机制深度解析
2.1 过滤器模式对比
模式类型 | 工作方式 | 适用场景 |
---|---|---|
标识符列表模式 | 精确匹配预设ID列表 | 固定ID通信系统 |
屏蔽模式 | 通过掩码指定需匹配的ID位 | 动态ID范围过滤 |
2.1.1 列表模式示例
// 设置过滤器0为列表模式
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdList;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x1234; // ID高位
CAN_FilterInitStructure.CAN_FilterIdLow = 0x5678; // ID低位
2.1.2 屏蔽模式示例
// 设置过滤器1为屏蔽模式
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x1FFF; // 只关注低11位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x1FFF;
2.2 过滤器优先级规则
- 32位宽 > 16位宽
- 列表模式 > 屏蔽模式
- 编号小的过滤器优先
三、关键代码逐行解析
3.1 初始化函数分析
u8 CAN1_Configuration(void){
// GPIO配置(略)
// CAN工作模式设置
CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; // 普通模式
CAN_InitStructure.CAN_SJW = tsjw; // 同步跳转宽度
CAN_InitStructure.CAN_BS1 = tbs1; // 时间段1
CAN_InitStructure.CAN_BS2 = tbs2; // 时间段2
CAN_InitStructure.CAN_Prescaler = brp; // 分频系数
// 过滤器配置(核心)
CAN_FilterInitStructure.CAN_FilterNumber = 0; // 使用过滤器0
CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask; // 屏蔽模式
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit; // 32位宽
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000; // 设置ID高位
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000; // 掩码全0(接收所有)
CAN_FilterInit(&CAN_FilterInitStructure); // 应用配置
}
3.2 接收函数解析
// 查询接收模式
u8 CAN_Receive_Msg(u8 *buf){
if(CAN_MessagePending(CAN1,CAN_FIFO0)==0) return 0; // 检查FIFO状态
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage); // 读取报文
memcpy(buf, RxMessage.Data, 8); // 拷贝数据
return RxMessage.DLC; // 返回实际数据长度
}
// 中断接收模式(部分代码)
void USB_LP_CAN1_RX0_IRQHandler(void){
CAN_Receive(CAN1,CAN_FIFO0,&RxMessage); // 中断读取
if(RxMessage.StdId == 0x12){ // ID过滤
// 处理有效数据
}
}
四、高级配置技巧
4.1 动态过滤器配置
// 动态设置过滤器ID范围
void CAN_SetFilter(uint32_t id, uint32_t mask){
CAN_FilterInitTypeDef filter;
filter.CAN_FilterNumber = 0;
filter.CAN_FilterMode = CAN_FilterMode_IdMask;
filter.CAN_FilterIdHigh = id >> 16;
filter.CAN_FilterIdLow = id & 0xFFFF;
filter.CAN_FilterMaskIdHigh = mask >> 16;
filter.CAN_FilterMaskIdLow = mask & 0xFFFF;
CAN_FilterInit(&filter);
}
4.2 多过滤器协同工作
五、CAN总线其他功能
5.1 工作模式对比
模式名称 | 功能说明 | 典型应用 |
---|---|---|
正常模式 | 标准收发模式 | 常规通信 |
环回模式 | 自发自收(本地测试) | 硬件自检 |
静默模式 | 只接收不发送 | 总线监听 |
睡眠模式 | 低功耗状态 | 电池供电设备 |
5.2 时间触发通信
// 启用时间戳功能
CAN_InitStructure.CAN_TTCM = ENABLE;
// 读取时间戳
uint16_t timestamp = RxMessage.TSR;
六、调试与优化建议
6.1 常见问题排查
现象 | 可能原因 | 解决方案 |
---|---|---|
接收不到数据 | 过滤器配置错误 | 检查ID和掩码设置 |
数据丢失 | FIFO溢出 | 提高读取频率或启用中断 |
接收错误帧 | 总线终端电阻缺失 | 添加120Ω终端电阻 |
6.2 性能优化策略
- 中断优化:使用DMA传输减少CPU占用
- 双FIFO策略:将高优先级数据路由到FIFO0
- 动态过滤:根据运行状态调整过滤器规则
- 错误统计:监控错误计数器预防故障
七、扩展应用示例
7.1 多ID接收系统
// 配置多个过滤器接收不同ID范围
CAN_FilterInitStructure.CAN_FilterNumber = 0; // 过滤器0
// 设置ID=0x100~0x1FF
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x100 << 5;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x1FF << 5;
CAN_FilterInitStructure.CAN_FilterNumber = 1; // 过滤器1
// 设置ID=0x200~0x2FF
// ...
7.2 混合模式通信
// 同时接收标准帧和扩展帧
CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x1FFFFFFF; // 允许扩展ID
通过本文的代码解析和机制说明,开发者可以深入掌握STM32的CAN接收机制。建议结合CAN分析仪实际观察报文流动,并尝试修改过滤器策略构建复杂通信网络。
本文系统解析了CAN总线接收机制,从硬件过滤到软件处理层层递进,提供了可直接复用的代码模板和调试方案。通过结构化的图示和代码注释,帮助开发者快速构建可靠的CAN通信系统。
八、相关资源
[1] 洋桃电子B站课程-STM32入门100步
[2] STM32官方文档手册
[3] STM32F103固件函数库用户手册(中文)
[4] CAN通信测试程序
[5] TJA1050 数据手册 + CAN总线协议
[6] CAN总线驱动程序分析3.pptx
💬 技术讨论(请在评论区留言~)
📌 下期预告:下一期将探讨ADC读电位器和光敏
重点课程
,欢迎持续关注!
点击查阅🔍往期【STM32专栏】文章
版权声明:本文采用[CC BY-NC-SA 4.0]协议,转载请注明来源
实测开发版:洋桃1号开发版(基于STM32F103C8T6)
更新日志:
- v1.0 初始版本(2025-03-12)