#针对PWM的学习记录,进行梳理

目录

一.PWM是什么,有什么用

二.PWM输入捕获/互补输出/输出比较功能(基于STM32)

1.输入捕获

2.互补输出

3.输出比较


一.PWM是什么,有什么用

1.PWM啥意思(结合deepseek深度思考)

PWM(脉宽调制)通过调节占空比来控制功率开关器件的导通时间,最终实现输出电压的稳定,其核心原理是 通过快速开关的周期性通断,控制能量的平均输出

 1. PWM的基本原理
    占空比(Duty Cycle:指一个周期内开关导通时间(高电平时间)与整个周期时间的比值。  
     公式:  
     占空比 = (导通时间\周期时间)*100% 
     开关频率:PWM信号的周期倒数(10Hz=表示每秒开关10次)。  
     频率越高,输出纹波越小,但开关损耗可能增加。

 2. 功率开关器件的导通控制
     功率开关器件(如MOSFET、IGBT)在导通时允许电流流过,截止时阻断电流。  
     通过PWM控制导通时间:  
     占空比大 → 导通时间长 → 平均输出电压高。  
     占空比小 → 导通时间短 → 平均输出电压低。  
     例如:  
     若输入电压为12V,占空比为50%,则平均输出电压约为6V。  
     占空比为75%时,平均输出电压约为9V。

 3. 如何实现“输出电压稳定”
    关键在于 闭环反馈控制,典型应用场景是开关电源(如BUCK、BOOST电路):  
    步骤1:采样输出电压
    通过电阻分压或传感器实时监测输出电压Vout。  
    步骤2:与参考电压比较
    将采样电压与目标参考电压(Vref,如5V)输入误差放大器,生成误差信号。  
    步骤3:动态调整占空比
    若 Vout< Vref→ 增大占空比 → 导通时间延长 → 提升输出电压。  
    若 Vout > Vref→ 减小占空比 → 导通时间缩短 → 降低输出电压。  
    步骤4:周期性调节
    PWM控制器根据误差信号实时调整占空比,直到输出电压稳定在目标值。

 4. 举例说明(BUCK降压电路)
     输入电压Vin:24V  
     目标输出电压Vout:12V  
     理论占空比:  
     D = Vout/Vin = 12/24= 50% 
     实际运行:  
     当负载突然增大 → Vout下降 → 控制器检测到误差 → 占空比增大至55% → 输出恢复12V。  
     当输入电压波动(如24V→22V)→ 占空比自动调整至更高值(如55%)以补偿输入降低的影响。

二.PWM输入捕获/互补输出/输出比较功能(基于STM32)

1.输入捕获

(STM32系列)应用于脉冲跳变沿时间测量, PWM 输入测量。选定输入通道,确定触发信号,然后设置触发信号的极性即可,因为是PWM 输入的缘故,另一路信号则由硬件配置,无需软件配置,从软件上来说,用 PWM 输入模式测量脉宽和周期更容易,付出的代价是需要占用两个捕获寄存器。

2.互补输出/输出比较(重点!常用)

应用:

• 电机控制(调节转速)。

• LED调光(调节亮度)。

• 直流调压电源(调节输出电压)。

• ⾳频信号⽣成(DAC模拟)。

通过定时器⽣成PWM信号,通常⽤于控制外部设备(如电机、LED亮度、电源开关等)。其核⼼原理是通过⽐较定时器计数器(CNT)和⽐较寄存器(CCR)的值,⽣成占空⽐可调的PWM波形。

⼯作原理

1. 计数器(CNT):定时器的计数器从0开始递增(或递减),直到达到⾃动重装载值(ARR)。

2. ⽐较寄存器(CCR):⽤⼾设置⼀个⽐较值,当CNT与CCR匹配时,触发输出电平变化。

3. 输出模式:

◦ PWM模式1:CNT < CCR时输出⾼电平,CNT ≥ CCR时输出低电平。

◦ PWM模式2:CNT < CCR时输出低电平,CNT ≥ CCR时输出⾼电平

配置步骤(以STM32为例)

1. 配置定时器时钟和预分频器。

2. 设置⾃动重装载值(ARR)决定PWM频率。

3. 设置⽐较寄存器(CCR)决定占空⽐。

4. 选择PWM模式并启动定时器。

代码实现

eg:TIM2,CH4单通道,输出比较配置见下:

void PWM_Configuration(void)
{
	 GPIO_InitTypeDef GPIO_InitStructure;
  /* TIM2 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 ;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOA, &GPIO_InitStructure);

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  
  PrescalerValue = (uint16_t) (SystemCoreClock / 24000000) - 1;
  
  RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9);  // (16MHz/2) *9 = 72MHz
  TIM_TimeBaseStructure.TIM_Prescaler = 71;       // ?????1MHz
  TIM_TimeBaseStructure.TIM_Period = 999;
  TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

  TIM_OCInitTypeDef  TIM_OCInitStructure;
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  /* PWM1 Mode configuration: Channel2 */
  
  TIM_OCInitStructure.TIM_Pulse = 0;

  TIM_OC2Init(TIM2, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);
  TIM_Cmd(TIM2, ENABLE);
 
}
void PWM_Configuration_wjtest(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef Tim2_st;
    TIM_OCInitTypeDef  TIM_OCst;
    /* Enable Clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA ,ENABLE);
    GPIO_InitStructure.GPIO_Mode = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    /* Gpio Init */
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    /* Time Config :
        in STM32F103x_data sheet, PA3 AF is TIM5_CH4 or TIM2_CH4 */
    /* Clock Enble */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    Tim2_st.TIM_Prescaler = 72-1;/* 7200-1; */  /* PSC */
    Tim2_st.TIM_CounterMode = TIM_CounterMode_Down;
    Tim2_st.TIM_Period = 100;/* 10000-1; */  /* ARR */
    Tim2_st.TIM_ClockDivision = TIM_CKD_DIV1;
    Tim2_st.TIM_RepetitionCounter = 0;  /* Only advanced Timer have. */

/* 
T = (ARR + 1) * (1 / CLK_cnt)
  = (1000 - 1 + 1) * (1 / 1MHz)
  = 1000 * (1 / 1000000 s)
  = 0.001 s
  = 1 ms
 */
    TIM_OCst.TIM_OCMode = TIM_OCMode_PWM1;  /* ?????PWM??1 */
    TIM_OCst.TIM_OutputState = TIM_OutputState_Enable; /* ?????? */
    TIM_OCst.TIM_OutputNState = TIM_OutputNState_Enable; /* ?????????? */
    TIM_OCst.TIM_Pulse = 50;/* 5000; */      /* ?????????? */
    TIM_OCst.TIM_OCPolarity = TIM_OCPolarity_Low;  /* ????????????????? */
    TIM_OCst.TIM_OCNPolarity = TIM_OCPolarity_Low; /* ????????????????????? */
    TIM_OCst.TIM_OCIdleState = TIM_OCIdleState_Set;  /* ???????????????????? */
    TIM_OCst.TIM_OCNIdleState = TIM_OCNIdleState_Reset; /* ???????????????????????? */

    /* Tim2 Init. */
    TIM_TimeBaseInit(TIM2,&Tim2_st);

    TIM_OC4Init(TIM2, &TIM_OCst);
    TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

    TIM_Cmd(TIM2, ENABLE);	
    // ????????????????????????????????
    TIM_CtrlPWMOutputs(TIM2, ENABLE);
    
}

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐