系统地讲解 STM32 高级定时器互补输出带死区控制的完整实验,包括:


✅ 实验目标:

使用 STM32F103 的 TIM1 或 TIM8 高级定时器,通过互补 PWM 输出+死区控制,实现两个输出端(如 TIM1_CH1 与 TIM1_CH1N)交替输出互补 PWM 波形,并且在两个输出之间插入“死区时间”,防止上下桥臂同开造成短路。


🧠 一、费曼学习法 - 原理理解

❓ 什么是互补输出?

互补输出指的是同一通道的两个引脚输出反相信号,例如:

  • CH1 输出高电平 时,

  • CH1N 输出低电平,反之亦然。

这种方式广泛应用于 全桥驱动半桥驱动等场景中。

❓ 为什么要加死区时间(Dead Time)?

在开关器件(如 MOSFET)控制中,如果上下桥臂几乎同时导通,会造成短路。所以,需要在关闭一个器件后,延时一段时间再打开另一个 —— 这段时间叫做“死区”。


🧰 二、实验准备

项目 内容
开发板 STM32F103ZETx 等具有 TIM1/TIM8 的芯片
CubeMX 用于配置高级定时器 TIM1
Keil MDK 编写和下载代码
外设连接 用示波器观测 CH1CH1N 输出波形

🧱 三、CubeMX 配置步骤(TIM1 为例)

1️⃣ 选择 TIM1 并使能通道:

  • 选择 PWM Generation CH1 and CH1N

  • TIM1 是高级定时器,自带互补输出功能(CHxN)。

2️⃣ Channel1 设置:

  • Mode: PWM Generation CH1 and CH1N

  • Polarity: High

  • Complementary Output Polarity: High

3️⃣ 死区时间配置:

在 TIM1 设置页下:

  • 进入 Break and Dead Time 标签页:

    • Dead Time:输入你希望的死区时间,比如 100(单位大致为 ns)

    • Break Enable: 关闭(本实验用不到)

    • OSSR/OSSI:默认即可

    • Lock Level: OFF

    • Automatic Output Enable: Enable(让互补输出可用)

4️⃣ 生成代码后,Cube 会自动配置以下几个函数:

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);

注意:互补通道需要启动 PWMN,否则不会有输出!


🧪 四、代码结构(重点)

初始化 TIM1(CubeMX 生成)

htim1.Instance = TIM1;
htim1.Init.Prescaler = 71;  // 72MHz / (71+1) = 1MHz
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 999;   // PWM 频率 = 1kHz
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
HAL_TIM_PWM_Init(&htim1);

配置输出通道 1:

sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500;  // 占空比 = 50%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);

设置死区和高级功能:

sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_ENABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 100;  // 死区时间,单位为“时钟周期”
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_ENABLE;
HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig);

启动主输出:

HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);

📊 五、相关 HAL 库函数总结

函数 说明
HAL_TIM_PWM_Init() 初始化定时器的 PWM 模式
HAL_TIM_PWM_ConfigChannel() 配置某个通道的 PWM 参数(占空比、极性等)
HAL_TIMEx_ConfigBreakDeadTime() 配置死区时间、刹车功能、锁定功能
HAL_TIM_PWM_Start() 启动主通道的 PWM 输出
HAL_TIMEx_PWMN_Start() 启动互补通道(CHxN)的 PWM 输出

🧠 关键问题总结

❓ 死区时间是如何工作的?

当主通道(如 CH1)关闭时,不会立刻开启互补通道(CH1N),会等待设置的死区时间,以避免“上下桥臂同时导通”。

❓ TIM1、TIM8 为何能用互补输出?

因为 TIM1 和 TIM8 是高级定时器,硬件支持互补输出,普通定时器如 TIM2、3、4 是不支持的。

❓ 为什么我的 CH1 有输出但 CH1N 没有?

因为你可能没有调用 HAL_TIMEx_PWMN_Start(),互补通道需要单独开启!


✅ 实验结果

使用示波器连接:

  • CH1: 查看主通道 PWM 波形

  • CH1N: 查看互补通道 PWM 波形
    你会看到两个信号完全互补,中间有明确的死区延迟。


Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐