ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

STM32F103+CAN总线无刷电机驱动方案详解与调试经验

STM32F103+CAN总线无刷电机驱动方案详解与调试经验 简介面向电机控制与嵌入式CAN总线学习者这份基于STM32F103的无刷电机CAN命令控制项目完整演示了通过CAN总线远程设定无刷电机转速、方向并读取运行状态的实现思路。压缩包共202个文件约577KB以C语言源码.c/.h、Keil工程配置.uvprojx/.uvoptx、编译产物.hex/.axf及调试辅助文件.map/.lst等为主便于直接打开工程对照学习CAN配置与电机控制逻辑。资源重点涵盖CAN报文帧结构与标识符、数据长度代码、滤波器及波特率配置以及STM32F103内置CAN控制器的收发编程电机控制部分介绍霍尔传感器位置检测、PWM三相逆变驱动、六步换相与FOC磁场定向控制等策略。源码采用模块化设计电机控制、CAN收发、中断处理相互分离并附带开发者学习笔记和排错记录能帮助初学者避开常见配置坑点。已有657人学习下载适合具备一定C语言与单片机基础、希望深入掌握BLDC与CAN通信联调的开发者。 做电机控制的人绕不开“单片机 通信 电机”这个铁三角。我在做智能车底盘和云台项目时第一版驱动方案用的就是 STM32F103 通过 CAN 总线命令控制无刷电机。当时选这个组合的初衷很简单F103 成本低、生态资料多CAN 总线抗干扰能力强、支持多机挂载无刷电机效率高、寿命长。三者搭在一起正好覆盖了低速大扭矩、多电机联动这类典型场景。这篇博文就把我这套方案从硬件选型、CAN 配置、驱动逻辑到调试踩坑完整梳理一遍适合正在学 32 单片机 CAN 通信、或者刚接触无刷电机驱动的朋友参考。1. 整体设计思路为什么是 F103 CAN 无刷电机1.1 需求拆解与方案选型先把需求说清楚。我要做的是一个机器人底盘四个轮子需要独立调速同时要求主控板能远程下发指令实时读取电机转速和故障状态。这样的需求下方案选型有几个硬性条件第一单片机要有多路 PWM 输出和 ADC 采样能力第二通信总线要能在现场强电磁干扰环境下稳定工作第三电机本体要有足够的过载能力和控制精度。STM32F103 系列在这个需求下几乎是水到渠成的选择。它内置 bxCAN 控制器支持标准帧和扩展帧通信速率最高可以到 1Mbps定时器资源丰富高级定时器 TIM1/TIM8 可以输出带死区控制的互补 PWM正好用来驱动三相全桥逆变电路ADC 采样率也够用配合单电阻或双电阻电流采样方案可以实现最基本的方波控制和简单的电流保护。更重要的是F103 的学习成本很低江科大那套笔记已经把外设配置讲得很细了照着写基本不会跑偏。1.2 为什么不用串口、不用 PWM 直控很多初学者会问控制电机用串口或者直接 GPIO 输出 PWM 不就行了吗为什么非要上一套 CAN 总线我实际对比过才体会到其中的差别。串口是一对一通信主控板要同时控制四个电机就得接四根串口线布线复杂不说差分抗干扰能力也弱在电机启停瞬间的电磁噪声干扰下偶发乱码。PWM 直控就更原始了它只能表达一个占空比转速、方向、使能、故障反馈这些信息都得额外用 IO 口逐位传递代码写起来像拼积木扩展性极差。CAN 总线用的是差分信号CANH 和 CANL 两根线绞在一起传输共模干扰被差分接收器天然抑制掉实测在电机全速启停的工况下总线上几乎没有误码。而且 CAN 是真正的多主机总线任何节点都可以主动发报文配合报文 ID 优先级仲裁机制控制命令可以做到毫秒级响应。我在这套系统里选的是 500kbps 波特率实测总线利用率不到 20%余量很充足。1.3 控制架构与命令流设计整个系统的控制链路是这样的上位机或者遥控器接收机通过 CAN 总线把命令帧发给 F103 电机驱动板F103 解析 ID 和数据场后根据命令切换电机使能状态、调整 PWM 占空比、改变换相逻辑同时驱动板定期把电机转速、母线电流、故障标志通过另一组 ID 回传给上位机。我设计的报文协议很简单标准帧、11 位 ID数据场 8 字节ID 0x301电机使能控制Byte0 0 失能 / 1 使能ID 0x302速度给定Byte0-1 目标转速RPM小端模式Byte2 方向0 正转 / 1 反转ID 0x303电流限制Byte0-1 最大允许电流单位 0.1AID 0x381状态回传Byte0-1 当前转速Byte2 母线电流Byte3 故障码这样的设计看起来简单但在实际调试中非常管用。每个 ID 对应一种明确的功能过滤器的配置也清晰哪个节点发哪个 ID、哪个节点收哪个 ID一眼就能看出来。2. CAN 通信配置的核心细节2.1 STM32F103 的 bxCAN 外设初始化F103 的 bxCAN 外设挂载在 APB1 总线上系统时钟 72MHz 时APB1 最高 36MHz。CAN 外设需要一个 1MHz 左右的时基通过分频和位时间段的配置组合得到 500kbps 波特率。我常用的配置是预分频器 Prescaler 4BS1 9BS2 8这样波特率 36MHz / (4 × (1 9 8)) 500kbps。初始化步骤看起来多但每个都有它的必要。GPIO 要配置为 AF 推挽复用模式PA11 是 CAN_RXPA12 是 CAN_TX忘记配置复用功能是“回环正常但标准模式发不出”的头号原因。CAN 初始化要设置时间触发通信模式、自动总线释放管理ABOM、自动唤醒AWUM这些标志位这些寄存器位在标准外设库里都有现成的宏定义直接对号入座就行。void CAN_Init_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; CAN_InitTypeDef CAN_InitStructure; CAN_FilterInitTypeDef CAN_FilterInitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE); GPIO_InitStructure.GPIO_Pin GPIO_Pin_11 | GPIO_Pin_12; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); CAN_DeInit(CAN1); CAN_StructInit(CAN_InitStructure); CAN_InitStructure.CAN_TTCM DISABLE; CAN_InitStructure.CAN_ABOM ENABLE; CAN_InitStructure.CAN_AWUM ENABLE; CAN_InitStructure.CAN_NART DISABLE; CAN_InitStructure.CAN_RFLM DISABLE; CAN_InitStructure.CAN_TXFP DISABLE; CAN_InitStructure.CAN_Mode CAN_Mode_Normal; CAN_InitStructure.CAN_SJW CAN_SJW_1tq; CAN_InitStructure.CAN_BS1 CAN_BS1_9tq; CAN_InitStructure.CAN_BS2 CAN_BS2_8tq; CAN_InitStructure.CAN_Prescaler 4; CAN_Init(CAN1, CAN_InitStructure); }2.2 过滤器配置ACCCode 与 ACCMask 到底怎么理解CAN 过滤器是新手最容易卡壳的地方。网上关于“ACCCode 和 ACCMask”的提问铺天盖地但很多教程只给了配置代码没讲清楚里面的逻辑。我用一个类比来解释把过滤器想象成小区门禁ACCCode 是要匹配的“房号列表”ACCMask 是“匹配精度”。Mask 位为 0 表示这一位不需要关心任何值都能通过Mask 位为 1 表示这一位必须和 Code 里的值一致。比如我要只接收 ID 0x301 的报文标准帧 11 位 ID 全部参与过滤那 Code 0x301Mask 0x7FF意思是每一位都必须匹配其他 ID 全部丢弃。如果我想接收 0x300 到 0x30F 这 16 个 ID只需要把 Mask 的低 4 位设为 0让 ID 的低 4 位可以自由变化即可。F103 的 bxCAN 有 14 个过滤器组每个都可以配置为掩码模式或列表模式。掩码模式适合按 ID 范围过滤列表模式适合精确匹配几个固定 ID。我在这套电机驱动板上的配置是过滤器组 0 工作在掩码模式屏蔽除本节点接收 ID 之外的所有报文这样中断服务函数里就不用再做二次判断减小 CPU 开销。CAN_FilterInitStructure.CAN_FilterNumber 0; CAN_FilterInitStructure.CAN_FilterMode CAN_FilterMode_IdMask; CAN_FilterInitStructure.CAN_FilterScale CAN_FilterScale_32bit; CAN_FilterInitStructure.CAN_FilterIdHigh (0x301 5) 16; CAN_FilterInitStructure.CAN_FilterIdLow (0x301 5) | CAN_ID_STD; CAN_FilterInitStructure.CAN_FilterMaskIdHigh (0x7FF 5) 16; CAN_FilterInitStructure.CAN_FilterMaskIdLow (0x7FF 5) | CAN_ID_STD; CAN_FilterInitStructure.CAN_FilterFIFOAssignment CAN_FIFO0; CAN_FilterInitStructure.CAN_FilterActivation ENABLE; CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);2.3 回环模式与标准模式的本质差异很多人把“回环测试通过”当成 CAN 通信调试完成的标志这是我在项目里见过最多的误判。回环模式下CAN 控制器的发送数据在芯片内部直接返回给接收邮箱根本不会经过 TX/RX 引脚也不需要外部收发器参与。所以回环测试能通过的只能说明 CAN 内核的时序配置没问题并不能证明外部电路和总线接得对。标准模式Normal下数据要先经过 TJA1050 这类 CAN 收发器转换成差分信号送上总线。收发器的 TXD 引脚接 F103 的 PA12RXD 接 PA11如果这两根线接反或者收发器的 STB/RS 引脚电平不对导致芯片进入待机或静音模式报文就永远发不出去。我排查过一例“回环正常、标准模式静默”的故障最后发现是收发器的 S 引脚悬空TJA1050 默认进入静默模式数据根本没上总线。还有一个很容易忽略的点CAN 总线两端要接 120 欧姆终端电阻。这个电阻不是随便选的它用来匹配总线特性阻抗防止信号在总线末端反射。只有一台设备单独调试时如果总线上没有终端电阻波形上升沿和下降沿会有明显的振铃严重时直接导致采样错误。我用示波器测过有终端电阻时CANH 和 CANL 之间的差分电压在显性位约为 2V隐性位接近 0V波形干净利落没有终端电阻时方波边缘全是毛刺波特率越高越明显。3. 无刷电机的驱动原理与实现细节3.1 方波控制与 FOC 控制怎么选无刷电机驱动的主流方案有两种方波控制六步换相和 FOC 矢量控制。F103 这颗芯片如果跑 FOC也不是不行只是电流环采样、Clarke/Park 变换加上 PID 调节会占掉大量 CPU 时间而且对 ADC 采样同步要求很高对新手来说调试门槛比较陡。我在这套底盘项目里最终选了方波控制原因是低速大扭矩场景对方波控制的扭矩波动并不敏感而且霍尔传感器方案线路简单、逻辑清晰一个定时器中断就能完成换相。方波控制的本质是根据转子位置依次导通三相桥臂中的两相产生旋转磁场拖动转子转动。每 60 度电角度换相一次一个电周期换相六次所以叫六步换相。使用带霍尔传感器的无刷电机时霍尔信号 H1、H2、H3 组合出六个状态正好对应六组换相表。3.2 霍尔换相逻辑表的建立换相表是最容易出错的地方因为不同厂家的电机霍尔安装角度可能不同直接套用网上的表经常出现电机抖动、反转、噪音大的问题。我的做法是先把霍尔信号接入 F103 的输入捕获引脚手动缓慢转动电机轴用串口打印出 H1、H2、H3 的电平变化顺序再根据这个实际顺序推导换相表。下面这张表是常见的 120° 安装霍尔换相表A/B/C 三相高电平表示上桥臂导通低电平表示下桥臂导通1 表示 PWM 输出霍尔状态 (H3 H2 H1)转子电角度A相B相C相1010°10PWM10060°1PWM0110120°PWM10010180°01PWM011240°0PWM1001300°PWM01实际项目中PWM 通常只加在某一相上用来调速另外两相按表导通到电源或地。换相动作放在霍尔信号变化的边沿中断里处理这样电机低速时换相频率低高速时换相频率自然升高逻辑上不需要额外的速度估算。3.3 电流采样方案电阻采样与 ADC 读取电流采样是电机控制里容易忽略、实际却非常重要的部分。没有电流采样就不知道电机是否堵转也无法实现限流保护。最常用的低成本方案是低端电阻采样在三相全桥下桥臂 MOSFET 的源极和地之间串联一个毫欧级采样电阻电机电流流过时产生一个微弱电压经过运放放大后送入 F103 的 ADC。采样电阻的阻值选择要经过计算。典型的小功率无刷电机额定电流 3A采样电阻取 0.05 欧姆满载时压降只有 0.15V需要放大才能有效利用 ADC 的量程。我用的放大倍数是 20 倍运放输出范围设计在 0~3.3V对应电流范围 0~3.3A留出一点过载余量。如果采样电阻选太大功耗和发热会明显上升选太小小电流时信噪比太差低速轻载工况下电流读不准。这个平衡需要在具体项目里多测试几组才能找到合适的点。ADC 采样时机也很关键。PWM 开关瞬间采样电阻上的电压会有严重的开关噪声这时候采到的值完全不可信。我的做法是让 ADC 触发信号和 PWM 中心对齐在 PWM 计数器的中心点触发采样避开上下桥臂开关切换的瞬间。实测这样采到的电流波形毛刺少很多配合简单的滑动平均滤波基本上就能得到平滑的电流值用于堵转保护。4. 调试实录CAN 通信与电机驱动的常见问题4.1 CAN 波形怎么判断通信质量调试 CAN 通信时示波器是最好用的工具。把探头接到 CANH 和 CANL 两根线上用差分方式观察波形第一眼看的是差分电压幅值。标准的显性位差分电压约 2V隐性位约 0V如果幅值明显偏低优先检查收发器供电电压和终端电阻。第二眼看的是波形边缘上升沿和下降沿如果出现振铃说明阻抗不匹配如果边沿变得很缓波特率可能配高了总线电容太大拉不上去。还有一种情况是波形看着正常但通信偶发失败这时候要看波特率的位时序。发送节点和接收节点的采样点位置不一致在总线较长或干扰较强时会时不时采到错误的位电平。F103 配置 BS19、BS28 时采样点在位时间的 83.3% 附近这是比较通用的配置。如果两台设备通信的采样点偏差过大可以适当调整 BS1 和 BS2 的分配尽量让采样点对齐在 75%~85% 之间。4.2 “回环正常、标准模式发不出”的排查清单这个问题在搜索热词里被反复提到我把它单独列成一个排查表。先检查软件再检查硬件按顺序来能省很多时间。排查项检查内容解决方式GPIO 复用配置PA11/PA12 是否设为 AF 推挽重新配置 GPIO_Mode_AF_PP模式寄存器CAN 初始化是否误设为回环模式改为 CAN_Mode_Normal收发器 STB 引脚TJA1050 S 引脚是否拉低接地或接 MCU GPIO 控制TXD/RXD 接线收发器与 MCU 引脚是否交叉对应确认 TXD 接 PA12RXD 接 PA11终端电阻总线两端是否有 120Ω 电阻按总线拓扑补接波特率一致性两端位时序参数是否一致计算并统一波特率过滤器配置接收端过滤是否把发送 ID 屏蔽检查掩码和标识符4.3 电机启停瞬间的电流纹波处理实际运行中有一个现象值得单独说一下无刷电机换相瞬间母线电流会出现很明显的纹波尖峰。原因也好理解换相时绕组电感中的电流不能突变续流路径切换到另一相时会产生较大的电流脉冲。这个问题在方波控制下尤其明显因为 PWM 只斩波其中一相换相瞬间另外两相的电流状态变化剧烈。处理办法是在母线输入端加电容组我常用的是 470uF 电解电容并联 0.1uF 陶瓷电容。电解电容提供低频储能陶瓷电容滤高频噪声两者配合能把母线电压波动控制在可接受范围内。电流采样如果放在母线侧采到的波形会有周期性尖峰软件上可以在每个 PWM 周期的同一时刻采样避开尖峰区间或者用中值滤波把异常点剔除掉。4.4 电机启动失败与霍尔信号错误新的硬件第一次上电时电机不转或者启动即抖动八九不离十是霍尔换相表对不上。我踩过这个坑直接抄了网上一个同型号电机的换相表结果电机反转时正常正转时剧烈抖动。最后用逐步调试法给电机通一个固定方向的电流手动转动电机轴观察霍尔状态变化重新建立映射关系才解决。霍尔信号的另一个典型问题是电平漂移。霍尔传感器是开漏输出需要外部上拉电阻如果上拉电阻没接或者阻值太大高速转动时霍尔信号上升沿会变缓状态切换延迟增大导致换相落后于实际转子位置电机高速时效率下降、发热严重。建议用 4.7kΩ~10kΩ 的上拉电阻同时用示波器确认三个霍尔信号的边沿是否陡峭。5. 经验总结与一点后续扩展这套基于 STM32F103 的 CAN 总线无刷电机控制系统我从最初的模块选型到最终的联调完成前后大概用了一周时间。整个过程最大的体会是CAN 通信调试要善用示波器和错误计数器不要靠猜无刷电机的换相逻辑一定要根据实际硬件去验证不要盲目抄表。现在我的新项目里已经把过滤器的配置、换相表、电流采样时间点这些关键参数都写在设计文档里换一个电机型号时只需要改表就能快速适配。最后再分享一个实用的小技巧F103 的 bxCAN 外设有硬件错误计数器调试时周期读取 CAN_GetECR 的值可以发现很多偶发性故障。正常情况下错误计数应该稳定在 0如果发现数值缓慢增长但通信还没中断说明总线上存在间歇性干扰或者位时序余量不足提前处理能避免后续运行中突然通信中断的严重问题。这套方案后续还可以往 FOC 方向扩展F103 跑双电阻 FOC 也不是不行但那就是另一个工程量级的故事了。本文还有配套的精品资源点击获取
返回列表