(一)简介
 PWM(Pulse Width Modulation脉宽调制)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号任然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有,要么完全无。比如我们的电压输出是5v的,那么经过改变PWM的占空比,可以达到在一定时间内输出3.3V或者1.3V的效果。

 PWM可应用于电机调速、功率调制、PID调节、通信等,配置简单、抗干扰能力强。可以通过PWM来控制LED灯的亮暗变化,可以通过PWM信号来控制无源蜂鸣器发出简单的声音以及实现功率继电器的线圈节能等。PWM用来驱动电机和调节电机转速是非常重要的内容。

PWM是脉冲宽度调制,具有两个非常重要的参数:频率和占空比。
  • 频率:PWM的频率是整个周期的倒数。
  • 占空比:占空比是指一个周期内高电平所占的比例。



(二)讲解
一般使用定时器PWM功能,都需要有以下几个步骤。
  • 使能时钟
  • 配置GPIO
  • 配置定时器
  • 配置PWM
  • 使能TIMER
  • 调整定时器输出通道占空比


如果我们要让PB0这个端口输出PWM,我们可以看一下手册PB0对应的定时器,因为PWM的输出是依赖定时器的
可以看到是TIM3_CH3
image.png

所以先使能时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  •     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  • 复制代码

    将PB0配置一下,复用推挽输出模式
    GPIO_InitTypeDef GPIO_InitStructure;
  •     GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
  •     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  •     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  •     GPIO_Init(GPIOB, &GPIO_InitStructure);
  • 复制代码

    定义定时器和PWM的结构体
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  •     TIM_OCInitTypeDef TIM_OCInitStructure;
  • 复制代码

    设置定时器的配置
    TIM_Period 为PWM的频率,TIM_Prescaler为时钟频率(72-1),TIM_CounterMode为向上计时
    TIM_TimeBaseStructure.TIM_Period = 99; // 自动重装载值,决定PWM频率
  •     TIM_TimeBaseStructure.TIM_Prescaler = 71; // 预分频值,TIM时钟频率/(PSC+1)
  •     TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
  •     TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  •     TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  • 复制代码

    设置PWM配置
    TIM_OCMode是选择定时器模式为TIM脉冲宽度调制模式2,TIM_OCPolarity输出极性为高
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  •     TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  •     TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
  •     TIM_OC3Init(TIM3, &TIM_OCInitStructure);
  • 复制代码

    使能TIM3
        // 使能TIM3 CH3的预装载寄存器
  •     TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

  •     // 使能TIM3
  •     TIM_Cmd(TIM3, ENABLE);
  • 复制代码

    我们可以创建一个函数
    里面用来设定PWM的占空比
    void PWM_SetCompare3(uint16_t Compare)
  • {
  •   TIM_SetCompare3(TIM3, Compare); // 使用TIM3的Channel 3
  • }
  • 复制代码


    (三)程序
    调用库和初始化函数我们就跳过了,直接看内容
    我们定义了一个i(uint8_t i;   //定义for循环的变量)
    然后for循环先是从0开始加i,并且用PWM_SetCompare3设置占空比,随着i越来越大,设置的占空比也越来越大,LED灯会越来越亮
    当for循环到达100之后,进入下一个for循环,从100往0减,随着i越来越小,占空比越来越小,LED越来越暗
    while (1)
  •         {
  •                 for (i = 0; i <= 100; i++)
  •                 {
  •                         PWM_SetCompare3(i);                        //依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮
  •                         Delay_ms(20);                                //延时10ms
  •                 }
  •                 for (i = 0; i <= 100; i++)
  •                 {
  •                         PWM_SetCompare3(100 - i);        //依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗
  •                         Delay_ms(20);                                //延时10ms
  •                 }
  •         }
  • 复制代码


    (四)程序演示
    示波器演示占空比的变化,即PWM的变化
    176a11954fff86df9397 -small-original.gif

    LED灯变化
    6dc8ceefe33e1218fdf0 -small-original.gif