STM32定时器PWM输出原理与配置


一、PWM是什么?

        脉冲宽度调制(PWM),利用微处理器的数字输出来对模拟电路进行控制。

1.PWM工作过程

        上一节说过,向上计数从0到ARR(自动装载值)产生中断。那么如何在计数过程中用到PWM呢?

        下图是向上计数,计数器在计数时,捕获比较寄存器(CCRx)和计数器的值相比较,当CCRx > 计数器的值就为低电平,CCRx < 计数器的值就为高电平(根据CCER寄存器来配置是高电平有效还是低电平有效),计数器的值到达ARR的值时,开始重装载,以此来循环。

2.PWM总结

        PWM模式(脉冲宽度调制模式)可以生成一个信号,该信号频率是由TIMx_ARR寄存器的值来决定的,其占空比则是由TIMx_CCRx寄存器值决定。

        PWM模式1:向上计数时,TIMx_CNT<TIMx_CCR1时,通道1为有效电平,否则为无效电平;在向下计数时,TIMx_CNT>TIMx_CCR1时,通道1为无效电平,否则为有效电平。

        PWM模式2:向上计数时,TIMx_CNT<TIMx_CCR1时,通道1为无效电平,否则为有效电平;在向下计数时,TIMx_CNT>TIMx_CCR1时,通道1为有效电平,否则为无效电平。

二、PWM编程流程(HAL库)

        

        1.开启TIM3和GPIO时钟

        __HAL_RCC_TIM3_CLK_ENABLE();

        __HAL_RCC_GPIOB_CLK_ENABLE();                // 复用的时候用

        2.初始化PWM时基参数

        HAL_TIM_PWM_Init();

        3.初始化PWM通道参数

        HAL_TIM_PWM_ConfigChannel();

        4.使能定时器PWM

        HAL_TIM_PWM_Start();

        5.配置IO口复用映射

        HAL_GPIO_Init();

      

三、小实验程序要求

        使用定时器PWM功能,输出占空比可变的PWM波,用来驱动LED灯,从而达到LED亮度由暗变亮,又从亮变暗,如此循环。

四、代码实现 

        tip:1.PB0和PB1为小灯,PB1的话我们需要用复用TIM3_CH4(第4频道);

                2.在TIM3_PWM_Init()里占空比是固定的,所以创建TIM3_PWM_SetValue函数改变占空比的值。

1.pwm.h

#ifndef __PWM_H
#define __PWM_H

#include "sys.h"

void TIM3_PWM_Init(void);
void TIM3_PWM_SetValue(TIM_HandleTypeDef *htim, uint32_t value);
extern TIM_HandleTypeDef TIM3_PWM_Struct;

#endif

2.pwm.c

#include "pwm.h"

TIM_HandleTypeDef TIM3_PWM_Struct;   // TIM_PWM句柄
TIM_OC_InitTypeDef TIM3_OC_Sturct;   // TIM_OC句柄

void TIM3_PWM_Init()         // PWM初始化
{

    TIM3_PWM_Struct.Instance = TIM3;
    TIM3_PWM_Struct.Init.Prescaler = 90 - 1;                  // 预分频系数  
    TIM3_PWM_Struct.Init.Period = 500 - 1;                     // 自动装载值  
    TIM3_PWM_Struct.Init.CounterMode = TIM_COUNTERMODE_UP;      // 计数模式:向上计数

    HAL_TIM_PWM_Init(&TIM3_PWM_Struct);                     // TIM_PWM初始化

    TIM3_OC_Sturct.OCMode = TIM_OCMODE_PWM1;                // 选择PWM1,还是PWM2
    TIM3_OC_Sturct.Pulse = 250;                             // 占空比:为Period(ARR)一半
    TIM3_OC_Sturct.OCPolarity = TIM_OCPOLARITY_LOW;         // 因为小灯是低电平有效 选择低电平

    HAL_TIM_PWM_ConfigChannel(&TIM3_PWM_Struct, &TIM3_OC_Sturct, TIM_CHANNEL_4);    // 初始化PWM通道参数
    
    HAL_TIM_PWM_Start(&TIM3_PWM_Struct, TIM_CHANNEL_4);     // 使能定时器PWM

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{

    if (htim->Instance == TIM3)
    {
        
        GPIO_InitTypeDef GPIO_Struct;           // GPIO句柄
        
        GPIO_Struct.Pin = GPIO_PIN_1;           // PB1
        GPIO_Struct.Mode = GPIO_MODE_AF_PP;     // 推挽输出
        GPIO_Struct.Pull = GPIO_PULLUP;         // 上拉
        GPIO_Struct.Speed = GPIO_SPEED_FAST;    // 高速
        GPIO_Struct.Alternate = GPIO_AF2_TIM3;  // 复用为TIM3

        HAL_GPIO_Init(GPIOB, &GPIO_Struct);  

        __HAL_RCC_TIM3_CLK_ENABLE();            // TIM3时钟使能
        __HAL_RCC_GPIOB_CLK_ENABLE();           // GPIOB时钟使能

    }

}

void TIM3_PWM_SetValue(TIM_HandleTypeDef *htim, uint32_t value)      // 改变PWM占空比的值
{

    htim->Instance->CCR4 = value;                        // 占空比大亮度亮,占空比小亮度暗

}

3.main.c

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "pwm.h"


int main(void)
{

    uint8_t direction = 1;          // 方向(判断转向)
    uint32_t led_pwm_value = 0;     // PWM占空比的值

    HAL_Init();                     // 初始化HAL库   
    Stm32_Clock_Init(360,25,2,8);   // 设置时钟,180Mhz
    delay_init(180);                // 初始化延时函数
    uart_init(115200);              // 初始化USART
    LED_Init();                     // 初始化LED 
    TIM3_PWM_Init();                // 初始化PWM3
	
	while (1)
    {
        
        delay_ms(10);
        if (direction)              // 判断方向
        {
            led_pwm_value++;
        }
        else
        {
            led_pwm_value--;
        }

        if (led_pwm_value > 400)    // 值最好不要超过Period(ARR)的值
        {
            direction = 0;
        }
        
        if (led_pwm_value == 0)
        {
            direction = 1;
        }

        TIM3_PWM_SetValue(&TIM3_PWM_Struct, led_pwm_value);
        
    }
    

}

### STM32 定时器配置实现互补 PWM 输出 #### 了解 PWM 和互补 PWM 的概念 脉宽调制 (PWM) 是一种用于控制功率传输的技术,在不改变信号频率的情况下通过调整占空比来调节输出电压或电流水平[^1]。 对于互补 PWM,两个通道的波形始终相反。当一个通道处于高电平时,另一个通道则保持低电平;反之亦然。这种特性常被应用于电机驱动、逆变电源等领域。 #### 配置 TIM1 实现 CH1 及其反相通道 CH1N 的互补 PWM 输出 为了使能并正确设置定时器以生成互补 PWM 波形: - **初始化 GPIO** - 将 PE8 设置为 TIM1_CH1 复用推挽输出模式。 - 同样地, 将 PE9 设定为 TIM1_CH1N 复用开漏输出模式。 - **配置定时器参数** - 使用向上计数方式。 - 自动重装载预分频系数设定合适的周期值。 - 死区时间是为了防止上下桥臂直通而引入的安全间隔。 - 对于 TIM1,可以通过修改 BDTR 寄存器中的 Dead-Time Generator 来定义具体的时间长度。 - **启动 PWM 模式** - 在 TIM1_CCER 中分别指定 CH1 和 CH1N 工作在 PWM1 或者 PWM2 方向。 - 确认 OCxM 字段指定了相应的 PWM 类型(如图所示),并且 OcxPE=1 表明该比较事件有效。 ```c // 初始化GPIO端口 void MX_GPIO_Init(void){ __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_9; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // 推挽复用 GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(GPIOE,&GPIO_InitStruct); } // 配置TIM1定时器 static void MX_TIM1_PWM_Config(void){ TIM_MasterConfigTypeDef sMasterConfig = {0}; TIM_OC_InitTypeDef sConfigOC = {0}; htim1.Instance = TIM1; // 基本定时器参数配置... ... // 配置CH1及其负逻辑(NOT)版本CH1N作为互补PWM输出 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = ARR_VALUE / 2 ; // 初始50%占空比 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCNPolarity = TIM_OCNPOLARITY_LOW; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET ; sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_SET ; HAL_TIM_PWM_ConfigChannel(&htim1 ,&sConfigOC,TIM_CHANNEL_1); // 开启死区发生器 __HAL_TIM deadtime_config(TIM_HandleTypeDef *htim,uint32_t DeadTimeValue) } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值