资讯动态

STM32有感BLDC驱动:六步换相与换相表实战解析

发布时间:2026/9/16 14:04:42 来源:尧图企业网站定制
简介基于STM32的有感直流无刷电机驱动控制程序采用C语言编写面向自动化、电子信息等专业的学生及嵌入式开发工程师。资源适用于毕业设计、课程设计及工程入门实践代码结构清晰注释完整可直接编译运行也可在现有基础上修改扩展实现不同控制逻辑满足学习与科研的双重需求。压缩包共733个文件以C源码和头文件为主包含433个c文件、226个h文件另含42个汇编文件、链接脚本与ARM数学库以及STM32F3系列HAL驱动代码包体约24.11MB目录组织规范便于按模块检索学习。已有680人学习下载。内容涵盖电机驱动核心控制模块、外设初始化配置、底层驱动接口及配套数学库可加速控制算法开发与验证适合需要深入理解直流无刷电机控制原理、撰写课程报告或进行项目二次开发的读者参考借鉴。1. 从一份 zip C 源码说起有感 BLDC 驱动程序里最有价值的为什么是换相表基于STM32有感直流无刷电机驱动控制程序C源码.zip看起来只是一份普通工程压缩包但对做电机控制的嵌入式工程师来说这个标题已经划出了三重边界主控是 STM32电机是有感直流无刷电机BLDC交付物是 C 源码。比起无感方案里复杂的反电动势检测启动霍尔传感器让转子位置在零速下就可读六步换相因此变成一张查表换相表、PWM 互补输出和闭环参数才是这个源码真正的核心。这篇按换相逻辑、驱动实现、闭环调参、移植排错四个层次把一个可复现的 STM32 有感 BLDC 驱动控制程序讲透适合正在做风机、水泵、机器人底盘或毕业设计的开发者。2. 有感 BLDC 六步换相霍尔真值表与换相表到底怎么查2.1 三个霍尔信号为何能确定六个换相状态有感 BLDC 的转子是永磁体定子三相绕组按星形或三角形连接。沿定子圆周相隔 120° 放置的三个开关型霍尔传感器只能输出 0 或 1因此每转过 60° 电角度霍尔信号组合跳变一次一圈下来正好得到 6 个互不相同的状态。控制器拿到这 6 个状态后就可以确定当前转子磁极位置并据此决定给哪两相绕组通电。注意这里的“120° 布局”指的是三个霍尔传感器在空间上相隔 120° 电角度实际电机还有 60° 布局的产品。两种布局在霍尔真值表上表现为高低电平互补换相顺序也会整体平移。所以拿到任何一份 C 源码第一步不是看 PID而是确认头文件里的换相表跟电机手册里的霍尔电气角定义一致。2.2 霍尔真值表与六步导通顺序以常见的 120° 霍尔布局为例三个霍尔信号 H3、H2、H1 的组合与六步导通顺序如下状态序号H3H2H1应导通相A 表示电流从 A 相流入1101A B-2100A C-3110B C-4010B A-5011C A-6001C B-这张表看起来只是六个组合但它是整个驱动控制程序的“坐标系”。如果霍尔信号编码顺序和表对不上轻则电机抖动重则启动瞬间电流直逼限流值。实际电机驱动中同一相的上桥和下桥不能同时导通所以每个状态必须恰好有一相上桥导通、一相下桥导通另一相悬空。2.3 在 C 源码中把换相表做成数组把霍尔状态编码成 3 bit 数值后六步换相就可以退化成一次查表。我在自己的工程里常用这样的结构typedef struct { uint8_t high_side; /* 上桥恒通的相: 0A, 1B, 2C */ uint8_t low_side; /* 下桥 PWM 斩波的相: 0A, 1B, 2C */ } commutation_step_t; /* 按 2.2 的真值表顺序排列使用前先用 get_commutation_index() 映射 */ const commutation_step_t bldc_table[6] { {0, 1}, /* 101: A 上桥通B 下桥斩波 */ {0, 2}, /* 100: A 上桥通C 下桥斩波 */ {1, 2}, /* 110: B 上桥通C 下桥斩波 */ {1, 0}, /* 010: B 上桥通A 下桥斩波 */ {2, 0}, /* 011: C 上桥通A 下桥斩波 */ {2, 1}, /* 001: C 上桥通B 下桥斩波 */ }; /* 霍尔状态 0b1010x5, 0b1000x4, 0b1100x6, * 0b0100x2, 0b0110x3, 0b0010x1 * 000 与 111 是非法状态返回 0xFF */ uint8_t get_commutation_index(uint8_t hall_code) { switch (hall_code) { case 0x5: return 0; case 0x4: return 1; case 0x6: return 2; case 0x2: return 3; case 0x3: return 4; case 0x1: return 5; default: return 0xFF; } }代码里把霍尔信号拼接成hall_code的动作一般在捕获中断里完成拼接顺序必须是(H3 2) | (H2 1) | H1否则查表结果会乱。bldc_table里的high_side和low_side并不是最终的 GPIO 电平而是给驱动层用的开关索引上位程序拿到这两个值后再去操作定时器的输出比较通道。这个查表设计的优点是换相时间固定不会因为 switch 分支过多产生纳秒级抖动。缺点是要保证bldc_table的顺序和get_commutation_index()一一对应工程里最常出现的 bug 也是这两处被分别维护后对不上。建议把两个数组放在同一个.c文件中并加上static const限定。2.4 换相顺序错误时会看到什么换相表装反不是完全不能转下面的现象可以帮你定位电机像卡住一样来回抖动声音发闷多半是霍尔编码或换相顺序不对此时电流非常大要立即断电能转但电流明显偏大空载运行几十秒电机烫手换相角偏前或偏后常见于 60° 霍尔布局用了 120° 真值表猛推一下才能启动松开又停可能是其中一个霍尔信号接反或者非法状态处理为直接关断导致换相缺相。提示初次上电验证换相表时母线电压不要超过 24V并且串联一个 60W 白炽灯做限流。灯泡亮说明电流大换相顺序很可能反了。3. 基于 STM32 的驱动控制程序PWM 互补输出与霍尔捕获3.1 用定时器输出 6 路互补 PWM 与死区STM32 驱动三相桥最常见的是用高级定时器 TIM1/TIM8 输出三相互补 PWM。CH1/CH2/CH3 输出上桥CH1N/CH2N/CH3N 输出下桥互补通道之间由硬件自动插入死区。以 STM32 标准外设库为例核心配置如下TIM_TimeBaseInitTypeDef tim_base; TIM_OCInitTypeDef tim_oc; TIM_BDTRInitTypeDef bdtr; tim_base.TIM_Prescaler 71; /* 72MHz / 72 1MHz */ tim_base.TIM_Period 999; /* PWM 频率 1MHz / 1000 1kHz调试用 */ TIM_TimeBaseInit(TIM1, tim_base); tim_oc.TIM_OCMode TIM_OCMode_PWM1; tim_oc.TIM_Pulse 500; /* 初始占空比 50% */ tim_oc.TIM_OutputState TIM_OutputState_Enable; tim_oc.TIM_OutputNState TIM_OutputNState_Enable; tim_oc.TIM_OCPolarity TIM_OCPolarity_High; tim_oc.TIM_OCNPolarity TIM_OCNPolarity_High; tim_oc.TIM_OCIdleState TIM_OCIdleState_Reset; tim_oc.TIM_OCNIdleState TIM_OCNIdleState_Reset; TIM_OC1Init(TIM1, tim_oc); /* CH2、CH3 的初始化完全一样只是通道号不同 */ bdtr.TIM_DeadTime 0x50; /* 死区约 1us由 BDTR 寄存器配置 */ TIM_BDTRConfig(TIM1, bdtr); TIM_CtrlPWMOutputs(TIM1, ENABLE); /* 高级定时器主输出使能 */这段代码里有三个参数最值得注意预分频、周期、死区。预分频和周期共同决定 PWM 频率1kHz 只是验证用的低频率真正跑电机一般取 15kHz 到 30kHz需要把TIM_Period改到 50 以内并按实际主频重算。TIM_DeadTime的单位由芯片的 BDTR 寄存器位定义决定标准库传入的数是定时器时钟 tick 数具体微秒值必须查参考手册。TIM_CtrlPWMOutputs是高级定时器特有的主输出使能忘记调用会导致端口量不到任何 PWM 波形这是 STM32 电机驱动源码里最常见的“无声失败”。注意STM32 的 IO 驱动能力不足以直接驱动功率 MOS必须经过栅极驱动芯片。选型时要看驱动芯片的传播延时和上下桥死区时间的匹配一般控制板取 0.5~2us 死区。3.2 霍尔信号接入与转速计算霍尔信号三个引脚建议接在同一个定时器的输入捕获通道上常见做法是用 TIM2 的 CH1/CH2/CH3 做输入捕获并且上升沿和下降沿都捕获。相邻两次边沿之间的时间就是一次换相周期。void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_CC1) ! RESET) { static uint32_t last 0; uint32_t now TIM_GetCapture1(TIM2); uint32_t diff now - last; /* uint32 回绕特性天然支持溢出 */ last now; if (diff 0) { /* 转速(转/分) 10,000,000 / (极对数 * diff_us) * 每个机械周期有 6 个极对数 * 换相沿 */ speed_rpm 10000000UL / (POLE_PAIRS * diff); } TIM_ClearITPendingBit(TIM2, TIM_IT_CC1); } }计算转速时要注意三点diff是微秒还是计数器 tick取决于定时器时钟频率相邻换相沿是 60° 电角度所以机械周期里有6 * POLE_PAIRS个换相沿now - last用无符号减法可以自动处理计数器回绕不用手动判断谁大谁小。低速时diff很大转速分辨率会变差一般只在 200RPM 以上使用这个公式更低转速用 M/T 法测量更准。3.3 换相状态机在中断里查表还是主循环查表换相的核心动作是“读霍尔状态 - 查表 - 改 CCR”。这个动作不能放在主循环里一直执行因为主循环会被各种耗时任务打断。常见做法是把查表放在霍尔捕获中断里但只更新开关状态另一路速度环中断根据计算结果修改TIM_Pulse。void Hall_Task_From_ISR(void) { uint8_t hall_code get_hall_code(); uint8_t idx get_commutation_index(hall_code); if (idx 0xFF) { return; /* 非法状态保持当前输出 */ } bldc_table_apply(idx); /* 内部修改定时器 CCR 与通道开关 */ }bldc_table_apply()要做的事不是直接操作 GPIO而是通过定时器的输出比较寄存器把对应的通道设为常开、常关或 PWM 斩波。工程里如果换相后电流尖峰大可以在查表后加一个固定换相延时这个延时补偿电机反电动势相位通常 1us 到 20us只能在示波器上看相电流波形后微调。3.4 标准外设库还是 HAL 库老一点的有感 BLDC 源码多基于标准外设库原因是电机控制需要精确控制寄存器时序标准库代码短、执行路径明确、中断延迟可控。HAL 库在定时器和 DMA 配置上封装更完整适合工程规模大、需要快速移植的场景。两种库都可以跑关键是换相中断和 PWM 更新不能走 HAL 的阻塞式延时。如果你拿到的是标准库工程强行把驱动文件塞进 HAL 工程会有一堆结构体重名最稳妥的是保留原驱动层只换启动和时钟配置。4. 有感 BLDC 速度闭环电流采样、PI 参数与 C 源码限幅4.1 为什么需要速度闭环而不是固定占空比固定占空比驱动 BLDC 时负载一变转速就往下掉母线电压波动也会直接反映到转速上。所以在风机、水泵这类需要稳速的场景里C 源码必然有一个速度环。常见结构是速度外环、电流内环速度环输出电流给定电流环输出 PWM 占空比。对大多数开发板和模组方案电流环不是必须的但至少要在速度环里加输出限幅否则堵转时占空比会冲到 100%。4.2 电流采样与 PWM 同步电流采样最常见的做法是在下桥臂串联采样电阻流过电流时在电阻上产生压降经运放放大后送 STM32 的 ADC。由于 PWM 周期内电流是断续的采样点必须放在下桥导通的中点这时电流最稳定。/* 在 PWM 周期中点触发 ADC 采样避免开关噪声 */ ADC_ExternalTrigConvCmd(ADC1, ENABLE); ADC_ExternalTrigConvConfig(ADC1, ADC_ExternalTrigConv_T8_TRGO, ENABLE);这里的 TRGO 来自定时器的事件触发具体选择哪一路触发源由定时器的主从模式决定。如果不用硬件触发也可以让定时器更新中断里延时几十微秒再读 ADC但那样会占用中断时间载波频率高时容易丢中断。采样电阻的压降一般在 0.1V 到 0.5VSTM32 ADC 满量程是 3.3V运放增益至少要放 6 到 30 倍具体按母线最大电流计算。4.3 PI 参数表与整定顺序有感 BLDC 的常规调参顺序是先电流环后速度环因为电流环带宽高参数错误容易看出振荡速度环的采样周期远大于电流环不会互相干扰。下面是适合大多数 24V 到 48V 驱动板的初始范围环路Kp 初始范围Ki 初始范围采样周期调节现象电流环0.3 ~ 1.50.01 ~ 0.0550us ~ 100us占空比抖动母线电流噪声大速度环0.5 ~ 2.50.05 ~ 0.51ms ~ 5ms转速超调、起动回退Kp 过大会让控制量随噪声剧烈变化表现为电机啸叫和电流毛刺Ki 过大会在转速给定变化时产生明显超调。整定手法是先把 Ki 置 0只加 Kp观察稳态转速波动波动小于 5% 后再逐步加 Ki直到满载时稳态误差落在目标转速的 1% 以内。整个过程中速度环输出必须限幅在电流环允许的范围内否则堵转瞬间积分无限增长恢复时会有一次猛烈冲击。4.4 C 源码中 PI 控制器的典型实现小型 BLDC 控制程序里不需要完整 PID速度环用 PI 足够微分项会把霍尔测速的高频噪声放大反而更难调。下面是一段可以直接抄进工程的结构typedef struct { float kp; float ki; float integral_max; /* 积分限幅 */ float limit; /* 输出限幅 */ float integral; float out; } pi_ctrl_t; float pi_update(pi_ctrl_t *h, float err, float Ts) { h-integral h-ki * err * Ts; if (h-integral h-integral_max) h-integral h-integral_max; if (h-integral -h-integral_max) h-integral -h-integral_max; h-out h-kp * err h-integral; if (h-out h-limit) h-out h-limit; if (h-out -h-limit) h-out -h-limit; return h-out; }注意Ts不能写死必须把实际速度环中断周期传进去否则换主频或者改定时器分频后所有参数都要重调。integral_max常见取值是limit的一半给比例项留出调节余量。在纯粹速度闭环程序里这个函数的返回值就是 PWM 占空比在带电流环的程序里返回值作为电流环给定是不是直接赋值要看驱动层怎么分层。4.5 启动阶段与开环预定位有感 BLDC 虽然零速下能读到霍尔位置但静止时转子正好停在换相边界或非法状态附近的情况不少见。直接进入闭环可能因为换相表索引跳变导致启动反向或堵转。常见做法是先开环预定位再切闭环void startup_routine(void) { for (uint32_t duty 600; duty 3500; duty 50) { set_open_loop_duty(duty); /* 按固定换相序续流 */ delay_ms(2); if (hall_change_count 24) { /* 检测到足够换相沿认为转起来了 */ break; } } reset_pi_integral(); }开环阶段换相序固定不管霍尔信号是什么按同一方向给三相通电hall_change_count在霍尔捕获中断里自增累计 24 次说明转子已经转过至少两圈电角度。切入闭环前务必将 PI 积分清零否则开环期间累积的误差会让转速冲高。5. 把 C 源码移植到自己的 STM32 工程换相序验证与调试技巧5.1 从压缩包到可编译工程的三件事先把驱动源文件放进要使能的模块组里再处理芯片型号和时钟树。Keil5 工程如果报错找不到芯片需要安装对应系列的器件包标准外设库工程还要确认启动文件是startup_stm32f10x_hd.s还是cl.sFlash 容量不同会直接影响中断向量布局。最后对着原理图把霍尔引脚、PWM 通道号、ADC 通道号全部核对一遍避免库里的宏定义与接线不一致。5.2 用低速盘转子法验证换相表在不通母线或者限流情况下给电机某一相通一个很小的直流电流让转子转到固定位置然后手动把转子转过一个完整电周期同时用调试器读霍尔状态和换相表输出。每一步霍尔跳变都应看到驱动状态按预想顺序推进一次。如果某一跳变没有触发更新多半是输入捕获通道配置错误如果触发了但输出相号顺序不对就是换相表本身问题。5.3 用逻辑分析仪抓霍尔与 PWM 的对应关系把三个霍尔信号和某一路 PWM 同时接到逻辑分析仪上采样率设到 50MHz 以上。正常波形中霍尔跳变沿应稍早于 PWM 斩波开关动作。如果 PWM 先动、霍尔后到说明中断响应慢了或换相延时设成了负值如果 PWM 输出有毛刺检查死区时间和互补极性高速下毛刺最容易出现在上下桥切换瞬间。5.4 调试中最高频的三个报错程序能编译但下载时报No STM32 target found多半是 SWD 接线、目标板供电或复位电路问题先检查 boot0 是不是拉到了高电平再用 ST-Link Utility 读芯片 ID。电机只抖不转优先查换相表而不是 PID用前面盘转子的方法十分钟就能确认。上电瞬间烧下桥 MOS常见原因是死区过小或 PWM 输出使能先于栅极驱动供电要保证驱动芯片电压稳定后再开TIM_CtrlPWMOutputs。正式带载前建议做一次锁定转子测试母线电压降到 12V 以下让程序缓慢增加占空比并记录母线电流。这个测试能同时暴露换相表、死区、电流采样极性和 PI 限幅四类问题比直接带扇叶调参安全得多。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价