当前位置: 首页 > news >正文

STM32学习笔记:深入浅出解析CAN总线

一、引言:为什么工程师必须掌握CAN总线?

在完成SPI教程后,许多读者问:“STM32还有哪些工业级通信协议值得学习?” 答案无疑是CAN总线。作为汽车电子神经脉络工业控制骨干网络,CAN总线具有:

  • 多主仲裁机制:无中心节点冲突自动解决
  • 抗干扰能力:差分信号(CANH/CANL)可承受±36V共模电压
  • 错误检测率99.9%:CRC校验+ACK应答+帧格式检查
  • 传输距离:40米@1Mbps,10公里@5Kbps

据2023年汽车电子报告,单辆燃油车平均搭载120个CAN节点,电动车高达200+节点

二、CAN协议核心机制解析

2.1 物理层:工业环境的生存之道

// 典型CAN收发器电路(TJA1050)_______
CAN_TX --| TXD  |         120Ω|      |----- CAN_H -----||----> 总线| TJA  |                 ||
MCU     | 1050 |----- CAN_L -----||
CAN_RX --| RXD  |         120Ω|______|

关键参数

  • 显性电平:CANH=3.5V, CANL=1.5V (差分2V)
  • 隐性电平:CANH=CANL=2.5V (差分0V)
  • 终端电阻必须放置总线两端(阻抗匹配防反射)

2.2 数据帧:高效传输的秘密

# CAN 2.0B扩展帧结构(29位ID)
| SOF | ID[28:18] | SRR | IDE | ID[17:0] | RTR | r0 | DLC | Data[0-8] | CRC | DEL | ACK | EOF |

核心字段

  • 仲裁场:29位ID(优先级数值越小越高)
  • 控制场:DLC=0~8(数据长度码)
  • 数据场:最大64位(CAN FD可达64字节)

2.3 非破坏性仲裁机制

NodeA 总线 NodeB 发送ID=0x101(显性) 发送ID=0x102(隐性) 检测到显性位,退出仲裁 赢得仲裁,继续发送 NodeA 总线 NodeB

三、STM32 bxCAN外设深度剖析

3.1 邮箱系统:高效数据管理

typedef struct {__IO uint32_t TIR;  // 标识符+请求类型__IO uint32_t TDTR; // 数据长度+时间戳__IO uint32_t TDLR; // 数据低4字节__IO uint32_t TDHR; // 数据高4字节
} CAN_TxMailBox_TypeDef; // 发送邮箱寄存器// 接收FIFO结构
typedef struct {__IO uint32_t RIR;  __IO uint32_t RDTR;__IO uint32_t RDLR;__IO uint32_t RDHR;
} CAN_FIFOMailBox_TypeDef;

3.2 过滤器配置:精准数据接收

32位掩码模式配置示例

// 接收ID范围:0x100 ~ 0x10F
uint32_t FilterId = 0x100 << 21;      // 标准ID左移21位
uint32_t FilterMask = 0x7F0 << 21;    // 高7位必须匹配CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterIdHigh = FilterId >> 16;
sFilterConfig.FilterIdLow = FilterId & 0xFFFF;
sFilterConfig.FilterMaskIdHigh = FilterMask >> 16;
sFilterConfig.FilterMaskIdLow = FilterMask & 0xFFFF;
sFilterConfig.FilterFIFOAssignment = CAN_FILTER_FIFO0;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);

四、硬件实战:双机通信系统搭建

4.1 材料清单

器件型号数量
STM32开发板STM32F407VET62
CAN收发器TJA10502
终端电阻120Ω 1%精度2
双绞线AWG22屏蔽线1米

4.2 接线图

[STM32A]          [总线]          [STM32B]CAN_TX--->TXD       |               |CAN_RX<---RXD       |               ||           |               |+--CAN_H----+---------------+|           |+--CAN_L----+---------------+|           |               |GND----------GND------------GND

注意:终端电阻仅加在总线两端的收发器上!

五、CubeMX配置详解

5.1 位时序计算(500Kbps示例)

APB1时钟 = 42MHz
预分频器 = 6
时间量子tq = 6 / 42MHz = 142.86ns位时间 = 14tq (推荐配置)Sync_Seg = 1tqProp_Seg = 2tqPhase_Seg1 = 6tqPhase_Seg2 = 5tq
采样点 = (1+2+6)/1478.6% (符合汽车标准)

六、HAL库代码实现

6.1 CAN初始化

CAN_HandleTypeDef hcan;void CAN_Init(void) {hcan.Instance = CAN1;hcan.Init.Prescaler = 6;hcan.Init.Mode = CAN_MODE_NORMAL;hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan.Init.TimeSeg1 = CAN_BS1_6TQ;hcan.Init.TimeSeg2 = CAN_BS2_5TQ;hcan.Init.TimeTriggeredMode = DISABLE;hcan.Init.AutoBusOff = DISABLE;hcan.Init.AutoWakeUp = DISABLE;hcan.Init.AutoRetransmission = ENABLE; // 自动重传hcan.Init.ReceiveFifoLocked = DISABLE;hcan.Init.TransmitFifoPriority = DISABLE;HAL_CAN_Init(&hcan);// 启动CANHAL_CAN_Start(&hcan);
}

6.2 数据发送函数

#define TX_ID_STD  0x101  // 标准帧ID
#define TX_ID_EXT  0x1800A001  // 扩展帧IDvoid CAN_SendMessage(uint8_t* data, uint8_t len, uint32_t id, uint32_t ide) {CAN_TxHeaderTypeDef TxHeader;uint32_t TxMailbox;if(ide == CAN_ID_STD) {TxHeader.StdId = id;TxHeader.IDE = CAN_ID_STD;} else {TxHeader.ExtId = id;TxHeader.IDE = CAN_ID_EXT;}TxHeader.RTR = CAN_RTR_DATA;TxHeader.DLC = len;TxHeader.TransmitGlobalTime = DISABLE;// 发送到邮箱(超时100ms)HAL_CAN_AddTxMessage(&hcan, &TxHeader, data, &TxMailbox);
}

6.3 中断接收(FIFO0)

// 中断回调函数
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) {CAN_RxHeaderTypeDef RxHeader;uint8_t RxData[8];HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &RxHeader, RxData);// 打印接收数据printf("ID: 0x%lX, DLC: %d, Data: ", (RxHeader.IDE == CAN_ID_STD) ? RxHeader.StdId : RxHeader.ExtId,RxHeader.DLC);for(int i=0; i<RxHeader.DLC; i++)printf("%02X ", RxData[i]);printf("\n");
}

七、双机通信实验

7.1 测试场景设计

测试用例发送节点A预期接收节点B
标准帧测试ID=0x101, Data=0xAA应正确接收并打印
扩展帧测试ID=0x1800A001需配置扩展ID过滤器
波特率容错测试临时改为480Kbps应出现错误帧

7.2 抗干扰压力测试

// 在总线上注入噪声(实验室方法)
1. 使用函数发生器在CANH-GND间注入100KHz正弦波
2. 幅值从0.5V逐步增加到2.5V
3. 监控错误计数器:HAL_CAN_GetError(&hcan, CAN_ERROR_CNT_REG);

八、高级调试技巧

8.1 使用CAN分析仪诊断

# 使用candump工具监听(Linux环境)
$ candump can0 -t a -x can0  101   [1]  55       # 标准帧ID=0x101, 数据0x55can0  1800A001 [8]  A1 B2 C3 D4 E5 F6  # 扩展帧can0  ERROR   [0]   // 错误帧

8.2 常见故障排查表

现象可能原因解决方案
完全无通信终端电阻缺失总线两端加120Ω电阻
能发不能收过滤器配置错误检查ID掩码设置
通信随机失败波特率容差不足调整BS1/BS2优化采样点
错误帧持续出现节点硬件故障逐个断开节点定位

九、工程化建议

9.1 提升通信可靠性

// 错误处理增强代码
void CAN_ErrorCallback(CAN_HandleTypeDef *hcan) {uint32_t esr = hcan->Instance->ESR;if(esr & CAN_ESR_BOFF) {// 总线关闭状态,需软件恢复HAL_CAN_ResetErrorState(hcan);}if(esr & CAN_ESR_EPVF) {// 错误被动状态,建议重启通信HAL_CAN_Stop(hcan);CAN_Init();}
}

9.2 CANopen协议集成准备

// COB-ID分配示例
#define NMT_ID     0x000   // 网络管理帧
#define PDO1_TX_ID 0x181   // 过程数据对象
#define SDO_RX_ID  0x601   // 服务数据对象

十、附录:关键资源

  1. 官方文档

    • ISO11898-1:2015 CAN协议标准
    • STM32F4xx参考手册
  2. 工具链

    • PCAN-View:官方CAN分析软件
    • BusMaster:开源CAN总线工具
http://www.lqws.cn/news/450217.html

相关文章:

  • 【生活点滴】车辆过户、新车挂牌
  • 基于物联网的智能衣柜系统设计
  • 变幻莫测:CoreData 中 Transformable 类型面面俱到(五)
  • 探秘阿里云云数据库Tair:性能、特性与应用全景解析
  • 基于大模型的三叉神经痛预测及治疗方案研究报告
  • [持续集成]
  • 腾讯云COS“私有桶”下,App如何安全获得音频调用流程
  • 效果成本双突破!快手提出端到端生成式推荐系统OneRec!
  • CSS知识补充 --- 控制继承
  • C++网络编程入门学习(五)-- CMake 学习笔记
  • 51单片机重要知识点1
  • git更改远端文件名称以及删除指定文件夹
  • 【Mini-F5265-OB开发板试用测评】3、MDS 可编程 IP 互联模块
  • npm下载离线依赖包
  • 算法-每日一题(DAY11)每日温度
  • CDGP|2025年传统工厂数据治理:智能制造升级的新引擎
  • ESP32-HTML-08
  • .Net Framework 4/C# 进程和线程的使用
  • .NET 4.7中使用NLog记录日志到数据库表
  • 基于PyQt5和PaddleSpeech的中文语音识别系统设计与实现(Python)
  • 数字媒体专业核心课程体系以“艺术创意+数字科技+产业应用”三维融合
  • VSCode1.101.1Win多语言语言编辑器便携版安装教程
  • Can‘t resolve ‘react/jsx-runtime‘ in xxx
  • Vue框架深度解析:从Vue2到Vue3的技术演进与实践指南
  • day43-硬件学习之ARM基础知识
  • uniapp 微信小程序在线引入字体图标
  • 数据集-目标检测系列- 餐具叉子 数据集 fork >> DataBall
  • LibCpr: Windows环境下实现一个C++版本的Http客户端
  • Spring Cloud 服务调用详解:Ribbon 负载均衡与 Feign 声明式接口调用
  • 【MATLAB代码】制导方法介绍与例程——追踪法,适用于二维平面,目标是移动的|附完整源代码