如何用定时器PWM产生SPWM?--电机驱动控制

用定时器生成 SPWM 的核心逻辑是:以高频三角波为载波,按正弦规律动态更新 PWM 占空比,最终通过低通滤波还原正弦波。以下是面向 STM32 的标准实现方案与代码。

一、核心原理与参数设计

  • 载波:高频三角波(推荐 10--20 kHz,远高于基波),由定时器 ARR/PSC 决定。
  • 调制:低频正弦波(如 50 Hz),通过查表或实时计算映射为 PWM 的 CCR 值。
  • 更新 :在每个载波周期起点更新 CCR,用定时器更新中断DMA实现。
  • 公式
    • PWM 频率:fPWM=ftimer_clk/((PSC+1)×(ARR+1))
    • 占空比映射:CCR=(1+sin(θ)×ARR)/2(归一化到 0--ARR)

二、硬件与参数选型(以 STM32F103 72 MHz 为例)

参数 取值 说明
定时器 TIM1(高级定时器) 支持互补输出与死区,适合电机驱动
载波频率 10 kHz fPWM​=10 kHz
PSC 71 72 MHz / (71+1) = 1 MHz 计数时钟
ARR 99 1 MHz / (99+1) = 10 kHz
基波频率 50 Hz 目标输出频率
采样点数 200 中断频率 = 50 Hz × 200 = 10 kHz

三、标准实现步骤(HAL 库)

1. 生成正弦表(离线 / 初始化)

预先计算一周期正弦值并映射到 0--ARR,提升运行效率。

复制代码
#define SINE_SIZE 200
uint16_t SineTable[SINE_SIZE];
const uint16_t ARR_VAL = 99;  // 对应10 kHz载波

void GenerateSineTable(void) {
  for(int i=0; i<SINE_SIZE; i++) {
    float theta = 2 * 3.14159f * i / SINE_SIZE;
    // 归一化到0~ARR_VAL
    SineTable[i] = (1 + sinf(theta)) * ARR_VAL / 2;
  }
}
2. 定时器 PWM 初始化

配置时基、通道与预装载,确保更新时 CCR 原子生效。

复制代码
TIM_HandleTypeDef htim1;
void MX_TIM1_Init(void) {
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 71;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = ARR_VAL;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim1);

  TIM_OC_InitTypeDef sConfigOC = {0};
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

  // 使能预装载
  __HAL_TIM_ENABLE_OCxPRELOAD(&htim1, TIM_CHANNEL_1);
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
}
3. 中断更新 CCR(推荐)

用 TIM_UP 中断按步长遍历正弦表,实现基波输出。

复制代码
uint16_t index = 0;
// 每100 us进入一次(对应10 kHz中断)
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
  if(htim->Instance == TIM2) {  // TIM2用于定时
    __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, SineTable[index]);
    index = (index + 1) % SINE_SIZE;
  }
}
4. 更高性能:DMA 传输(无 CPU 开销)

将正弦表直接绑定到 CCR,适合高频场景。

复制代码
// 初始化后启动DMA
HAL_TIM_PWM_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t*)SineTable, SINE_SIZE);

四、关键优化与注意事项

  1. 死区保护:驱动 MOS 管时,高级定时器需配置死区(如 1 µs),防止上下桥直通。

    // 配置死区1 µs(计数时钟1 MHz,死区值=1)
    __HAL_TIM_SET_DEADTIME(&htim1, 1);

  2. 互补输出:三相逆变时,用 CHx 与 CHxN 输出互补信号。

  3. 抗混叠:输出端加 LC 低通滤波器,滤除高频载波,还原平滑正弦波。

  4. 调制度:通过缩放正弦表幅值调整调制度(0--1),避免过调制失真。

五、完整工程流程(CubeMX+HAL)

  1. CubeMX 配置:TIM1 为 PWM 生成模式,TIM2 为 10 kHz 更新中断;使能 GPIO 复用输出。
  2. 生成代码,在main.c中调用GenerateSineTable()
  3. 启动 TIM2 中断与 TIM1 PWM,在回调中更新 CCR 或直接启动 DMA。
  4. 编译下载,用示波器验证 CH1 输出为 SPWM,经 LC 滤波后为正弦波。

六、常见问题与排查

  • 波形失真:检查载波频率是否足够高、正弦表点数是否充足、CCR 更新是否及时。
  • 无输出 :确认 GPIO 复用映射正确、PWM 通道使能、主输出使能(高级定时器需TIM_BDTR寄存器)。
  • 噪声大:增加滤波电容 / LC 参数,优化 PCB 布线,PWM 走线尽量短且远离干扰源。

七、扩展:三相 SPWM 与 EtherCAT 同步

  • 三相:生成三相互差 120° 的正弦表,在 TIM_UP 中断中同时更新 CH1/CH2/CH3。
  • EtherCAT 同步:用 SYNC0 信号初始化 PWM 计数器,确保控制周期与通信同步,提升运动控制精度。
相关推荐
Szime2 小时前
全球首创10位40GSPS超宽带ADC选型参考:国产超高速ADC深智微科技选型支持
科技·单片机·嵌入式硬件·fpga开发
(Morgan)3 小时前
51单片机期末复习知识点总结
stm32·单片机·嵌入式硬件
Zyed6 小时前
[STM32]Day9-Part1USART+串口接收+串口收发
stm32·单片机·嵌入式硬件
嵌入式ZYXC9 小时前
STM32烧录一次后无法再次烧录的两种原因
stm32·单片机·嵌入式硬件
踏着七彩祥云的小丑10 小时前
嵌入式测试学习第33 天:压力测试、反复开关机、反复插拔接口测试
单片机·嵌入式硬件·学习
开发笔记-阿牛11 小时前
CK6159A 可靠性测评:芯片工艺、环境测试与量产稳定性分析
stm32·单片机·嵌入式硬件
国科安芯11 小时前
商业航天通信载荷数字处理单元供电架构研究——基于ASP7A84AS的高精度低压差线性稳压器技术分析
前端·单片机·嵌入式硬件·fpga开发·架构·安全性测试
嵌入式ZYXC11 小时前
第8篇:《面试题:模拟地和数字地为什么要分开?怎么接?》
stm32·单片机·嵌入式硬件·面试·职场和发展
开发笔记-阿牛12 小时前
CK6159A 主控开发:多模式手电筒硬件架构、接线规范及选型参考
单片机·嵌入式硬件
一目Leizi12 小时前
通信协议完全指南
stm32·单片机·嵌入式硬件