ARTICLE DETAIL

资讯详情

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

STC8H1K28驱动三相无刷电机:51内核实现霍尔与无感换相

STC8H1K28驱动三相无刷电机:51内核实现霍尔与无感换相 简介针对STC 51单片机以STC8H1K28为例驱动三相无刷电机的完整工程资料面向单片机与电机控制爱好者可帮助解决从脉宽调制调速、换相逻辑到驱动电路设计的常见难点。压缩包共17个文件以C语言源码、十六进制固件、Keil工程配置、调试辅助文件为主附带一份三相无刷电机驱动电路PDF整体仅145KB结构紧凑。目前已有2129人学习查看。资料内包含无感电位器调速与带霍尔传感器电位器调速捕捉中断换相两套独立实例分别演示六步换相法和反电动势检测的工作方式便于对照两种控制策略的异同结合电路原理图与可烧录的固件可在学习脉宽调制定时器配置、电压换相时序的同时直接移植到自己的开发板中验证。对于希望入门无刷电机驱动或深入研究STC高性能51系列电机控制的读者是轻量而完整的参考素材。1. STC8H1K28 驱动三相无刷电机51 内核为什么还能打拿到这套资料的时候我第一反应是都什么年代了还有人用 51 内核折腾 BLDC但翻完motor_Opt.c和motor_Uv2工程之后我改变了看法。STC8H1K28 这颗芯片虽然挂着 51 的名头但主频跑到 24MHz 以上、内置 15 路 PWM、还带模拟比较器和 ADC做六步换相的无感驱动绰绰有余。资料里同时给了两套完整工程——带霍尔传感器的捕捉中断换相方案和无感反电动势过零检测方案都是电位器调速hex 和 OBJ 文件齐全烧进去就能转。这套东西适合三类人刚接触 BLDC 控制想看懂换相逻辑的学生用 STM32 做惯了 FOC 想回头梳理六步换相底层原理的工程师以及需要低成本量产电调、预算卡死在几块钱 MCU 上的产品开发者。51 的价值从来不在于算力而在于外设直接、中断响应可控、代码裸奔也能把时序拿捏住。2. 带霍尔方案捕捉中断换相的工程实现2.1 霍尔传感器与六步换相的基本逻辑三相无刷电机的定子绕组是三相对称的转子是永磁体。要让它持续转下去必须让定子磁场始终领先转子磁场一个角度这就是换相的本质。带霍尔传感器的电机在内部装了三个开关型霍尔元件间隔 60° 电角度安装转子转一圈会输出 6 种组合状态每种状态对应一个确定的转子位置区间。六步换相法的核心就是每一时刻只有两相绕组通电第三相悬空每 60° 电角度换一次相一个电气周期内完成 6 次换相。霍尔状态和换相之间的关系用一张表就能列清楚霍尔状态 (H1,H2,H3)通电相序假设 A 相悬空为例转子电角度区间001C / B-0° ~ 60°101A / C-60° ~ 120°100A / B-120° ~ 180°110B / A-180° ~ 240°010B / C-240° ~ 300°011C / A-300° ~ 360°2.2 捕捉中断换相的代码结构资料里那套STC8H1K28-带霍尔传感器-电位器调速-捕捉中断换相.c换相的核心不是轮询霍尔电平而是利用 STC8H1K28 的外部中断或 PCA 捕获功能在霍尔信号跳变沿触发中断中断里读取完整霍尔状态再决定下一步怎么换。这种方式的好处是电机转速变化时霍尔信号频率跟着变但中断总能及时响应不会因为主循环里的其他任务而错过换相时机。// 霍尔状态到换相输出映射表共 8 种含非法状态 // 每项对应A相上桥, A相下桥, B相上桥, B相下桥, C相上桥, C相下桥 // 1 表示打开0 表示关闭 unsigned char code hall_table[8][6] { {0, 0, 0, 0, 0, 0}, // 000 非法或停止态 {0, 0, 0, 0, 1, 1}, // 001: C B- {0, 0, 1, 1, 0, 0}, // 010: B C- {1, 1, 0, 0, 0, 0}, // 011: C A-此项依实际接线修正 {1, 1, 0, 0, 0, 0}, // 100: A B- {0, 0, 1, 1, 0, 0}, // 101: A C- {0, 0, 0, 0, 1, 1}, // 110: B A- {0, 0, 0, 0, 0, 0}, // 111 非法或停止态 }; // 霍尔跳变沿触发的中断服务函数 void hall_isr() interrupt 0 { unsigned char hall_state; hall_state P3 0x07; // 读取霍尔引脚P3.0, P3.1, P3.2 if (hall_state 0 || hall_state 7) { motor_stop(); // 非法状态立即关断 return; } commutation_output(hall_table[hall_state]); }这是一个典型的查表法换相。hall_table里存的不是 PWM 占空比而是 6 个功率管的导通组合。实际工程里还有一点需要处理霍尔信号跳变和换相输出之间存在机械角度偏差也就是所谓的超前换相角。资料里直接用中断立刻换相对低速起步够用但高速时建议在表里预置提前量或者用定时器做延迟换相。2.3 驱动电路与上下桥控制策略驱动电路部分资料里的三相无刷电机驱动电路.pdf画的是经典的半桥驱动结构STC8H1K28 的 PWM 输出引脚接栅极驱动芯片常见的是 IR2101 或 EG2131再驱动 6 个 N-MOSFET 组成三相全桥。注意上桥要自举电容供电下桥直接由单片机 IO 或驱动芯片输出驱动。调速方面资料用电位器分压后进 ADC然后改 PWM 占空比。有一种常见的控制策略是上桥 PWM 斩波下桥恒通。也就是换相表里被点亮的两个桥臂里一个桥臂走 PWM 信号另一个桥臂一直导通。这种做法的好处是开关损耗集中在一对管子上控制逻辑简单。缺点也明显——6 个管子发热不均长时间满负荷跑要留意上桥管温升。void set_pwm_duty(unsigned int duty) { // STC8H1K28 的 PWM 寄存器是 16 位周期值由 PWMA_ARR 决定 // duty 范围 0 ~ PWMA_ARR对应占空比 0% ~ 100% PWMA_CCR1 duty; // 通道1A相上桥 PWMA_CCR2 duty; // 通道2B相上桥 PWMA_CCR3 duty; // 通道3C相上桥 }这里只更新了上桥的占空比下桥在换相表里已经固定为常通或常闭。电位器的 ADC 采样值需要先做线性映射把 0~4095 的采样范围映射到 PWM 死区之外的占空比区间。我一般会限制最小占空比在 5% 左右避免低速时三相电流太小转子在换相间隙里丢失位置尤其是带霍尔方案里霍尔安装误差会造成低速转矩脉动。3. 无感方案反电动势过零检测与三段式启动3.1 为什么去掉霍尔还能知道转子位置无感方案去掉霍尔传感器之后转子的位置信息只能从电机的电气量里提取。最常用的手段是检测反电动势Back EMF。原理不复杂转子永磁体转动时会在定子绕组里感应出电压这个电压的幅值和转子角速度成正比。六步换相中有一相是悬空的这一相在导通区间内会暴露出反电动势的波形反电动势穿过零点的时刻恰好对应转子的一个关键位置点。STC8H1K28 内部有一个模拟比较器正端接三相绕组的星形中点电压或虚拟中点负端接悬空相的分压信号。当悬空相的反电动势电压穿过中点时比较器翻转捕获这个翻转沿就知道该换相了。资料里的STC8H1K28-无感-电位器调速.c就是用比较器中断做换相触发的代码结构上比霍尔方案多了一层启动流程。// 比较器中断服务函数检测到反电动势过零事件 void cmp_isr() interrupt 21 { // 清中断标志 CMPCR1 ~0x80; // 记录本次过零时间戳 last_zero_crossing_time timer_get_count(); // 延时 30° 电角度后执行换相 // 常见做法开启一个定时器延时 上次换相周期的一半近似 30° set_timer_delay(last_commutation_period / 2); } // 定时器延时时长到了之后执行真正换相 void timer_delay_isr() interrupt 3 { commutation_output(next_com_table_entry()); last_commutation_period last_zero_crossing_time - prev_zero_crossing_time; prev_zero_crossing_time last_zero_crossing_time; }比较器只负责捕捉过零点换相还要再等 30° 电角度这一步必须用定时器做延迟不能直接在比较器中断里换相。注释里写得很清楚延时时间取上次换相周期的一半这是一种近似估算实际中因为反电动势波形不是理想正弦30° 延时会有几度误差但工程上完全可用。3.2 三段式启动定位、强制换相、闭环切入无感电机最头疼的是启动。静止状态下反电动势为零比较器根本等不到过零事件必须靠外力把转子先转起来。资料里的无感方案采用的是一般项目里最常见的三段式第一段定位。随便选一个换相状态给电机通电定子磁场会把转子拉到某个固定位置这个过程叫预定位。通常拉 200~500ms电流不宜太大否则转子会过冲。第二段强制换相。按固定的时间间隔依次切换换相状态不管转子是否真的到位强迫电机转起来。时间间隔从大往小缩比如从 30ms 起步逐渐减到 5ms相当于开环升频。第三段闭环切入。当强制换相频率达到某个阈值反电动势已经明显可测此时把控制权交给比较器中断检测到过零就换相系统进入闭环。void motor_start() { // 第一步预定位 300ms commutation_output(align_state); delay_ms(300); // 第二步强制换相启动换相间隔逐步缩短 for (comm_period 30; comm_period 5; comm_period - 2) { commutation_output(next_com_table_entry()); delay_ms(comm_period); } // 第三步启动比较器中断切换到反电动势闭环 CMPCR1 | 0x80; // 使能比较器中断 motor_state CLOSED_LOOP; }注意强制换相阶段的换相时间表没有反馈校正如果电机负载很重转子跟不上换相速度就会失步。一个常见的补救措施是把启动电流上限设高一点或者在强制换相阶段用更大的占空比提供额外的加速力矩。资料里电位器旋到最大时启动会顺畅很多就是这个原因——电压裕量补偿了开环阶段的盲目性。3.3 比较器配置与分压网络参数无感方案的硬件电路上三相绕组输出要经过一个无源分压网络接到比较器输入。原因很简单单片机的比较器输入范围是 GND 到 VCC而绕组节点处的电压在 PWM 开关过程中会大幅波动直接接入会把比较器打坏。分压电阻取 10kΩ/3.3kΩ 的分压比比较稳妥把最高 24V 或 36V 的母线电压折算到 5V 以内。STC8H1K28 比较器有两个输入引脚正端建议接三个 10kΩ 电阻组成的虚拟中点网络负端接三相反电动势检测选通网络。软件里还要设置比较器的滤波时间因为在 PWM 开关边沿会有尖峰干扰可能造成比较器误翻转。资料里虽然没有写滤波参数但一般做法是把比较器的数字滤波设为 1μs 左右滤掉功率管开关瞬间的毛刺保留真实过零点。4. 电位器调速与 STC8H1K28 关键外设配置4.1 ADC 采样与占空比映射电位器调速的本质是电压模拟量到数字量再到物理输出的一个链路电位器分压 → ADC 采样 → 计算占空比 → PWM 输出 → 改变电机端电压 → 转速变化。STC8H1K28 的 ADC 是 12 位的参考电压默认是 VCC电位器接在 VCC 和 GND 之间中间抽头进 ADC 引脚。unsigned int adc_read(unsigned char channel) { ADC_CONTR 0x80 | (channel 4); // 启动 ADC选择通道 ADC_CONTR | 0x40; // 开始转换 while (!(ADC_CONTR 0x20)); // 等待 ADC 完成标志 ADC_CONTR ~0x20; // 清标志 return (ADC_RES 8) | ADC_RESL; // 12 位结果合成 } void speed_loop() { unsigned int adc_val adc_read(1); // 读电位器所在 ADC 通道 unsigned int duty; // 映射到 5%~95% 占空比区间避免死区和满占空比直通 duty 50 (adc_val * 900) / 4095; set_pwm_duty(duty); }这段代码有一个容易被忽略的点把 0~4095 的 ADC 值映射到 50~950 的 PWM 计数值用的是先乘法后除法避免浮点运算。adc_val * 900在 4095 量级下最大乘积是 368 万刚好落在 STC8H1K28 的 16 位乘法范围内吗不是368 万已经超过 16 位了所以这里要用无符号整型的自动类型提升编译器会扩展为 32 位计算。如果代码里用了unsigned int强制压缩结果会溢出转速会毫无规律地跳变这是实际调车时最容易踩的坑。4.2 PWM 输出模式与互补死区设置STC8H1K28 的高级 PWM 模块PWMA支持互补输出和死区插入这是驱动半桥电路的必要功能。即使你只是在换相表里开某些管子每个管子也不能直接给纯逻辑电平因为 MOSFET 的栅极充电需要时间上下桥切换瞬间可能出现直通短路。死区时间通常设在 300ns~1μs 之间具体取多少取决于管子型号和栅极驱动电阻。// PWMA 初始化边沿对齐模式设置死区 500ns // // PWMA_PSCRH / PWMA_PSCRL预分频 // PWMA_ARRH / PWMA_ARRL自动重装载值决定 PWM 周期 void pwm_init() { PWMA_PSCRH 0; PWMA_PSCRL 23; // 24MHz / 24 1MHz 计数频率 PWMA_ARRH 0x03; // 周期 1000 计数值 PWMA_ARRL 0xE8; // 即 1000实际 PWM 频率 1kHz PWMA_CCMR1 | 0x60; // PWM 模式 1 PWMA_CCER1 | 0x03; // 使能输出 使能互补输出 PWMA_CCER1 ~0x02; // 极性配置高电平有效 PWMA_DTR 0x1E; // 死区寄存器30 / 1MHz 500ns PWMA_BKR | 0x80; // 使能主输出 }这里的预分频 24、计数周期 1000对应 PWM 频率是 1kHz。BLDC 驱动一般建议开关频率在 16kHz~20kHz超出人耳可听范围避免噪音。把预分频改成 1不分频ARR 改成 1200就是 24MHz / 1200 20kHz死区时间要用周期除以频率换算1 / 24MHz × 30 1.25μs适合大多数图腾柱驱动的 MOSFET。4.3 Keil 工程结构与 STC-ISP 烧录要点资料里的工程文件是用 Keil uVision 建的.Uv2是老版本 Keil 的工程文件直接用 Keil 5 打开会提示版本转换正常选是就行。工程里同时存在STC8H1K28-无感-电位器调速.c和STC8H1K28-带霍尔传感器-电位器调速-捕捉中断换相.c两个源码文件但同一时间只能有一个参与编译。我打开motor.Uv2看了一下资料默认的是无感方案如果你要看霍尔方案把无感的那个源文件右键从工程中移除再把霍尔方案的加进来即可。烧录用的是 STC-ISP接好串口后选对芯片型号 STC8H1K28加载 hex 文件点下载。STC 系列需要在冷启动状态下才能进入 ISP 模式所以操作顺序是先点“下载/编程”再给板子重新上电。STC-ISP 还提供硬件选项配置比如内部晶振频率、复位脚功能等。注意不要勾选“下次下载时重新上电”以外的选项否则可能把 PWM 引脚占用成普通 IO导致电机不动。5. 换相时序与启动失败的关键调试点无感方案调试时建议先接示波器探头夹在悬空相和虚拟中点之间看反电动势波形是否完整穿过零位。如果波形有严重削顶或噪声先检查分压网络和比较器滤波。启动失败大概率出现在强制换相阶段频率收太快转子还没跟上就进入闭环看到的现象是电机抖两下就停了。最直接的排查方法是把强制换相间隔的最小值从 5ms 改成 10ms损失一点启动时间换回的是稳定切入闭环的把握。霍尔方案调试相对省事但要注意三个霍尔信号不能直接测量换相是否正确。我一般先只接电机的两根线用手慢慢转动转子一边转一边看六个霍尔状态是否正确循环到了 1~6。状态缺失或者顺序错乱先调整霍尔线序而不是改代码——大多数时候是表里的顺序和实际接线不匹配。霍尔信号线上串一个 1kΩ 电阻、对地并 100nF 电容能有效消除长线引入的高频干扰。电位器调速范围如果线性度差大概率是 ADC 参考电压不稳。STC8H1K28 的 VREF 脚接了滤波电容之后ADC 采样稳定性会明显改善。另外一个细节是PWM 占空比突变不能太大每次调速循环最多调 1%~2%直接跳变会造成电流冲击表现在电机上是“咯噔”一下的顿挫严重点会让过流保护动作。电机高速运行时注意听声音换相噪声如果突然变大说明换相时序偏移了——带霍尔方案要查霍尔安装角度无感方案要检查过零延时是否恒定。整套资料里最有价值的不是某一个代码文件而是两套方案能放在同一个芯片上对比同样的硬件平台带霍尔和无感在启动策略、中断响应、调试工具上的差异比单纯看书理解得透彻得多。本文还有配套的精品资源点击获取
返回列表