STM32 FOC调试记录

发布时间:2026/11/5 7:49:06
STM32 FOC调试记录 STM32 FOC调试记录程序卡死在set_pwm_dutyweak符号踩坑现象ADC中断正常后把电流模式代码加进 while(1)cmotor_control_context.torque_norm_d 0;motor_control_context.torque_norm_q 0.4;motor_control_context.type control_type_torque;HAL_Delay(1000);程序卡在这段代码后面后面的printf不打印了。更严重的是电机开始发烫——PWM还在输出但FOC中断不再更新占空比某一相持续通电。排查过程第一步用printf逐段定位在关键位置加printf看程序执行到哪一步cprintf(A\r\n);motor_control_context.type control_type_torque;printf(B\r\n);HAL_Delay(1000);printf(C\r\n);打印到B就停了说明卡在 HAL_Delay(1000) 里或者它后面。第二步在lib_torque_control里加printfcvoid lib_torque_control(float torque_norm_d, float torque_norm_q){printf(T1\r\n);float d torque_d_loop(torque_norm_d);printf(T2\r\n);float q torque_q_loop(torque_norm_q);printf(T3\r\n);foc_forward(d, q, rotor_logic_angle);printf(T4\r\n);}打印到T3就停了卡在 foc_forward。第三步在foc_forward里加printfcvoid foc_forward(float d, float q, float rotor_rad){printf(F1\r\n);float d_u 0, d_v 0, d_w 0;svpwm(rotor_rad, d, q, d_u, d_v, d_w);printf(F2\r\n);set_pwm_duty(d_u, d_v, d_w);printf(F3\r\n);}打印了4个F1进入函数、三个变量初始化、svpwm完成第5个F1set_pwm_duty之后没打印。卡在set_pwm_duty函数里。根因weak符号被链接器选中打开 foc.c发现里面有一个weak版本的 set_pwm_dutycvoid set_pwm_duty(float d_u, float d_v, float d_w) __attribute__((weak));void set_pwm_duty(float d_u, float d_v, float d_w){while (1);}我的 main.c 里明明有强符号版本cvoid set_pwm_duty(float d_u, float d_v, float d_w){d_u min(d_u, 0.9);d_v min(d_v, 0.9);d_w min(d_w, 0.9);__disable_irq();__HAL_TIM_SET_COMPARE(htim1, TIM_CHANNEL_1, d_u * htim1.Instance-ARR);// ...__enable_irq();}但链接器选了 foc.c 里的weak版本运行时卡在 while(1)。关于weak符号__attribute__((weak)) 是GCC/ARM编译器的弱符号机制。规则如果别处有同名的强符号链接器就用强符号如果没有才用弱符号。原作者的意图foc.c 是算法层不应该关心底层硬件所以放一个weak版本的 set_pwm_duty 作为占位如果你的工程里实现了硬件驱动就用你的如果忘了实现就执行 while(1) 死循环让你一运行就发现这个设计思路是对的但在我这翻车了。为什么链接器选错了可能的原因链接顺序问题foc.o 在 main.o 之前被链接链接器先看到weak版本就定了编译器对weak的处理有差异不同工具链行为可能不一致main.c里的强符号因为某种原因没被识别结果就是本该用“主胎”的用了“备胎”卡死在while(1)。修复方法删掉 foc.c 里的weak函数定义只保留一行声明cvoid set_pwm_duty(float d_u, float d_v, float d_w);这样链接器只能去 main.c 里找实现没有选择余地。改完后编译烧录程序不再卡死电机正常响应。声明和定义的区别写法 类型 作用void set_pwm_duty(float d_u, float d_v, float d_w); 声明 告诉编译器有这个函数具体实现去别处找void set_pwm_duty(float d_u, float d_v, float d_w) { ... } 定义 给出函数的完整实现唯一区别在末尾有分号 声明有花括号 定义。总结项目 内容现象 程序卡死电机发烫根因 链接器选了foc.c里的weak版本卡在while(1)解决 删掉weak定义只保留声明教训 weak符号调试时要小心编译期报错比运行期死循环好

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询