学习笔记:STM32 OC输出比较(PWM)详解

一、输出比较简介

1.1 输出比较功能

  • OC(Output Compare)输出比较

  • 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置O或翻转的操作,用于输出一定频率和占空比的PWM波形

  • 每个高级定时器和通用定时器都拥有4个输出比较通道

  • 高级定时器的前3个通道额外拥有死区生成和互补输出的功能

  • 1.2 输出比较结构

            触发控制器选择时钟源后传递到定时器的TIMx的时基单元,将预分频信号传递到计数器,计数器比较寄存器比较后输出指定电平,自动重装载计数器载CNT达到一定条件后装载初值

    1.2 输出比较计算

  • PWM参数:频率={\frac{1}{T_S}},占空比={\frac{T_{ON}}{T_S}},分辨率=占空比变化的步距

  • PWM频率:Freq=CK_PSC/(PSC+1)/(ARR+1)

  • PWM占空比:Duty=CCR/(ARR+1)

  • PWM分辨率:Rese=1/(ARR+1)

  • CK_PSC为预分频时钟频率,PSC为预分频数,ARR为重载计数值,CCR为计数比较值

    1.3 输出比较模式

    模式 描述
    冻结 CNT=CCR时,REF保持为原状态
    匹配时置有效电平 CNT=CCR时,REF置有效有效电平
    匹配时置无效电平 CNT=CCR时,REF置无效电平
    匹配时电平翻转 CNT与CCR时,REF电平翻转
    强制为无效电平 CNT与CCR无效,REF强制为无效电平
    强制为有效电平 CNT与CCR无效,REF强制为有效电平
    PWM模式1 向上计数:CNT<CCR时,REF置有效电平,CNT>=CRR时,REF置无效电平;向下计数:CNT>CCR时,REF置无效电平,CNT<=CRR时,REF置有效电平
    PWM模式2 向上计数:CNT<CCR时,REF置无效电平,CNT>=CRR时,REF置有效电平;向下计数:CNT>CCR时,REF置有效电平,CNT<=CRR时,REF置无效电平

    二、输出比较函数

    2.1 输出比较单元结构体

    创建输出比较单元结构体

    TIM_OCInitTypeDef   TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);

    输出比较单元结构体变量

    typedef struct
    {
      uint16_t TIM_OCMode;        /*!< Specifies the TIM mode.
                                       This parameter can be a value of @ref TIM_Output_Compare_and_PWM_modes */
    ​
      uint16_t TIM_OutputState;   /*!< Specifies the TIM Output Compare state.
                                       This parameter can be a value of @ref TIM_Output_Compare_state */
    ​
      uint16_t TIM_OutputNState;  /*!< Specifies the TIM complementary Output Compare state.
                                       This parameter can be a value of @ref TIM_Output_Compare_N_state
                                       @note This parameter is valid only for TIM1 and TIM8. */
    ​
      uint16_t TIM_Pulse;         /*!< Specifies the pulse value to be loaded into the Capture Compare Register. 
                                       This parameter can be a number between 0x0000 and 0xFFFF */
    ​
      uint16_t TIM_OCPolarity;    /*!< Specifies the output polarity.
                                       This parameter can be a value of @ref TIM_Output_Compare_Polarity */
    ​
      uint16_t TIM_OCNPolarity;   /*!< Specifies the complementary output polarity.
                                       This parameter can be a value of @ref TIM_Output_Compare_N_Polarity
                                       @note This parameter is valid only for TIM1 and TIM8. */
    ​
      uint16_t TIM_OCIdleState;   /*!< Specifies the TIM Output Compare pin state during Idle state.
                                       This parameter can be a value of @ref TIM_Output_Compare_Idle_State
                                       @note This parameter is valid only for TIM1 and TIM8. */
    ​
      uint16_t TIM_OCNIdleState;  /*!< Specifies the TIM Output Compare pin state during Idle state.
                                       This parameter can be a value of @ref TIM_Output_Compare_N_Idle_State
                                       @note This parameter is valid only for TIM1 and TIM8. */
    } TIM_OCInitTypeDef;
  • TIM_OCMode:输出比较模式

  • 参数 作用
    TIM_OCMode_Timing 冻结模式
    TIM_OCMode_Active 匹配时置有效电平
    TIM_OCMode_Inactive 匹配时置无效电平
    TIM_OCMode_Toggle 匹配时电平翻转
    TIM_OCMode_PWM1 PWM模式1
    TIM_OCMode_PWM2 PWM模式2
  • TIM_OutputState:输出比较状态

  • 参数 作用
    TIM_OutputState_Disable 失能
    TIM_OutputState_Enable 使能
  • TIM_OCPolarity:输出比较极性

  • 参数 作用
    TIM_OCPolarity_High 高极性,有效电平是高电平
    TIM_OCPolarity_Low 低极性,有效电平是低电平
  • TIM_Pulse:脉冲值,CCR寄存器的值,0x0000~0xFFFF

  • 最后比较输出通道初始化

    TIM_OC1Init(TIM2, &TIM_OCInitStructure);

    2.2 输出比较单元初始化

    void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);

    TIMx为定时器,TIM_OCInitStruct为输出比较单元结构体变量

    2.2 输出比较默认初始化

    void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);

    将TIM_OCInitStruct变量按默认初始化

    2.3 强制输出模式

    void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

    强制输出电平

    2.4 输出比较寄存器预装

    void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

    2.6 配置输出比较通道极性

    void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

    2.7 配置输出比较互补通道极性

    void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);

    2.8 修改输出比较模式

    void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);

    2.9 修改输出比较寄存器值

    void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare);

    修改指定定时器TIMx的通道1CH1的输出比较值,如果要修改其他通道的输出比较值可用

    TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t compare);
    TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t compare);
    TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t compare);

    一个通用定时器可同时输出4路相同频率、不同占空比的PWM

    2.10 使能PWM主输出

    void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);

    仅高级定时器使用

    三、输出比较程序

    3.1 开启时钟总线

    开启定时器TIM4、GPIOB端口和复用IO的时钟总线

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    3.2 GPIO初始化

    根据数据手册查看定时器复用引脚,需要采用复用推挽输出

    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    3.3 配置TIM定时器

    为定时器TIM4选择内部时钟

    TIM_InternalClockConfig(TIM4);

    设置定时器TIM4的时基单元,选择时基单元预分频值为720,内部时钟单元频率为72MHz,预分频后为100KHz,选择计数周期(值)为100,输出比较频率为1KHz

    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;     //向上计数模式
    TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;                     //计数周期(值)
    TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;                  //预分频 
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;    

    使用时基单元结构体给TIM4初始化

    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);

    3.4 配置OC单元

    输出比较单元输出模式为PWM1模式,输出有效极性为高电平,输出状态为使能,输出比较值为50,意味当TIM计数器值大于50时输出高电平,小于50时输出低电平,由于计数周期为100,所以占空比为50%

    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;       
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;   
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 50; 

    OC单元结构体初始化

    TIM_OC1Init(TIM4, &TIM_OCInitStructure);

    开启TIM使能

    TIM_Cmd(TIM4, ENABLE); 

    3.5 例程

    该例程可以使GPIOB的GPIO_Pin_6输出占空比为50%,如需修改占空比则可以使用TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)函数修改

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
        
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;       
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
        
    TIM_InternalClockConfig(TIM4);                          
        
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; 
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 
    TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;     
    ​
    TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;      
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;    
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStructure);
        
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_OCStructInit(&TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;           
    ​
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;   
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 50; 
    TIM_OC1Init(TIM4, &TIM_OCInitStructure);
        
    TIM_Cmd(TIM4, ENABLE); 

    物联沃分享整理
    物联沃-IOTWORD物联网 » 学习笔记:STM32 OC输出比较(PWM)详解

    发表评论