STM32定时器输出比较技术详解

文章目录

  • 一、输出比较简介
  • 通用定时器输出比较部分电路
  • 输出模式寄存器
  • 二、PWM
  • PWM简介
  • PWM基本结构
  • 三、配置PWM
  • 函数介绍
  • 配置PWM波形输出端口
  • 一、输出比较简介

    OCOutput Compare)输出比较
    输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形
    每个高级定时器和通用定时器都拥有4个输出比较通道
    高级定时器的前3个通道额外拥有死区生成和互补输出的功能

    通用定时器输出比较部分电路


    工作流程
    最左边是寄存器CNT和CCR1的捕获比较寄存器,CNT≥CCR1时(需提前配置好CCR1中的值,使用结构体变量配置CCR1,也可函数单独配置
    给输出模式控制器传递信号,控制器再给OC1ref(reference即参考信号)传递高低电平;
    REF主要走下路,通过极性选择后(写0,走上路保持原电平;写1,走下路电平取反;故配置OC模式时,需选择极性,使用结构体变量配置极性);
    输出使能电路选择是否输出(CC1E给输出使能电路写值;故配置OC模式时,需使能OC电路,使用结构体变量使能电路);
    最后到达OC1引脚,到达GPIO口。

    输出模式寄存器


    冻结:CNT和CCR无效,REF保持原状态。
    匹配时置有效电平和无效电平,分别是指高低电平。(信号是一次性的,不适合输出连续变化的波形;如置配置时置有效电平模式,满足条件后,信号一直保持有效电平)
    配置时电平翻转:可以形成一个50占空比的PWM波形。
    强制为无效或有效电平,和冻结模式类似,只是指定了冻结后的高低电平,如果想暂停输出波形,并且在暂停期间置高低电平,可以选择此模式。
    PWM1和PWM2,一般使用向上计数,二者只是极性不同,通常使用PWM1。
    输出模式和选择极性都可以配置信号极性,非常灵活。(即PWM模式选择改变极性;结构体配置选择极性时,也可改变)

    二、PWM

    PWM简介

    PWM(Pulse Width Modulation)脉冲宽度调制
    具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速等领域。

    PWM参数:
    频率 = 1 / TS
    占空比 = TON / TS
    分辨率 = 占空比变化步距

    PWM基本结构


    红线为CCR值,黄线为ARR,蓝线为CNT。
    以PWM1为例,当CNT<ARR时高电平,>时,为低电平。

    三、配置PWM

    第一步:RCC开启时钟,打开我们要用的TIM,GPIO外设的时钟打开。
    第二步:配置时基单元。
    第三步:配置输出比较单元,包括CCR的值,输出比较模式,极性选择,输出使能这些参数
    第四步:配置GPIO位复用推挽输出。
    第五步:运行控制。启动计数器。

    函数介绍

    承接上节函数介绍,将继续介绍,与TIM输出比较相关的函数的作用。

    初始化TIM输出比较功能 (OC1-4分别为定时器的四个通道)

    void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);//重要 参数1:选择定时器;参数2:结构体配置具体功能
    void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
    

    结构体赋默认值

    void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
    

    配置强制输出模式

    void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
    void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
    void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
    void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
    

    配置CCR寄存器的预装功能(预装功能上节有讲,不在叙述;OC1-4分别表示4个输出/捕获通道)

    void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
    

    配置快速使能

    void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
    void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
    void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
    void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
    

    外部事件时清除REF信号

    void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
    void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
    void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
    void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
    

    单独设置输出比较极性的(N是指高级定时器的互补通道,结构体初始化也可以设置极性,一般来说结构体里的参数都可以用函数来单独修改的)。

    void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
    void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
    void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
    void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
    void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
    void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
    void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
    

    来单独修改输出使能参数的

    void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);//
    void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);
    

    单独修改输出比较模式的

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

    单独配置CCR的值的

    void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);
    void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
    void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
    void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);
    

    仅高级定时器使用,当高级定时器输出PWM时,调用此函数,使能主输出,否则无法正常输出PWM。

    void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);
    

    TIM配置代码

    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    	TIM_InternalClockConfig(TIM2);
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;
    	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
    	TIM_TimeBaseInitStruct.TIM_Period=10000;//ARR
    	TIM_TimeBaseInitStruct.TIM_Prescaler=7200-1;//PSC
    	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
    	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
    	//以上为配置时基单元的部分,详看上节
    	
    	TIM_OCInitTypeDef TIM_OCInitStructure;//结构体赋初值,下面再更改我们需要用的值,结构体变量中有很多高级定时器的功能,我们暂不需要,调用函数设默认值即可
    	TIM_OCStructInit(&TIM_OCInitStructure);
    	
    	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//配置为PWM模式1
    	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//极性选择
    	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//配置使能
    	TIM_OCInitStructure.TIM_Pulse=;//配置CCR的值(可提前配置,PWM则保持一个固定的占空比;也可后续调用函数更改,改变PWM的占空比)
    	
    	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//将TIM2中OC1配置为上述模式
    	
    	TIM_Cmd(TIM2,ENABLE );//打开定时器2
    

    PWM频率 Freq=CK_PSC/(PSC+1)/(ARR+1)
    PWM占空比 Duty=CCR/(ARR+1)
    PWM分辨率Reso=1/(ARR+1)

    产生一个频率为1KHZ,占空比50%,分辨率为1%PWM波形
    得:ARR=100;CCR=50;PSC=720;

    配置PWM波形输出端口

    配置OC1借用的GPIO口

    再STM32最小系统板中,TIM2的CH1和ETR都复用在PA0引脚上,故使用TIM2的CH1只能在PA0输出。


    若两个引脚冲突,可使用重定义功能(引脚重映射),如图中TIM2的CH3,只能重映射到指定位置的引脚

    GPIO配置代码

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    	
    	GPIO_InitTypeDef GPIO_InitStruct;
    	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出模式,将控制权转交给片上外设。
    	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
    	GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
    	
    	GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    void PWM_SetCompare1(uint16_t n)
    {
    	TIM_SetCompare1(TIM2,n);//单独更改PWM占空比
    }
    
    //主程序 while中
    for (i = 0; i <= 100; i++)
    		{
    			PWM_SetCompare1(i);			//依次将定时器的CCR寄存器设置为0~100,PWM占空比逐渐增大,LED逐渐变亮
    			Delay_ms(10);				//延时10ms
    		}
    		for (i = 0; i <= 100; i++)
    		{
    			PWM_SetCompare1(100 - i);	//依次将定时器的CCR寄存器设置为100~0,PWM占空比逐渐减小,LED逐渐变暗
    			Delay_ms(10);				//延时10ms
    		}
    
    

    延时函数的作用是,防止LED变化过快,人眼无法捕捉现象(呈现出一平均值,设置为0-100占空比,若没有延时函数,平均值为50),故暂定一段时间。

    作者:啊?啊?啊?

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32定时器输出比较技术详解

    发表评论