硬件部分
主功率回路

导通模式
步骤1:初始导通(Q1/Q4导通)
- 状态:Q1(左上管)与Q4(右下管)导通
- 电流路径:
VIN+ → Q1 → 负载上端 → 负载下端 → 电感 → Q4 → VIN-
- 关键特征:
- 电感储能阶段(能量来自输入电源)
- 输出端电压为正向幅值(Vout ≈ Vin)
步骤2:关闭Q1/Q4(换向起点)
关闭顺序:
- 优先关闭Q1(高压侧管),后关闭Q4(或同步关闭)
- 死区时间需覆盖最慢关断时间(典型值:100-200ns)
续流路径:
- 电感电流通过MOS体二极管续流:
负载下端 → 电感 → Q3体二极管(右上) → VIN+ → VIN- → Q2体二极管(左下) → 负载上端
物理现象:
- 体二极管导通导致Vds电压降至负值(需注意门极负压防护)
步骤3:死区时间(无开关管导通)
- 持续时间:50-100ns(由驱动芯片设置)
- 关键要求:
- 必须大于最慢体二极管反向恢复时间(推荐SiC MOSFET以缩短死区)
- 风险控制:
- 避免共通导通(上下管同时导通导致直通短路)
步骤4:开启Q2/Q3(负半周导通)
- 导通顺序:同时或略有延迟开启Q2(左下管)和Q3(右上管)
- 电流转移过程:
- 体二极管续流维持电流
- MOS沟道逐渐导通,电流从二极管转移到MOS管
- 稳定路径:
VIN+ → Q3 → 电感 → 负载下端 → 负载上端 → Q2 → VIN-
步骤5:关闭Q2/Q3(反向换向)
- 关闭顺序:优先关闭Q3(高压侧管),后关闭Q2
- 续流路径:
负载上端 → Q1体二极管 → VIN+ → VIN- → Q4体二极管 → 电感 → 负载下端
- 关键现象:
- 电感能量回馈至输入电容(需注意输入电压泵升风险)
步骤6:开启Q1/Q4(新周期开始)
- 反向恢复影响:
- Q1/Q4体二极管在导通瞬间产生反向恢复电流尖峰
- 使用快速恢复二极管或SiC MOSFET可降低尖峰幅度
- 优化策略:
- 门极驱动添加米勒钳位电路(抑制Vgs振荡)
输出滤波部分
一、LC滤波 vs LCL滤波对比
特性 | LC滤波 | LCL滤波 |
---|---|---|
拓扑结构 | 单电感+单电容 | 双电感+单电容+阻尼网络 |
适用场景 | 离网逆变、电机驱动 | 并网逆变、高精度电能质量场景 |
高频衰减 | -20dB 斜率(低于转折频率) | -60dB 斜率(高于谐振点) |
谐振风险 | 单谐振峰(需RC阻尼) | 双谐振峰(必须主动/被动阻尼) |
体积/成本 | 电感体积较大 | 总电感量减少30%~50% |
EMI抑制 | 有效抑制开关频率谐波 | 可同时抑制高频和低频谐波 |
关键设计约束 | 避免与负载谐振 | 需精确控制电网阻抗影响 |
二、LC滤波器参数设计
适用场景:离线式逆变器、UPS、电机驱动(无需并网)
核心设计思想:LC滤波器的主要目标是有效衰减由开关频率 ($f_{sw}$) 产生的纹波,同时确保期望的输出基波频率能够无衰减或低衰减地通过。设计的关键在于将LC滤波器的截止频率 ($f_c$) 设置在远低于开关频率但又显著高于输出基波频率的合理位置。
设计步骤
- 确定目标截止频率 ($f_c$)
滤波器截止频率由L和C共同决定: $$
f_c = \frac{1}{2\pi\sqrt{L \cdot C}}
$$ 建议取: $$
f_c \approx \frac{f_{sw}}{10} \quad \text{(典型取值:1/20 ~ 1/5 }f_{sw}\text{)}
$$ 示例:若开关频率 $f_{sw}=20\ \text{kHz}$,则取 $f_c \approx 2\ \text{kHz}$
- 选择初始元件参数
根据实际需求选择L或C作为起点:- 方法一:优先选定电感L
$$
C = \frac{1}{(2\pi f_c)^2 \cdot L}
$$ 估算电流纹波:
$$
\Delta I_L \approx \frac{V_{dc}}{4 \cdot L \cdot f_{sw}}
$$ - 方法二:优先选定电容C
$$
L = \frac{1}{(2\pi f_c)^2 \cdot C}
$$
- 方法一:优先选定电感L
- 标称元件选择与验证
选择最接近标称值后重新计算实际截止频率: $$
f_{c_actual} = \frac{1}{2\pi\sqrt{L_{nominal} \cdot C_{nominal}}}
$$ 误差应控制在±10%以内
- 纹波验证 验证项目 公式 允许范围 电流纹波 $$\Delta I_L \approx \frac{V_{dc}}{4Lf_{sw}}$$ <20%额定电流峰值 电压纹波 $$\Delta V_{out} \approx \frac{\Delta I_L}{8f_{sw}C}$$ <2%输出电压峰值
- 阻尼电阻设计
抑制谐振峰的推荐参数: $$
R_{damp} \approx \frac{1}{3}\sqrt{\frac{L}{C}} \quad \text{(与C串联)}
$$
设计验证案例
案例1:高压逆变器(380V→220VAC)
参数 | 值 |
---|---|
直流母线电压 | 380 V |
目标截止频率 | 2 kHz |
额定功率 | 3 kW |
选择电感 | 1.2 mH |
计算电容 | 5.28 μF → 选用5.6 μF |
实际截止频率 | 1.94 kHz |
电流纹波 | 3.96 A (峰值19.3A时20%) |
电压纹波 | 4.42 V (峰峰值1.42%) |
阻尼电阻 | 4.7 Ω/10W |
案例2:低压系统(24V直流输入)
参数 | 值 |
---|---|
直流母线电压 | 24 V |
目标截止频率 | 2 kHz |
已有电感 | 330 μH |
计算电容 | 19.19 μF → 18.8 μF实测 |
实际截止频率 | 2.02 kHz |
电流纹波 | 0.91 A (峰峰值) |
电压纹波 | 0.30 V (峰峰值1.5%) |
三、LCL滤波器参数设计
1. 谐振频率边界设定
$$
10 \cdot \underbrace{f_{grid}}_{\text{电网频率}} < \underbrace{f_{res}}_{\text{谐振频率}} < 0.5 \cdot \underbrace{f_{sw}}_{\text{开关频率}}
$$
- $f_{grid}$:电网基波频率(50/60Hz)
- $f_{sw}$:逆变器开关频率(10-50kHz)
- $f_{res}$:滤波器谐振频率(推荐1-2kHz)
2. 电感参数设计
$$
L_1 \approx \frac{\overbrace{V_{dc}}^{\text{直流电压}}}{k \cdot \underbrace{\Delta I_{L1,pp}}_{\text{纹波峰峰值}} \cdot f_{sw}} \quad \text{(}k=8\text{,SPWM调制系数)}
$$
- $L_1$:逆变器侧电感(单位:亨/H)
- $V_{dc}$:直流母线电压(如400V)
- $\Delta I_{L1,pp}$:允许的纹波电流峰峰值(通常取额定电流的10%-20%)
$$
\begin{cases} L_1 = (60\%\sim70\%)L_{total} \\ L_2 = L_{total} – L_1 \quad \text{(电网侧电感)} \end{cases}
$$
3. 电容参数计算
$$
C = \frac{1}{(2\pi \underbrace{f_{res}}_{\text{目标谐振频率}})^2} \cdot \frac{\overbrace{L_1 + L_2}^{\text{总电感量}}}{L_1 L_2}
$$
- $C$:滤波电容(单位:法拉/F)
- $L_1$:逆变器侧电感(0.8mH)
- $L_2$:电网侧电感(0.45mH)
4. 阻尼网络设计
$$
\underbrace{R_d}_{\text{阻尼电阻}} = \frac{1}{3 \cdot (2\pi f_{res}) \cdot C}
$$
$$
\underbrace{P_{Rd}}_{\text{电阻功率}} = \left( \frac{V_{dc}}{4\sqrt{3}f_{sw}L_1} \right)^2 \cdot R_d \cdot \underbrace{2}_{\text{安全系数}}
$$
- $R_d$:阻尼电阻(单位:欧姆/Ω)
- $P_{Rd}$:电阻耗散功率(需满足温升要求)
PCB设计
输入→母线电容→全桥MOS管→LC滤波→输出
1. 电容-最短化电流路径
- 低ESL设计:电容与MOS管构成三角形电流环,寄生电感可压降至<5nH,对比远端布局(如电容放板边)可减少60%电压尖峰
- 纹波吸收:电容距离MOS管D极<15mm时,高频纹波吸收效率提升3倍(10MHz以上频段)
2. MOS水平阵列
- 对称性强制:Q1/Q2与Q3/Q4严格镜像对称,各桥臂走线长度偏差<0.5mm(确保导通阻抗一致)
- 热均衡策略:水平排列使热源均匀分布,配合底部2oz铜箔+散热过孔,温差可控制在ΔT<8℃
- 开关节点优化:中间两管(Q2/Q3)的D极形成紧凑的SW节点区域,铜箔面积<4cm²(降低辐射EMI)
3. 驱动芯片下置——信号完整性
- 路径最短化:驱动输出到栅极的路径长度≤20mm,可将栅极回路电感限制在7nH以下
- 干扰隔离:利用MOS管本体作为天然屏蔽层,驱动电路与功率回路形成垂直电磁隔离
4. LC滤波
- π型滤波结构:电感前后布置两级电容(例如100μF电解电容+10μF陶瓷电容)
- 高频滤波:电容GND引脚直接连接至电源地层(非通过过孔),可将100MHz以上噪声衰减20dB
- 安全间距:电感与电容保持≥5mm间距,避免磁场耦合引发损耗


软件部分
SPWM参数
1. 调制度(Modulation Index, ( m ))
定义:调制波幅值与载波幅值的比值,决定输出电压幅值
公式:
$$
m = \frac{\sqrt{2} \cdot V_{\text{ph}}}{V_{\text{dc}}} \quad (\text{单极性SPWM})
$$
- $V_{\text{dc}}$:直流母线电压
- $V_{\text{ph}}$:输出相电压有效值
取值范围:
$$
0.8 < m < 0.95 \quad \text{(常规逆变器)}
$$
2. 周内点数(Points per Cycle, ( N ))
定义:每个正弦波周期内的PWM脉冲数
公式:
$$
N = \frac{f_{\text{c}}}{f_{\text{m}}} = \frac{T_{\text{m}}}{T_{\text{c}}}
$$
- $f_{\text{c}}$:载波频率(边缘对齐模式下PWM频率)(单位:Hz)
- $f_{\text{m}}$:调制波频率(正弦波基波频率)(单位:Hz)
设计规则:
$$
N \geq \begin{cases}
21 & (\text{THD}<5\%) \
81 \sim 201 & (\text{高精度模式})
\end{cases}
$$
3. SPWM中值(Mid-value)
定义:正弦波零点对应占空比
公式:
$$
Mid = \frac{ARR}{2}
$$
4. SPWM幅值(Amplitude of Modulation Wave, ( $V_{\text{m}}$ ))
定义:SPWM峰峰值
公式:
$$
Amp = Mid \times M
$$
5. 载波频率 ($f_c$) 设计规范
设计约束条件:
采样定理约束
$$
f_c \geq 10 \times f_{max}
$$
- $f_{max}$:系统需处理的最高谐波频率(通常取基波频率的21次谐波)
行业应用指南:
功率等级 | 推荐$f_c$范围 | 适用器件类型 | 损耗分布特性 |
---|---|---|---|
<1kW | 10-20kHz | MOSFET | 驱动损耗占比>60% |
1-10kW | 5-10kHz | IGBT/SiC MOSFET | 开关损耗占比>70% |
>10kW | 2-5kHz | IGCT/压接式IGBT | 散热设计主导参数 |
高频应用 | 50-100kHz | GaN HEMT | 需配合零电压切换技术(ZVS) |
案例:3kW光伏逆变器参数
参数 | 计算值 | 选用值 | 验证结果 |
---|---|---|---|
理论$f_c$ | 18.7 kHz | 20 kHz | 通过 |
栅极驱动功耗 | 3.2 W | 3.8 W | 温升Δ8℃ |
器件开关损耗 | 45 W | 48 W | 散热器65℃ |
总效率影响 | 0.7% | 0.82% | 符合EN50530 |
6. PWM对齐模式
参数 | 边缘对齐模式 | 中心对齐模式 |
---|---|---|
实现复杂度 | 简单(单计数器) | 复杂(双计数器) |
谐波分布 | 集中在$f_{\text{c}}$附近 | 分布在2$f_{\text{c}}$附近 |
死区影响 | 波形不对称度较高 | 对称性好 |
适用场景 | 低成本单相逆变器 | 三相电机驱动/光伏逆变器 |
EMI性能 | 较差 | 较好 |
开关损耗 | 较高(集中在周期边沿) | 较低(分散分布) |
驱动部分
- 同一桥臂内部:上下管驱动信号严格互补(理想相位差180°)并必须插入死区时间,以防止桥臂直通。
- 两桥臂之间:
- 双极性SPWM:通常由一对互补的SPWM信号(一个主PWM和它的反相信号,均包含死区)分别驱动两个桥臂的上管(或半桥驱动芯片的输入),使得两桥臂的输出电压近似反相。
- 单极性SPWM:通常由两路独立的、相位错开180°的SPWM信号分别驱动两个桥臂(或其半桥驱动芯片),或者通过更复杂的逻辑使得输出电压呈现三电平特性。
双极性SPWM
1. 电压切换特性
- 输出电平:H桥输出电压(滤波前)在 $+V_{DC}$ 和 $-V_{DC}$ 之间进行双电平切换
- 电压跳变幅度:在一个开关周期内,电压变化幅度 $\Delta V$ 可达 $2V_{DC}$
2. LC滤波器特性
- 电容电流:滤波电容 $C_f$ 上的电流由 $$ I_C = C_f \frac{dV}{dt} $$ 决定
- 电压变化率 $dV/dt$:在24V系统中 ($\Delta V \approx 48V$),若开关时间为0.24µs – 0.48µs,则 $dV/dt$ 约为 $$100V/\mu s \sim 200V/\mu s$$
- 典型电流尖峰:$100nF \times (100V/\mu s \sim 200V/\mu s) = \textbf{10A} \sim \textbf{20A}$
3. 直流电源特性
- 空载电流(RMS估算):
$$ I_{RMS} \approx \frac{2V_{DC}f_{sw}C_f}{\sqrt{3}} $$
实例:24V系统/20kHz开关频率/1.98µF电容时 $I_{RMS} \approx 1.1A$ - 风险:实测24V电源电压跌落至10V,电流达到限流点
单极性SPWM
1. 电压切换特性
- 输出电平:H桥输出电压(滤波前)在 $+V_{DC}$、0V、和 $-V_{DC}$ 之间进行三电平切换
- 电压跳变幅度:主要跳变幅度 $\Delta V$ 通常为 $V_{DC}$
2. LC滤波器特性
- 电容电流: $$ I_C = C_f \frac{dV}{dt} $$
- 电压变化率 $dV/dt$:在24V系统中 ($\Delta V \approx 24V$),$dV/dt$ 降低50%至 $$50V/\mu s \sim 100V/\mu s$$
- 典型电流尖峰:$100nF \times (50V/\mu s \sim 100V/\mu s) = \textbf{5A} \sim \textbf{10A}$
3. 直流电源特性
- 空载电流(RMS估算):
$$ I_{RMS} \approx \frac{V_{DC}f_{sw}C_f}{2\sqrt{3}} $$
实例:相同参数下电流降至 $I_{RMS} \approx 0.28A$ - 优势:电源电压稳定性提升约3.9倍
关键参数对比
技术指标 | 双极性SPWM | 单极性SPWM |
---|---|---|
输出电压电平数 | 2电平 ($+V_{DC}$/$-V_{DC}$) | 3电平 ($+V_{DC}$/0/$-V_{DC}$) |
电压跳变幅度 | $2V_{DC}$ | $V_{DC}$ |
电容电流尖峰 | 10-20A@100nF | 5-10A@100nF |
开关频率利用率 | 1×载波频率 | 2×载波频率 |
THD(@m=0.9) | 3.8% | 1.2% |
滤波器体积比 | 基准100% | 电感体积减少40% |
EMI主频分布 | $f_{sw}$±n$f_m$ | $2f_{sw}$±n$f_m$ |
开关器件损耗 | 全桥高频开关 | 半桥高频+半桥工频 |
参考代码
PWM20KHZ 生成正弦表 开20KHZ中断 产生SPWM
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "hrtim.h"
#include "tim.h"
#include "gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
#define SINE_TABLE_POINTS 400
#define HRTIM_PERIOD_VALUE 57600 // HRTIM 周期寄存器值 (ARR/PER)
#define SPWM_CENTER_VALUE (HRTIM_PERIOD_VALUE / 2)
#define SPWM_AMPLITUDE_VALUE 24480 // 28800 * 0.85
// 正弦查找表 (400点, m=0.85)
const uint16_t sine_table[SINE_TABLE_POINTS] = {
28800,29184,29568,29950,30332,30712,31090,31467,31842,32215,32587,32956,33323,33688,34050,34410,
34767,35121,35472,35820,36164,36505,36842,37176,37506,37832,38154,38472,38786,39095,39400,39700,
39996,40287,40573,40854,41130,41401,41667,41928,42183,42434,42679,42919,43153,43382,43605,43823,
44035,44242,44443,44639,44829,45013,45192,45365,45532,45693,45849,45998,46142,46280,46412,46538,
46658,46772,46880,46982,47078,47168,47252,47330,47402,47468,47528,47582,47630,47672,47708,47738,
47762,47780,47792,47798,47798,47792,47780,47762,47738,47708,47672,47630,47582,47528,47468,47402,
47330,47252,47168,47078,46982,46880,46772,46658,46538,46412,46280,46142,45998,45849,45693,45532,
45365,45192,45013,44829,44639,44443,44242,44035,43823,43605,43382,43153,42919,42679,42434,42183,
41928,41667,41401,41130,40854,40573,40287,39996,39700,39400,39095,38786,38472,38154,37832,37506,
37176,36842,36505,36164,35820,35472,35121,34767,34410,34050,33688,33323,32956,32587,32215,31842,
31467,31090,30712,30332,29950,29568,29184,28800,28416,28032,27650,27268,26888,26510,26133,25758,
25385,25013,24644,24277,23912,23550,23190,22833,22479,22128,21780,21436,21095,20758,20424,20094,
19768,19446,19128,18814,18505,18200,17900,17604,17313,17027,16746,16470,16199,15933,15672,15417,
15166,14921,14681,14447,14218,13995,13777,13565,13358,13157,12961,12771,12587,12408,12235,12068,
11907,11751,11602,11458,11320,11188,11062,10942,10828,10720,10618,10522,10432,10348,10270,10198,
10132,10072,10018,9970,9928,9892,9862,9838,9820,9808,9802,9802,9808,9820,9838,9862,
9892,9928,9970,10018,10072,10132,10198,10270,10348,10432,10522,10618,10720,10828,10942,11062,
11188,11320,11458,11602,11751,11907,12068,12235,12408,12587,12771,12961,13157,13358,13565,13777,
13995,14218,14447,14681,14921,15166,15417,15672,15933,16199,16470,16746,17027,17313,17604,17900,
18200,18505,18814,19128,19446,19768,20094,20424,20758,21095,21436,21780,22128,22479,22833,23190,
23550,23912,24277,24644,25013,25385,25758,26133,26510,26888,27268,27650,28032,28416
};
volatile uint16_t sine_table_index = 0; // 正弦表当前索引
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_HRTIM1_Init();
MX_TIM1_Init();
/* USER CODE BEGIN 2 */
HAL_HRTIM_WaveformOutputStart(&hhrtim1, HRTIM_OUTPUT_TA1|HRTIM_OUTPUT_TA2); //通道打开
HAL_HRTIM_WaveformCountStart(&hhrtim1, HRTIM_TIMERID_TIMER_A); //开启子定时器A
HAL_TIM_Base_Start_IT(&htim1);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
{
Error_Handler();
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_HRTIM1|RCC_PERIPHCLK_TIM1;
PeriphClkInit.Tim1ClockSelection = RCC_TIM1CLK_HCLK;
PeriphClkInit.Hrtim1ClockSelection = RCC_HRTIM1CLK_PLLCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
}
/* USER CODE BEGIN 4 */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM1) // 确保是TIM1中断
{
uint16_t spwm_val_ta1;
uint16_t spwm_val_ta2;
// 1. 从正弦表中获取TA1的当前SPWM比较值
spwm_val_ta1 = sine_table[sine_table_index];
// 2. 计算TA2的SPWM比较值 (与TA1相差180度)
// 公式: val_ta2 = HRTIM_PERIOD_VALUE - val_ta1
// 这个公式适用于单极性SPWM,其中两个桥臂的调制信号反相。
// 请确保sine_table中的值始终小于HRTIM_PERIOD_VALUE。
// 如果spwm_val_ta1可能等于HRTIM_PERIOD_VALUE,则spwm_val_ta2会为0。
// 如果spwm_val_ta1可能为0,则spwm_val_ta2会等于HRTIM_PERIOD_VALUE。
// 这通常是期望的行为。
spwm_val_ta2 = HRTIM_PERIOD_VALUE - spwm_val_ta1;
// 安全钳位 (可选,但推荐,以防正弦表计算有误或溢出)
// 你的正弦表设计应该已经保证了值在有效范围内 (例如 0 到 HRTIM_PERIOD_VALUE-1)
// 如果你的正弦表值可以达到 HRTIM_PERIOD_VALUE,那么这里钳位到 HRTIM_PERIOD_VALUE-1 可能更安全,
// 以避免占空比为100%或0%时可能出现的非常窄的脉冲或无脉冲的问题,具体取决于你的Set/Reset配置。
// 但是对于标准的周期置位,比较值复位, HRTIM_PERIOD_VALUE 作为比较值意味着整个周期都是高电平(或低电平,取决于极性)。
// 0 作为比较值意味着在周期开始时就复位。
// if (spwm_val_ta1 >= HRTIM_PERIOD_VALUE) spwm_val_ta1 = HRTIM_PERIOD_VALUE -1; // 防止100%占空比问题 (如果需要)
// if (spwm_val_ta1 == 0) spwm_val_ta1 = 1; // 防止0%占空比问题 (如果需要)
// if (spwm_val_ta2 >= HRTIM_PERIOD_VALUE) spwm_val_ta2 = HRTIM_PERIOD_VALUE -1;
// if (spwm_val_ta2 == 0) spwm_val_ta2 = 1;
// 3. 更新 HRTIM Timer A 的比较寄存器
// TA1 由 Compare Unit 1 控制
__HAL_HRTIM_SETCOMPARE(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_1, spwm_val_ta1);
// TA2 由 Compare Unit 2 控制
__HAL_HRTIM_SETCOMPARE(&hhrtim1, HRTIM_TIMERINDEX_TIMER_A, HRTIM_COMPAREUNIT_2, spwm_val_ta2);
// 4. 移动到正弦表的下一个点
sine_table_index++;
if (sine_table_index >= SINE_TABLE_POINTS)
{
sine_table_index = 0; // 到达表尾则回绕到表头
}
}
}
/* USER CODE END 4 */
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */