这个开源项目针对ST官方电机控制库5.4版本进行了深度改造,特别适合正在学习STM32电机控制的开发者。原始ST库虽然功能强大,但存在两个典型痛点:一是缺乏中文注释,二是寄存器操作逻辑不够透明。本工程通过Keil开发环境,对无感FOC控制的核心代码进行了逐行注解,同时保留了完整的寄存器配置记录。
我在工业伺服系统开发中多次使用ST电机库,发现新手最常卡在三个地方:PWM定时器配置、ADC采样同步和角度观测器实现。这个项目正好解决了这些痛点,特别是把AD采样触发机制和定时器联动关系用中文图示标注了出来,比官方手册直白得多。
工程采用标准STM32CubeMX生成的项目结构,但重点改造了以下关键目录:
code复制/Drivers
/MCSDK_v5.4.0 # 修改后的电机库
/MotorControl
/FOC_utils # 磁场定向控制核心
/PWM_CurrFdbk # 电流反馈处理
/State_Observer # 状态观测器
/User
/main.c # 带详细启动流程注释
/motor_parameters.h # 电机参数配置指南
特别值得注意的是mc_interface.c文件,作者用彩色注释区分了不同功能块:
ST库通常用HAL库函数封装底层寄存器操作,这给调试带来困难。本工程采用混合访问策略:
c复制// 在TIM1初始化函数中添加的寄存器说明
// CR1寄存器配置说明 [地址:0x40010000]
// bit7-5: 时钟分频(001表示不分频)
// bit4: 计数方向(0向上计数)
TIM1->CR1 = 0x0080; // 实际配置值
// 对比HAL库等效写法
HAL_TIM_Base_Init(&htim1);
这种写法既保留了库函数的可移植性,又让开发者能看到实际寄存器操作。我在调试无刷电机时就曾遇到PWM死区时间配置不生效的问题,通过这种透明化配置很快定位到是BDTR寄存器的LOCK位没设置。
原始库的电机启动分为三段式:
工程中对MC_StartMotor()函数添加了状态机注释,特别标明了各阶段切换条件:
c复制/* 状态切换阈值说明 */
#define OPEN_LOOP_TO_CLOSED_THRESHOLD 0.2f // 当估算反电动势达到额定值20%时切闭环
#define ALIGNMENT_DURATION_MS 500 // 对齐阶段持续时间
// 在状态机中添加调试钩子
if (transition_to_closed_loop) {
USER_DEBUG_LOG("切换到闭环控制"); // 通过串口输出状态
BSP_LED_On(LED_DEBUG); // 调试LED指示
}
电机控制中ADC采样时刻直接影响电流测量精度。工程里重点注释了ADC触发与PWM的配合:
c复制// 在PWM周期中心点采样可避开开关噪声
// 使用TIM1_CH4的CCR4作为ADC触发源
TIM1->CCR4 = (TIM1->ARR)/2; // ARR为自动重装载值
// ADC采样窗口计算
// 采样时间 = (ADC_SMPR + 12.5)个时钟周期
// 建议设置为开关频率的1/10以下
hadc1.Init.SamplingTime = ADC_SAMPLETIME_15CYCLES;
重要提示:在调试时发现,如果PWM频率超过20kHz,必须缩短ADC采样时间,否则会错过中心点窗口。具体计算参考工程中的《AD采样时序设计指南》文档。
工程使用Keil MDK-ARM V5,需要特别注意:
USE_FULL_LL_DRIVER 使用底层驱动ARM_MATH_CM4 启用DSP库ini复制LR_IROM1 0x08000000 0x00100000 { ; Flash配置
ER_IROM1 0x08000000 0x00100000 {
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 0x00020000 { ; SRAM配置
.ANY (+RW +ZI)
}
}
SEGGER_SYSVIEW_Conf.h中配置电机控制任务IDmatlab复制% 工程提供的MATLAB辅助工具
Kp = I_rated * Ls / (T_s * Vdc); % 比例系数基础计算
Ki = Kp * Rs / Ls; % 积分系数关系
mc_faults.c中模拟过流条件现象:切换到闭环控制时出现明显抖动
排查步骤:
c复制// 在mc_observer.c中打印日志
printf("初始角度:%.2f 对齐角度:%.2f",
pObserver->EstimatedAngle,
pMotor->AlignAngle);
c复制// 默认值可能不适合大惯量负载
#define SPEED_BANDWIDTH 30.0f // 可尝试降低到15.0f
c复制// 在开环阶段注入测试电压
Vdq.v = 0.2f * Vdc_bus;
常见故障模式及对策:
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 相电流不对称 | 采样电阻偏差 | 校准ADC偏移寄存器 OFFSET_CHx |
| 高频噪声大 | PWM干扰 | 检查PCB布局,缩短采样走线 |
| 数据跳变 | 同步触发失效 | 验证TIM1->CCR4与ADC_CR2的EXTEN配置 |
工程预留了多种位置接口的扩展点:
c复制// 在mc_config.h中选择编码器类型
#define ENCODER_MODE ENCODER_ABZ
// 或 #define ENCODER_MODE ENCODER_SINCOS
// 扩展TLE5012B磁编码器示例
void TLE5012_Init(void) {
SPI_CS_LOW();
WriteReg(0x08, 0x0001); // 配置为14位模式
SPI_CS_HIGH();
}
虽然工程基于STM32F303,但移植到F4系列只需修改:
arm_math.h)我在移植到STM32G4系列时,主要工作量在ADC配置上。G4的ADC有硬件过采样功能,可以简化软件滤波:
c复制// STM32G4的ADC配置差异
hadc1.Init.OversamplingMode = ENABLE;
hadc1.Init.Oversampling.Ratio = 0x08; // 8倍过采样
这个项目最实用的其实是那些调试注释,比如在mc_loop.c里标注的:"如果Q轴电流始终震荡,先检查Vbus电压测量值是否准确,再调整观测器增益"。这种经验之谈在官方文档里根本找不到,却是调试时最关键的突破口。