最近在学习无刷电机的FOC控制硬件平台是STM32F103C8T6MT6701磁编码器SPI接口三相全桥驱动双ADC注入组采样电流上位机用VOFA看波形。程序架构参考了一个开源例程ADC中断里执行FOC核心算法Clarke、Park、PID、SVPWM主循环只做printf和LED闪烁。按照例程移植完之后遇到了两个问题在这里记录一下排查过程。问题一串口发不出数据现象程序烧录后LED正常闪烁说明主循环在跑。但VOFA接收区没有任何数据。试了printf和直接调用HAL_UART_Transmit都收不到。先检查了软件层面fputc函数已重定向到USART2Keil里Use MicroLIB已勾选波特率115200COM口选的COM3硬件TX/RX没接反GND也共地了这些看起来都没问题。然后我把while(1)里改成只发一句最裸的测试HAL_UART_Transmit(huart2, (uint8_t*)HELLO\r\n, 7, 100);HAL_Delay(500);结果还是收不到。我做了什么测试把商家提供的能正常运行的例程和自己的工程做了逐文件对比usart.c里的MX_USART2_UART_Init函数——配置完全一样main.c里的SystemClock_Config——看起来也一样但仔细看SystemClock_Config的最后一行PeriphClkInit.AdcClockSelection RCC_ADCPCLK2_DIV2例程里是RCC_ADCPCLK2_DIV6。打开CubeMX的Clock Configuration看了一下ADC预分频选的是/2ADC时钟显示36MHz而且是红色的查到的资料翻STM32F103的数据手册ADC时钟的最大值是14MHz。36MHz超了2.5倍还多。根因ADC时钟超频导致外设时序紊乱USART2的发送被干扰了。解决在CubeMX里把ADC Prescaler从/2改成/6ADC时钟变成12MHz。重新生成代码编译烧录串口立刻正常了。小结CubeMX里红色的配置项不能忽略它是在提示你配置不合法。ADC超频这种问题表面上看和串口无关但实际上会影响整个芯片的外设时序。问题二程序卡死电机发现象串口通了之后把电流模式加进while(1)结果程序卡在这行之后motor_control_context.type control_type_torque;后面的printf不打印了。同时电机开始发烫——PWM还在输出但FOC中断似乎没有更新占空比。我做了什么测试在case control_type_torque:前后加printfcase control_type_torque:printf(T-start\r\n);lib_torque_control(motor_control_context.torque_norm_d, motor_control_context.torque_norm_q);printf(T-end\r\n);break;结果T-start打印了T-end没打印。说明卡在lib_torque_control里。继续往里加void lib_torque_control(float torque_norm_d, float torque_norm_q){printf(L1\r\n);float d torque_d_loop(torque_norm_d);printf(L2\r\n);float q torque_q_loop(torque_norm_q);printf(L3\r\n);foc_forward(d, q, rotor_logic_angle);printf(L4\r\n);}结果打印了L1、L2、L3L4没打印。说明卡在foc_forward。再往里void 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函数里。查到的资料打开foc.c发现里面有一个weak版本的set_pwm_dutyvoid 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里也有一个同名的set_pwm_duty是真正写寄存器的版本。我查了一下__attribute__((weak))的机制它表示这是一个“弱符号”如果链接时发现别处有强符号普通函数就用强符号。如果没有才用这个弱符号。按理说我的main.c里有强符号链接器应该用main.c的版本。但实际上链接器选了foc.c里的weak版本导致程序卡在while(1)。关于weak我的理解作者在foc.c里放一个weak版本的set_pwm_duty我理解是为了解耦foc.c只负责FOC的数学计算不应该关心底层硬件是哪个芯片、哪个定时器。它只需要知道调用set_pwm_duty就能输出PWM就够了。所以foc.c里放一个weak版本的占位函数如果你的工程里有实现就用你的如果没有实现就执行这个占位函数。占位函数写成while(1);是故意的如果忘了实现底层驱动程序会卡死在这里让你立刻发现。** 如果占位函数是空的程序会静默地不输出PWM电机不转但你不知道是哪里出了问题更难查。这个设计思路是对的但在我这里翻车了——链接器选了weak版本而不是强符号。我查了一些资料可能和链接顺序、编译器的weak符号处理有关。删掉foc.c里的weak函数定义只保留一行声明void set_pwm_duty(float d_u, float d_v, float d_w);这样链接器只能去main.c里找实现没有选择余地。重新编译烧录程序不再卡死。小结weak符号的机制虽然灵活但调试时容易让人抓狂——链接器选错版本时不会报错运行时才暴露问题。如果是我自己写代码我会在foc.c里只放声明不放定义让链接器在编译期就报未定义符号第一时间暴露问题。总结这两个问题花了我不少时间记录几点心得1. CubeMX里红色的配置项必须处理。ADC时钟超频这种问题表面看和串口无关实际上会影响整个系统2. 调试时按信号链逐层隔离。从主循环→中断→算法函数→底层驱动一层层加printf定位比瞎猜有效得多。3. weak符号有它的设计意图但调试时要小心。链接器的行为依赖于工具链跨编译器可能不一致。更安全的做法是只声明不定义。后续会继续记录PID调参和VOFA在线整定的过程。
企业数字化 ERP 产品动态
相关推荐
3个坑让超级卖霸白学?源码解析揭秘避坑指南 3个坑让超级卖霸白学?源码解析揭秘避坑指南 官方文档那几万字,谁看谁头疼。 想搞懂超级卖霸,光看理论全是虚的。 真正的门道,全藏在源码解析的底层逻辑里。 我是干了十年后端的老张,见过太多人卡在配置和性能上。… · 2026/9/23 10:12:01
PaddleNLP 中的 ERNIE-GEN 预训练模型:权重一览与源码级架构解析 PaddleNLP 中的 ERNIE-GEN 预训练模型:权重一览与源码级架构解析 【免费下载链接】PaddleNLP Easy-to-use and powerful LLM and SLM library with awesome model zoo. 项目地址: https://gitcode.com/gh_mirrors/pa/PaddleNLP
ERNIE-GEN 是面向序列到序列&a… · 2026/9/23 10:11:48
20分钟掌握增强版模组安装:ASI加载器与冲突排查实战 1. 拆解“增强版模组”安装这件事:为什么20分钟足够,以及你需要提前想清楚什么“20分钟教会你安装增强版模组”这个标题,乍一看像是那种快餐式教程,但真正动手装过模组的人都知道,时间从来不是花在“点下一步”上&… · 2026/9/23 12:11:54
图解js数组操作:告别复制粘贴报错,5分钟吃透核心逻辑 图解js数组操作:告别复制粘贴报错,5分钟吃透核心逻辑 你有没有遇到过这种绝望时刻?从网上复制了一段看似完美的js数组操作代码,粘贴进项目里,结果控制台直接报红,或者返回的结果完全不是预期那样。你盯着屏幕,试图在几十行代码里找出哪一行出了问… · 2026/9/23 12:11:54
用友U8入库调整单实操指南:从业务逻辑到月末结账避坑 1. 入库调整单到底解决什么问题?先搞懂它存在的意义存货核算这个模块,平时财务和仓库都不太爱碰,但一到月末结账、成本计算的时候,它就成了所有人绕不开的坎。用友U8里的入库调整单,就是存货核算里一个容易被人忽略、但… · 2026/9/23 12:11:54
基于YOLOV5的水域游泳者危险检测:从数据集处理到部署避坑 简介:本资源为基于YOLOv5的水域中游泳者危险检测识别系统完整项目包,面向计算机视觉方向的高校学生、期末大作业或毕业设计开发者,以及需要水域安全监控方案的工程人员。项目已获导师指导并通过,取得96分高分,代码完整… · 2026/9/23 12:11:54
WSL2 + Webman + Swoole 开发环境搭建实录(上):环境搭建 WSL2 Webman Swoole 开发环境搭建实录(上):环境搭建这是一套三篇系列实录,记录我从零开始在 WSL2 里搭起 PHP 8.3 Swoole Webman 开发环境的全过程。不是教程,是实操记录——包括踩过的坑、绕过的路、以及那些“早… · 2026/9/23 12:11:41
转换视频格式源码深度剖析 3秒修复视频格式转换报错的速查手册 复制来的视频格式转换代码,一跑就报 OSError: [Errno 1] Operation not permitted ?别急着甩锅给环境,90%的情况是你没搞懂底层调用链。很多开发者把 FFmpeg… · 2026/9/23 12:11:35
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29