【动手学STM32G4】(15)三路互补带死区 PWM 输出

【动手学STM32G4】(1)STM32G431之创建项目
【动手学STM32G4】(4)STM32G431之PWM输出
【动手学STM32G4】(15)三路互补带死区 PWM 输出

【动手学电机驱动】(15)三路互补带死区 PWM 输出

    • [1. 项目介绍](#1. 项目介绍)
      • [1.1 项目内容](#1.1 项目内容)
      • [1.2 互补PWM与死区时间](#1.2 互补PWM与死区时间)
      • [1.3 硬件需求与引脚分配](#1.3 硬件需求与引脚分配)
    • [2. CubeMX工程配置](#2. CubeMX工程配置)
      • [2.1 创建新项目](#2.1 创建新项目)
      • [2.2 TIM 配置](#2.2 TIM 配置)
      • [2.3 生成代码](#2.3 生成代码)
    • [3. CubeIDE 编程与调试](#3. CubeIDE 编程与调试)
    • [4. 实验结果](#4. 实验结果)
  • [5. 小结](#5. 小结)

1. 项目介绍

1.1 项目内容

在电机控制中通常使用三相逆变桥来驱动电机,每个桥臂需要一对互补的PWM信号来控制上下桥臂的MOSFET,并且为了避免上下桥臂同时导通(直通),必须插入死区时间。

  • 三相系统:需要U、V、W三个独立的PWM通道
  • 双向驱动:每相需要高侧(推)和低侧(拉)两个开关管
  • 互补控制:高侧和低侧必须严格互补导通
  • 安全间隙:切换瞬间必须留出"死区时间"防止直通

我们在前文 【动手学STM32G4】(4)STM32G431之PWM输出 中已经介绍了 PWM 输出的基本方法。本文在此基础上,实现三路互补带死区的 PWM 输出。

  • 配置STM32G431的高级定时器TIM1
  • 生成三路带死区的互补PWM信号
  • 掌握 PWM 的计算与配置方法

1.2 互补PWM与死区时间

脉冲宽度调制(PWM)利用MCU 的数字输出来对模拟电路进行控制,采用一系列形状不同但面积相等的矩形脉冲代替正弦信号,具有与正弦波输入近似的输出响应。

一类 PWM 输出的应用是由 MOS、IGBT 等功率器件组成的 H 桥或三相桥 ,每路桥壁的上半桥和下半桥互补输出。"互补"意味着:当上桥臂导通时,下桥臂必须关断;当下桥臂导通时,上桥臂必须关断。

在电机控制中,通过控制开关管的导通和关断,来在电机三相绕组上产生所需的电压。每一相不能同时打开高侧和低侧开关管,否则会造成电源"直通"(Shoot-through),短路到地会瞬间产生大电流,烧毁开关管。

为了避免直通,同时又能控制电流的方向,需要采用"互补PWM"的控制方式。所谓互补,就是指同一相的高侧和低侧开关管的控制信号是互补的:当高侧打开时,低侧必须关闭;当低侧打开时,高侧必须关闭。

由于开关管从导通到关断,以及从关断到导通,都需要一定时间(开关时间)。如果在高侧关断后立即打开低侧,高侧可能还没有完全关断而导致直通。因此,需要在控制信号中插入一段"死区时间"(Dead Time),在半桥关断后延迟一段时间再打开互补半桥,防止上下半桥同时导通而导致器件烧毁。

1.3 硬件需求与引脚分配

  1. 硬件平台:NUCLEO-G431RB 开发板

  2. 引脚分配

    本实验使用 TIM1 定时器,PWM 输出的引脚分配如下。

bash 复制代码
TIM1:
  CH1: PA8, CH1N:PB13
  CH2: PA9, CH2N:PB14
  CH3: PA10, CH3N:PB15
  1. 中断频率与 PWM 占空比计算
    根据业务需要,本实验生成频率 10kHz、占空比为 50% 的 PWM。

(1)配置系统时钟 SysCLK 为 160MHz,选择 PSC = 0(不分频),ARR = 8000-1。

系统时钟频率为 168MHz,将计数周期 Counter Period 设为 16000/2(除2是因为三角波分为上升和下降两段),则 PWM 频率为 160MHz/16000 = 10KHz。

(2)计算 PWM 频率与占空比:

f P W M = f s y s ( P S C + 1 ) ∗ ( A R R + 1 ) = 160 M H z 8000 = 20 k H z p u l s e = d u t y ∗ A R R = 0.5 ∗ 7999 = 4000 \begin{matrix} f_{PWM} &=&\frac{f_{sys}}{(PSC+1)*(ARR+1)} &=&\frac{160 MHz}{8000}&= 20 kHz \\ pulse &=& duty *ARR &=& 0.5 * 7999 &= 4000 \end{matrix} fPWMpulse==(PSC+1)∗(ARR+1)fsysduty∗ARR==8000160MHz0.5∗7999=20kHz=4000

(3)设置 Prescaler(PSC)为 0,设置 Counter Period(ARR)为 8000。在 "PWM Generation Channel 1" 下,设置 Pulse 为 4000,则可以得到频率为 10kHz,占空比为 50% 的 PWM。

  1. 死区时间的计算:
    (1)IHM16M1 驱动板使用 STSPIN830,典型开关延迟:50ns,上升/下降时间:30ns。按照 50% 安全余量设计:最坏情况延迟 = 50ns + 30ns =80ns,安全死区时间 = 80ns * 1.5 = 120ns。
    (2)在 STM32G431 上,死区时间以定时器时钟周期为单位:TIM1 时钟 160 MHz,时钟周期 = 1/160MHz = 6.25ns,由此计算:死区时钟计数 = 120ns/6.25ns = 19.2。
    于是,死区时间计数取为 20。

2. CubeMX工程配置

2.1 创建新项目

  1. 新建工程。

    启动 STM32CubeMX,点击 "Start New Project" (或Ctrl-N快捷键)新建工程,进入 New Project 界面。

    选择MCU为 STM32G431RBT6(参考开发板的 MCU 型号选择)。

    选择开发板为 NUCLEO-G431RB 开发板。

    点击右上角 "Start Project" 创建项目。

  2. 配置系统时钟树。

    (1)点击顶部 "Clock Configuration" 选项卡,进入时钟树配置。

    (2)设置输入频率 Input frequency=24 MHz,SysCLK frequency=160 MHz。

    配置完成后,System Clock 显示为160MHz,HCLK、PCLK1、PCLK2 均为160MHz。

  1. 系统配置:在引脚配置(Pinout & Configuration)中,选择 "System Core -- SYS" 。

    (1)设置调试器类型,将 Debug 模式设为 "Serial Wire"。

    (2)设置基础时钟源(Timebase Source),可以选择默认设置 "SysTick"。

    (3)时钟配置:在引脚配置(Pinout & Configuration)中,选择 "System Core -- RCC" 配置时钟模式。

    设置高速时钟为外部晶振,将 High Speed Clock (HSE) 设为 "Crystal/Ceramic Resonator"。

    Low Speed Clock (LSE) 设为 "Disable"(本实验不需要)。

  2. GPIO 配置。

    (1)将 LD2(PA5)配置为输出模式 "GPIO_Output"。

    (2)将用户按键(PC13)配置为外部中断 "GPIO_EXTI13"。

2.2 TIM 配置

配置定时器 TIM1 中断频率为 10kHz。

  1. 配置 TIM1 输出管脚。
    在右侧 Pinout View 图中,
bash 复制代码
将 TIM1_CH1 映射到 PA8 管脚
将 TIM1_CH2 映射到 PA9 管脚
将 TIM1_CH3 映射到 PA10 管脚
将 TIM1_CH1N 映射到 PB13 管脚
将 TIM1_CH2N 映射到 PB14 管脚
将 TIM1_CH3N 映射到 PB15 管脚
  1. 启用并配置TIM1 :
    (1)选择 "引脚配置(Pinout & Configuration)",从左侧下拉列表中选择 "Timers -- TIM1 -- TIM1 Mode and Configuration ",配置 TIM1 Mode 如下:
bash 复制代码
Clock Source 配置为: Internal Clock
Channel-1 配置为: PWM Generation CH1 CH1N(PWM 互补输出)
Channel-2 配置为: PWM Generation CH2 CH2N(PWM 互补输出)
Channel-3 配置为: PWM Generation CH3 CH3N(PWM 互补输出)
Channel-4 配置为: PWM Generation No Output(备用,用于 触发ADC采样)

(2)TIM1 计数器参数配置:

预分频 Prescaler(PSC)设为 0,不分频;

计数器模式 Counter Mode 选择中心对齐的三角波:Center Aligned model 1 ;

计数周期 Counter Period 设为 PWM 频率:8000-1;

允许重新加载:auto-reload preload 设为 Enable;

更新时触发一个事件:Trigger Event Selection TRGO 设为 Update Event。

bash 复制代码
Counter Settings:
   Prescaler (PSC-16 bits value): 0
   Counter Mode: Center Aligned mode 1
   Counter Period (ARR): 7999
   Internal Clock Division (CKD): No Division
   Repetition Counter (RCR): 0
   auto-reloaded preload: Enable
Trigger Output (TRGO) Parameters:
   Trigger Event Selection TRGO: Update Event

(3)死区时间参数配置:

在 "Break And Dead Time management - Output Configuration" 选项中:

bash 复制代码
Break And Dead Time management - Output Configuration:
   Automatic Output State: Enable
   DeadTime Preload: Enable
   Dead Time: 20(计数周期)

(4)PWM 发生器参数配置:

互补 PWM 的极性配置要根据硬件选择,例如上管 PMOS、下管 NMOS,需要将极性配置相反;如果上下桥都是 NMOS,则需要将极性配置相同。

bash 复制代码
PWM Generation Channel 1 and 1N
   Mode: PWM mode 1
   Pulse: 4000 (占空比为 50%)
   Output compare preload: Enable
PWM Generation Channel 2 and 2N
   Mode: PWM mode 1
   Pulse: 4000 (占空比为 50%)
   Output compare preload: Enable
PWM Generation Channel 3 and 3N
   Mode: PWM mode 1
   Pulse: 4000 (占空比为 50%)
   Output compare preload: Enable

2.3 生成代码

  1. 点击 "Project Manager" 菜单按钮,进入工程配置界面。
  • 输入项目名称为 "STM32G431_PWM04",选择项目的保存路径。
  • 将Toolchain / IDE 设为 STM32CubeIDE(根据用户安装和使用的 IDE 选择,也可以选择 EWARM、MDK-ARM、MakeFile、CMake 等IDE工具)
  • 点击右上角 "GENERATE CODE" 生成代码
  • 加载完毕后,弹出代码生成提示窗口,点击" OPEN PROJECT",进入 STM32CubeIDE。

3. CubeIDE 编程与调试

  1. 在 STM32CubeIDE 打开代码文件 main.c。

    代码生成后,已经自动进入 STM32CubeIDE,并打开创建的 STM32G431_DAC01 项目。在 "Core\Src" 目录中,已经生成了 dac.c 和 main.c 等基础程序。

  2. 程序 main.c 的架构如下:

  3. 编写程序代码。

(1)在程序开头部分,添加参数定义和 生成 PWM 输出的函数如下。

c 复制代码
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#define TIM_CLK_MHz 160
#define PWM_FREQ 10000
#define PWM_PERIOD 1000000*TIM_CLK_MHz/PWM_FREQ/2
/* USER CODE END Includes */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void generate_PWM(void)
{
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1); // Start PWM CH1
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);

	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_1); // Set PWM CH1N
	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_2);
	HAL_TIMEx_PWMN_Start(&htim1,TIM_CHANNEL_3);

	__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1, 0.5*PWM_PERIOD); // Set PWM1-CH1 duty: 50%
	__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2, 0.4*PWM_PERIOD);
	__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3, 0.3*PWM_PERIOD);
}
/* USER CODE END 0 */

(2)在主程序 main() 初始化完成后,添加 生成 PWM 输出的程序代码:

c 复制代码
  /* USER CODE BEGIN 2 */
  generate_PWM();
  /* USER CODE END 2 */

  /* Infinite loop */
  while (1)
  {
	  HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	  HAL_Delay(100);  // Insert delay 100 ms
  }

(3)将鼠标移动到 HAL_TIM_PWM_Start,按 F3 可以打开 HAL_TIM_PWM_Start() 的程序代码如下。该程序用于启动 PWM 信号发生器。(该步骤非必须,只是介绍查看的方法)

c 复制代码
/**
  * @brief  Starts the PWM signal generation.
  * @param  htim TIM handle
  * @param  Channel TIM Channels to be enabled
  *          This parameter can be one of the following values:
  *            @arg TIM_CHANNEL_1: TIM Channel 1 selected
  *            @arg TIM_CHANNEL_2: TIM Channel 2 selected
  *            @arg TIM_CHANNEL_3: TIM Channel 3 selected
  *            @arg TIM_CHANNEL_4: TIM Channel 4 selected
  *            @arg TIM_CHANNEL_5: TIM Channel 5 selected
  *            @arg TIM_CHANNEL_6: TIM Channel 6 selected
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_PWM_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
  1. 程序编译与调试
  • 用 USB连接线,连接 PC 与 NUCLEO-G431RB 开发板。
  • 点击工具栏中 "Build Debug" 按键对程序代码进行编译。
  • 点击工具栏中 "Debug" 按键,将程序下载烧录到目标板 NUCLEO-G431RB 。
  • 点击工具栏中 "Resume" 按键 或 F8 快捷键,运行程序。

4. 实验结果

运行程序,NUCLEO-G431RB 开发板上的 LD2 指示灯以 10Hz 频率闪烁。

使用示波器观察引脚 PA8 和 PB13 输出的波形。

(1)示波器通道1 → U相高侧驱动信号UH(对应 PA8 引脚)

(2)示波器通道2 → U相低侧驱动信号UL(对应 PB13 引脚)

注:UH和UL是互补信号,用于驱动同一相的上、下桥臂MOSFET。

如下图所示,可以看到在每次电平切换时,UH和UL信号存在短暂的时间同时保持低电平,这就是死区时间。

5. 小结

本文详细介绍基于STM32G431的三路互补PWM输出,重点配置了死区时间保护和中央对齐模式,为电机FOC控制搭建了可靠的基础设施。通过理论计算与示波器验证,确保了PWM信号的精确性和安全性。下一讲将在此基础上,实现与PWM同步的电流采样,向完整的电机控制系统迈出关键一步。

版权声明:

youcans@qq 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/157326354)

Copyright@youcans 2026

Crated:2026-1

相关推荐
小慧10242 小时前
外部中断与回调函数
stm32·单片机·嵌入式硬件
加斯顿工程师2 小时前
STM32F103C8T6驱动DS18B20温度传感器程序
stm32·单片机·嵌入式硬件
czy87874752 小时前
LwIP 协议栈核心.c 文件依赖关系图
c语言·网络·单片机
猪八戒1.03 小时前
L C D
开发语言·stm32
YouEmbedded3 小时前
解码STM32 看门狗、低功耗与RTC外设
stm32·低功耗·rtc·看门狗·闹钟
YouEmbedded3 小时前
解码模数转换器(ADC)
stm32·adc·电位器adc·ps2摇杆模块adc·adc数据滤波算法·光敏电阻adc
Zeku3 小时前
Linux驱动学习笔记:SPI子系统中的内核线程初始化
stm32·freertos·linux驱动开发·linux应用开发
项目題供诗4 小时前
51单片机入门(四)
单片机·嵌入式硬件·51单片机
1379号监听员_4 小时前
stm32平衡车
stm32·单片机·嵌入式硬件