STM32F103VET6 无刷电机 FOC 控制工程(标准外设库,手写实现)
| 项目 | 配置 |
|---|---|
| 芯片 | STM32F103VET6 (HD, LQFP100) |
| 外部晶振 | HSE = 8MHz |
| 系统时钟 | SYSCLK = 72MHz (APB1=36MHz, APB2=72MHz) |
| 开发环境 | Keil v5 (ARMCC V5.06) |
| 外设库 | STM32 Standard Peripheral Library V3.5 |
| 调试器 | CMSIS-DAP |
| 驱动板 | LKS560 栅极驱动器 EVB 板 |
| 波形调试 | VOFA+ (JustFloat 协议, 115200bps) |
| 版本管理 | Git |
当前阶段:SVPWM 开环控制已实现,电机可启转运行。
三相半桥由两组高级定时器独立驱动:
| 相 | 上管(高边) | 下管(低边) |
|---|---|---|
| A相 | TIM1_CH1 → PE9 | TIM8_CH1 → PC6 |
| B相 | TIM1_CH2 → PE11 | TIM8_CH2 → PC7 |
| C相 | TIM1_CH3 → PE13 | TIM8_CH3 → PC8 |
定时器配置:
- 模式:中心对齐模式1(仅下溢产生更新中断)
- PWM 频率:20kHz
- ARR:1799(72MHz / (2 × 20kHz) - 1)
- PSC:0(72MHz 不分频)
- 启动方式:TIM_Cmd() 同时使能 TIM1 和 TIM8
- 死区方式:软件偏移 CCR(无硬件死区)
- NVIC 分组:NVIC_PriorityGroup_2
- 中断优先级:抢占1 / 子0(TIM1 与 TIM8 相同)
FOC标准库_手写/
├── Doc/
│ └── readme.txt ← 详细技术文档
├── Libraries/
│ ├── CMSIS/ ← Cortex-M3 内核 + 启动文件
│ │ ├── core_cm3.c/h
│ │ ├── stm32f10x.h
│ │ ├── system_stm32f10x.c/h
│ │ └── startup/ ← startup_stm32f10x_hd.s
│ └── FWlib/ ← STM32 标准外设库 V3.5
│ ├── inc/ ← 库头文件
│ └── src/ ← 库源文件
├── Project/
│ └── RVMDK(uv5)/
│ └── BH-STM32.uvprojx ← Keil 工程文件
├── User/
│ ├── main.c ← 主程序(SVPWM 开环测试入口)
│ ├── bsp_pwm.c/h ← PWM 驱动 (TIM1上管 + TIM8下管)
│ ├── FOC.c/h ← FOC 算法模块(浮点版)
│ ├── adc.c/h ← ADC 电流采样(开发中)
│ ├── vofa_uart.c/h ← VOFA+ JustFloat 串口波形输出
│ ├── stm32f10x_it.c/h ← 中断服务函数
│ └── stm32f10x_conf.h ← 外设库配置
├── Output/ ← Keil 编译输出
├── Listing/ ← Keil 链接输出
├── keilkill.bat ← Keil 编译中间文件清理脚本
└── README.md ← 本文件
void BSP_PWM_Init(void);
/* 上管占空比设置(duty 范围:0 ~ 1799)*/
void BSP_PWM_SetDutyHighA(uint16_t duty); // A相上管 PE9
void BSP_PWM_SetDutyHighB(uint16_t duty); // B相上管 PE11
void BSP_PWM_SetDutyHighC(uint16_t duty); // C相上管 PE13
/* 下管占空比设置(duty 范围:0 ~ 1799)*/
void BSP_PWM_SetDutyLowA(uint16_t duty); // A相下管 PC6
void BSP_PWM_SetDutyLowB(uint16_t duty); // B相下管 PC7
void BSP_PWM_SetDutyLowC(uint16_t duty); // C相下管 PC8
/* 批量更新六路 PWM */
void BSP_PWM_Set(int* PWM_SetDutyHighA, int* PWM_SetDutyLowA,
int* PWM_SetDutyHighB, int* PWM_SetDutyLowB,
int* PWM_SetDutyHighC, int* PWM_SetDutyLowC);/* Clarke 变换(三相静止 → 两相静止,等幅值)*/
void Clarke(float Ia, float Ib, float Ic, float *Ialpha, float *Ibeta);
/* Park 变换(两相静止 → 两相旋转)*/
void Park(float Ialpha, float Ibeta, float theta, float *Id, float *Iq);
/* 反 Park 变换(两相旋转 → 两相静止)*/
void InvPark(float Id, float Iq, float theta, float *Ialpha, float *Ibeta);
/* 反 Clarke 变换(两相静止 → 三相静止)*/
void InvClarke(float Ialpha, float Ibeta, float *Ia, float *Ib, float *Ic);
/* 角度制 → 弧度制转换 */
void shift(float theta_degrees, float *theta);
/* SVPWM 算法(6扇区,含过调制保护)*/
void svpwm(float Ts, float Ualpha, float Ubeta, float *Ta, float *Tb, float *Tc);FOC 算法常量(FOC.h):
| 宏定义 | 值 | 说明 |
|---|---|---|
SQRT3 |
1.73205080757f | √3 |
ONE_SQRT3 |
0.577350269f | 1/√3 |
PI |
3.14159265358979323846f | π |
_sqrt3_2 |
0.8660254037844f | √3/2 |
_1_2 |
0.5f | 1/2 |
void VOFA_Init(void); // 初始化(含串口硬件)
void VOFA_SetChannel(uint8_t ch_idx, float value); // 设置单通道值
void VOFA_SendChannels(float ch0, float ch1, // 设置6通道并发送
float ch2, float ch3,
float ch4, float ch5);
void VOFA_Send(void); // 发送当前帧main.c 主循环中,角度逐次递增 1°,执行开环 SVPWM 控制:
theta_degrees从 0° 递增(步长 1°),≥ 360° 时归零循环shift()— 角度制 → 弧度制转换InvPark(D=0, Q=9.0, theta)— 反 Park 变换,得到 Uα/Uβsvpwm(Ts, Uα, Uβ)— 计算三相占空比 A/B/C- 映射到 CCR:
A_num = (int)(A × PWM_DUTY_MAX / Ts),范围 0~1799 BSP_PWM_Set()— 批量更新六路 PWM 占空比VOFA_SendChannels()— 串口输出波形数据
- TIM1 上管 + TIM8 下管 PWM 驱动(中心对齐,20kHz)
- Clarke / InvClarke 变换
- Park / InvPark 变换
- SVPWM 算法实现(开环,6扇区,过调制保护)
- LKS560 驱动板连接 — 电机已可转动
- VOFA+ JustFloat 串口波形输出(6通道,115200bps)
- ADC 三相电流采样(PC0/PC1/PC2, ADC1 IN10/IN11/IN12)
- TIM6/TIM7 硬件触发 ADC(与 PWM 同步采样)
- 死区时间软件偏移
- PI 电流闭环(Id/Iq 闭环控制)
- 速度闭环
- FOC_Q15 定点版算法实现
-
TIM1 引脚使用全重映射(
GPIO_FullRemap_TIM1),PE9/PE11/PE13 为上管 PWM 输出。 -
上下管分属不同定时器,死区需在 SVPWM 算法中通过偏移 CCR 值实现。
-
高级定时器必须调用
TIM_CtrlPWMOutputs()使能主输出 MOE,否则 PWM 引脚无波形输出。 -
编译宏定义:
STM32F10X_HD,USE_STDPERIPH_DRIVER,HSE_VALUE=8000000 -
VOFA+ 串口使用 USART1(PA9 TX),115200bps,JustFloat 协议,帧尾
0x00 0x00 0x80 0x7F。 -
当前版本不再使用 TIM1 TRGO → TIM8 ITR0 主从同步机制,改为
BSP_PWM_Init()末尾直接同时使能两个定时器。
- 打开
Project/RVMDK(uv5)/BH-STM32.uvprojx - 选择目标芯片:STM32F103VE
- 编译:点击 Build(或 F7)
- 下载:连接 CMSIS-DAP 调试器,点击 Download(或 F8)
- 运行:复位后自动运行
最后更新:2026-06-21