3. STM32与CAN外设入门:STM32 CAN控制器原理、CubeMX配置、基础收发实验、回环测试

CAN(Controller Area Network)总线自20世纪80年代由Bosch公司提出以来,凭借其卓越的实时性、可靠性和抗干扰能力,已成为工业自动化、汽车电子、运动控制等领域的骨干通信网络。在运动控制系统中,CAN总线承担着伺服驱动器、变频器、I/O模块与主控制器之间的实时数据交换任务。STM32系列MCU内置的bxCAN(Basic Extended CAN)控制器,为开发者提供了高性能、低成本的CAN通信解决方案。本章将深入剖析STM32 CAN控制器的内部架构与工作原理,系统讲解基于STM32CubeMX的初始化配置流程,并通过基础收发实验与回环测试,帮助读者建立CAN通信的完整工程认知。

STM32 bxCAN 控制器内部架构与收发链路 STM32F103/F407 MCU CAN_TX 邮箱 CAN_RX FIFO 过滤器组 协议引擎 位时序:SYNC_SEG + TSEG1 + TSEG2 APB1 (36MHz/42MHz) CAN 收发器 TJA1050 / SN65HVD230 3.3V/5V 供电 CAN_TX (PA12) CAN_RX (PA11) 120Ω 终端电阻 (两端各一个) CAN_H CAN_L 节点 2 (另一MCU/设备) 回环模式:内部连接,无需外部节点 过滤器工作模式(32位/16位) • 屏蔽位模式:ID + 屏蔽码,匹配范围 • 列表模式:精确匹配ID • 14个过滤器组,可分配到FIFO0/FIFO1 位时序关键参数(1Mbps 示例) • 预分频:APB1=36MHz → 4分频 → 9MHz • 位时间 = 1/1Mbps = 1μs = 9个时间量子 • SYNC_SEG=1, TSEG1=5, TSEG2=3, SJW=1 图:STM32 bxCAN 内部架构、外部收发器连接及回环测试路径 关键引脚与配置速查 • CAN1_TX: PA12 (AF9) | CAN1_RX: PA11 (AF9) | CAN2_TX: PB13 | CAN2_RX: PB12 • 回环测试:LoopBack Mode = Enabled,无需外部收发器即可验证协议引擎

3.1 STM32 CAN控制器核心原理

3.1.1 bxCAN架构与功能模块

STM32家族中,F103系列搭载的是bxCAN控制器,F407系列则升级为兼容性更强的CAN2.0B控制器。两者在核心架构上保持一致,均包含协议引擎、发送邮箱、接收FIFO、过滤器组以及寄存器接口五大功能模块。协议引擎负责处理CAN帧的封装、解封装、位同步、仲裁、错误检测等底层逻辑,对开发者透明。发送侧提供3个发送邮箱(TX Mailbox),支持优先级调度,开发者只需将待发送数据写入邮箱并请求发送,硬件会自动完成帧的构建与总线仲裁。接收侧配备2个FIFO(FIFO0和FIFO1),每个FIFO可存储3个完整报文,配合14个可配置的过滤器组,实现报文的硬件级筛选,大幅减轻CPU负担。

bxCAN的位时序设计是其可靠通信的基石。每个位时间由同步段(SYNC_SEG)、传播段(PROP_SEG)和相位缓冲段(PHASE_SEG1/2)组成,通过调整预分频器(BRP)和各个段的长度,可以精确配置波特率并优化采样点位置。在运动控制网络中,通常要求采样点位于位时间的70%-80%处,以保证在长距离、高干扰环境下仍能正确采样。

功能模块资源数量核心作用关键寄存器
发送邮箱3个缓存待发送报文,支持优先级仲裁CAN_TIxR, CAN_TDTxR, CAN_TDLxR
接收FIFO2个(各3级深度)缓存接收报文,支持FIFO溢出保护CAN_RIxR, CAN_RDTxR, CAN_RDLxR
过滤器组14个(F103)/28个(F407)硬件筛选报文ID,减少无效中断CAN_FMR, CAN_FMxR, CAN_FSxR
协议引擎1个位同步、帧编解码、错误检测、仲裁CAN_BTR, CAN_ESR
中断控制TX/RX/错误/唤醒事件通知,支持中断或轮询模式CAN_IER, CAN_MSR

3.1.2 CAN帧格式与仲裁机制

CAN协议定义了标准帧(11位ID)和扩展帧(29位ID)两种格式。在运动控制场景中,标准帧因其帧头开销小、实时性高而更常用。数据帧由帧起始(SOF)、仲裁场、控制场、数据场、CRC场、ACK场和帧结束(EOF)组成。仲裁机制是CAN总线的精髓:当多个节点同时发送时,ID值越小优先级越高,通过逐位比较实现非破坏性仲裁。这意味着高优先级报文(如急停信号)可以无延迟地抢占总线,而低优先级报文自动退避重发。

运动控制中的ID分配策略:通常将紧急停止(ID=0x000)、伺服使能(ID=0x001)、速度指令(ID=0x100-0x1FF)等关键控制字分配低ID值,将状态反馈(ID=0x200+)、诊断信息(ID=0x300+)分配高ID值。这样即使总线负载较高,关键控制指令也能获得优先传输。

3.2 STM32CubeMX配置CAN外设

3.2.1 引脚分配与时钟配置

使用STM32CubeMX进行CAN配置的第一步是正确分配引脚。以STM32F103C8T6为例,CAN1的发送引脚为PA12,接收引脚为PA11,均复用为AF9功能。在CubeMX的Pinout视图中,点击PA11和PA12,选择CAN1_RX和CAN1_TX即可完成引脚复用。时钟配置方面,CAN外设挂载在APB1总线上,F103的APB1最大频率为36MHz,F407为42MHz。CAN控制器内部通过预分频器将APB1时钟分频得到CAN时钟,再进一步分频得到位时间量子。

// CubeMX 生成的 CAN 初始化代码(F103, 1Mbps)
hcan.Instance = CAN1;
hcan.Init.Prescaler = 4;        // APB1=36MHz, 4分频 → 9MHz CAN时钟
hcan.Init.Mode = CAN_MODE_NORMAL; // 正常模式(回环测试时改为 CAN_MODE_LOOPBACK)
hcan.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan.Init.TimeSeg1 = CAN_BS1_5TQ;  // 传播段+相位缓冲段1
hcan.Init.TimeSeg2 = CAN_BS2_3TQ;  // 相位缓冲段2
hcan.Init.TimeTriggeredMode = DISABLE;
hcan.Init.AutoBusOff = ENABLE;     // 自动退出BusOff状态
hcan.Init.AutoWakeUp = DISABLE;
hcan.Init.AutoRetransmission = ENABLE; // 自动重传
hcan.Init.ReceiveFifoLocked = DISABLE;
hcan.Init.TransmitFifoPriority = DISABLE;
if (HAL_CAN_Init(&hcan) != HAL_OK) { Error_Handler(); }

3.2.2 过滤器配置与中断使能

过滤器配置是CAN接收的核心。在运动控制网络中,主站通常需要接收多个从站的反馈报文,合理的过滤器设置可以只接收关心的ID,避免CPU被无关中断打扰。CubeMX中通过CAN_FilterConfTypeDef结构体配置过滤器:设置过滤器编号(FilterNumber)、工作模式(FilterMode)、过滤器位宽(FilterScale)、ID和屏蔽码(FilterIdHigh/Low, FilterMaskIdHigh/Low)以及关联的FIFO(FilterFIFOAssignment)。

// 配置过滤器0:接收所有标准帧(屏蔽码全0)
CAN_FilterTypeDef sFilterConfig;
sFilterConfig.FilterBank = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;  // 全0表示不屏蔽任何位
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;
sFilterConfig.FilterActivation = ENABLE;
HAL_CAN_ConfigFilter(&hcan, &sFilterConfig);
// 使能FIFO0消息挂起中断
HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
// 启动CAN外设
HAL_CAN_Start(&hcan);

3.3 基础收发实验与回环测试

3.3.1 回环测试原理与配置

回环测试(LoopBack Mode)是验证CAN控制器协议引擎是否正常工作的最快捷方式。在此模式下,发送邮箱的数据会直接路由到接收FIFO,无需外部收发器和总线连接。这特别适合在没有硬件环境的情况下进行软件调试。CubeMX中将CAN模式设置为CAN_MODE_LOOPBACK,同时保持波特率配置不变。回环测试可以验证:位时序配置是否正确、帧封装/解封装逻辑是否正常、过滤器是否按预期工作、中断处理流程是否完整。

回环测试的局限:回环模式不经过CAN收发器,因此无法验证物理层信号质量、总线竞争仲裁、错误处理等真实总线行为。完成回环测试后,务必在真实总线环境下进行多节点通信测试。

3.3.2 发送与接收代码实现

发送报文使用HAL_CAN_AddTxMessage函数,需要构造CAN_TxHeaderTypeDef结构体,指定ID、帧格式、数据长度等参数。接收报文在中断回调函数HAL_CAN_RxFifo0MsgPendingCallback中处理,使用HAL_CAN_GetRxMessage读取数据。以下是一个完整的收发示例:

// 发送标准帧 ID=0x123, 数据长度8字节
CAN_TxHeaderTypeDef txHeader;
uint8_t txData[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};
uint32_t txMailbox;
txHeader.StdId = 0x123;
txHeader.ExtId = 0;
txHeader.IDE = CAN_ID_STD;
txHeader.RTR = CAN_RTR_DATA;
txHeader.DLC = 8;
HAL_CAN_AddTxMessage(&hcan, &txHeader, txData, &txMailbox);

// 接收中断回调
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
    CAN_RxHeaderTypeDef rxHeader;
    uint8_t rxData[8];
    if (HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rxHeader, rxData) == HAL_OK)
    {
        // 处理接收到的报文
        if (rxHeader.StdId == 0x123)
        {
            // 运动控制指令处理逻辑
            ProcessMotionCommand(rxData);
        }
    }
}

3.3.3 实验步骤与结果验证

回环测试的实验步骤可以归纳为以下流程:

  1. 在CubeMX中配置CAN1为LoopBack模式,波特率设为1Mbps,使能FIFO0中断。
  2. 生成代码并编译下载至STM32开发板。
  3. 在主循环中周期性发送测试报文(如每100ms发送一次ID=0x123的数据帧)。
  4. 在中断回调中设置一个标志位,并在主循环中检查该标志,同时将接收到的数据通过串口打印。
  5. 观察串口输出,确认接收到的数据与发送数据完全一致。
测试项预期结果常见异常排查方法
波特率配置收发正常,无错误帧总线错误计数增加检查BRP和BS1/BS2参数
过滤器设置只接收匹配ID的报文收到无关报文或收不到目标报文检查屏蔽码和ID配置
中断触发每次接收进入回调中断不触发或频繁触发检查NVIC配置和FIFO锁定设置
数据完整性收发数据逐字节一致数据错位或丢失检查DLC设置和缓冲区大小

3.4 常见误区与工程实践要点

3.4.1 波特率计算与采样点优化

许多初学者在配置CAN波特率时,只关注最终速率而忽略采样点位置。在运动控制网络中,总线长度可能超过50米,且存在电机驱动器等强干扰源,采样点位置直接影响通信可靠性。推荐将采样点设置在75%-80%处。以1Mbps为例,若APB1=36MHz,预分频4得到9MHz CAN时钟,每个位时间9个TQ,则SYNC_SEG=1, TSEG1=5, TSEG2=3,采样点位置=(1+5)/9=66.7%,偏低。调整为TSEG1=6, TSEG2=2,采样点=(1+6)/9=77.8%,更优。

注意:CAN总线的终端电阻必须正确配置。标准CAN要求总线两端各接一个120Ω电阻,中间节点不接。缺少终端电阻会导致信号反射,表现为通信不稳定、错误帧增多。在实验室环境中,如果只有两个节点,每个节点各接一个120Ω电阻即可。

3.4.2 错误处理与BusOff恢复

CAN控制器内置强大的错误检测机制,包括位错误、填充错误、CRC错误、格式错误和ACK错误。当错误计数超过阈值时,节点会进入BusOff状态,脱离总线。在运动控制中,BusOff可能导致伺服失控,因此必须配置自动恢复功能。CubeMX中设置AutoBusOff = ENABLE,同时建议在应用层增加错误回调处理,记录错误类型和发生时间,便于故障诊断。

3.4.3 案例拆解:伺服驱动器通信调试

背景:某自动化设备使用STM32F407作为主控,通过CAN总线控制4台伺服驱动器(波特率1Mbps,标准帧)。设备上电后,主控能收到伺服状态报文,但发送速度指令时,伺服偶尔不响应。

现象分析:通过CAN分析仪抓取总线数据,发现主控发送的指令帧ID=0x201,但伺服反馈的报警代码显示"接收超时"。进一步检查发现,主控发送频率为1kHz,而伺服驱动器要求指令间隔至少1.2ms。

解决过程:1) 调整发送周期至1.5ms,问题依旧;2) 检查CAN错误寄存器,发现TEC(发送错误计数)偶尔增加;3) 使用示波器测量CAN_H和CAN_L差分信号,发现信号幅值仅1.8V(正常应为2V),且存在振铃;4) 检查硬件,发现主控板CAN收发器电源滤波电容缺失,导致瞬态压降。

改进措施:在收发器电源引脚增加100nF+10μF去耦电容,优化PCB走线,将CAN差分对远离电机驱动线。改进后,TEC归零,通信稳定。

复盘要点:CAN通信问题往往不是单一原因,需要从软件配置、硬件设计、外部干扰多维度排查。建议在开发初期就加入错误计数监控和总线分析仪,缩短问题定位时间。

3.4.4 总结与最佳实践

  • 配置顺序:先配置时钟和引脚,再配置CAN参数,最后配置过滤器和中断。启动CAN前务必确认所有参数已生效。
  • 调试技巧:利用回环模式验证软件逻辑,利用CAN分析仪验证物理层,利用错误中断捕获异常状态。
  • 代码健壮性:发送函数应检查返回值,处理邮箱满的情况;接收回调应快速处理数据,避免阻塞。
  • 网络设计:合理规划ID分配,预留扩展空间;控制总线负载率在60%以下,保证实时性。