STM32输出PWM波形进行比较

PWM配置

  • Introduction
  • START
  • END
  • Parameter selection
  • TIM_OCMode
  • TIM_OCPolarity
  • TIM_OutputState
  • TIM_Pulse
  • 引脚重映射
  • Introduction

    STM32定时器输出比较功能,主要用来输出PWM波形,应用在包含有电机的项目中,如智能车、机器人等;

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

    在右下部分,CNT是时基单元里面的计数器;CCR是捕获/比较寄存器,它是输入捕获和输出比较共用的,当使用输入捕获时,它就是捕获寄存器,当使用输出比较时,它就是比较寄存器。请添加图片描述
    红框里的电路会比较CNT和CCR的值,CNT计数自增,CCR是我们给定的一个值,当CNT>CCR、CNT<CCR、CNT=CCR时,输出端TIMx_CH1就会对应置1、置0、置1、置0,这样就可以输出一个电平不断跳变的PWM波形了。


    PWM波形是一个数字输出信号,由高低电平组成,通过不断调整PWM波形可以等效地实现一个模拟信号的输出。比如可以使用PWM波形来实现呼吸灯的效果,通过让LED不断点亮、熄灭、点亮达到一定频率时,LED就不会闪烁而是呈现出一个中等亮度,调整点亮和熄灭的时间比例就能让LED呈现出不同的亮度。

    占空比50%就是高低电平时间相等的方波,占空比20%就是高电平占20%低电平占80%。占空比决定了PWM等效出来的模拟电压大小,占空比越大等效的模拟电压就越趋近于高电平,占空比越小等效的模拟电压就越趋近于低电平,等效关系一般是线性的,比如高电平是5V,低电平是0V,那50%占空比等效于中间电压,就是2.5V。

    分辨率它等于占空比变化步距,如占空比按1%、2%、3%这样的变化就是分辨率为1%。

    START

    Step1. 开启外设时钟
    把要使用的外设时钟打开,RCC开启TIM和GPIO外设时钟

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    

    Step2. 配置GPIO
    使用PA0输出PWM波形

        GPIO_InitTypeDef GPIO_Initstructure;
    	GPIO_Initstructure.GPIO_Mode=GPIO_Mode_AF_PP;//配置为复用推挽输出
    	GPIO_Initstructure.GPIO_Pin=GPIO_Pin_0;
    	GPIO_Initstructure.GPIO_Speed=GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_Initstructure);
    

    Step3. 配置时基单元
    配置时基单元,包括这前面的时钟源选择

        TIM_InternalClockConfig(TIM2);
    
        TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
    	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
    	TIM_TimeBaseInitStructure.TIM_Period=100-1;//ARR
    	TIM_TimeBaseInitStructure.TIM_Prescaler=720-1;//PSC
    	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;
    	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
    

    Step4. 配置输出比较单元
    配置输出比较单元,CCR的值、输出比较模式、极性选择、输出使能

        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//用来设置CCR的
    	TIM_OC1Init(TIM2, &TIM_OCInitStructure);
    

    PWM参数计算

    假如要产生一个频率为1Khz,占空比为50%,分辨率为1%的PWM波形
    由公式可得ARR+1=100,CCR=50,PSC+1=720,CK_PSC为固定72MHz。

    Step5. 开启计数器
    运行控制,启动计数器

        TIM_Cmd(TIM2,ENABLE);
    

    END

    检查

    void PWM_SetCompare1(uint16_t Compare)
    {
    	TIM_SetCompare1(TIM2,Compare);//单独更改通道1CCR的值
    }
    

    调用上面函数可以改变CCR的值进而影响PWM波形占空比,由于使用A0口输出PWM波形,所以就使用A0口实现呼吸灯。
    记得在main函数中初始化PWM,在while循环里面调用下面代码即可。

    for(i=0;i <=100;i++)
    		{
    			PWM_SetCompare1(i);
    		    Delay_ms(10);
    	    }
    		for(i=0;i <=100;i++)
    		{
    			PWM_SetCompare1(100-i);
    		    Delay_ms(10);
    	    }
    

    Parameter selection

    在stm32f10x_tim.h文件
    TIM_OCInitTypeDefTIM输出比较初始化结构体定义

       typedef struct
        {
        uint16_t TIM_OCMode;       //输出比较模式
        uint16_t TIM_OutputState;  
        uint16_t TIM_OutputNState;  
        uint16_t TIM_Pulse;        
        uint16_t TIM_OCPolarity;   
        uint16_t TIM_OCNPolarity;   
        uint16_t TIM_OCIdleState;  
        uint16_t TIM_OCNIdleState;  
        } c
    

    TIM_OCMode


    解释 & 说明

    #define TIM_OCMode_Timing     //冻结模式              
    #define TIM_OCMode_Active     //相等时置有效电平            
    #define TIM_OCMode_Inactive   //相等时置无效电平             
    #define TIM_OCMode_Toggle     //相等时电平翻转           
    #define TIM_OCMode_PWM1       //PWM模式1             
    #define TIM_OCMode_PWM2       //PWM模式2             
    


    输出模式控制器的输入是CNT和CCR的大小关系,输出是REF的高低电平,输出模式可以根据下面的TIMx_CCMR1寄存器进行配置。
    冻结模式,不再管CNT和CCR,直接REF保持不变,维持上一个状态,比如正在输出PWM波,突然想暂停一会儿输出,就可以设置成冻结模式,该模式下输出的高低电平也保持在暂停时刻状态不变化;
    匹配时置有效电平、无效电平、电平翻转为高级定时器里说法,可以认为匹配时置有效电平就是置高电平,无效就是低电平。匹配时电平翻转可以方便地输出一个频率可调,占空比始终为50%的PWM波形。
    PWM模式1可以输出频率和占空比都可调的PWM波形

    **原因是:**CNT不断计数运行,CCR是自己设定,同时他们两个会不断比较,CCR后面是输出模式控制器。观察右上图,蓝色线是CNT的值,黄色线是ARR的值,蓝色线从0开始自增,一直增到ARR到99,之后清零继续自增,红色线是CCR,假如CCR为30,CNT<30时下面绿色为输出,它会输出高电平,CNT>30就会输出低电平。所以通过改变CCR就可以改变PWM占空比

    TIM_OCPolarity

    #define TIM_OCPolarity_High                ((uint16_t)0x0000)
    #define TIM_OCPolarity_Low                 ((uint16_t)0x0002)
    #define IS_TIM_OC_POLARITY(POLARITY) (((POLARITY) == TIM_OCPolarity_High) || \
                                          ((POLARITY) == TIM_OCPolarity_Low))
    

    TIM_OCPolarity_High高极性,就是极性不翻转,REF波形直接输出或者说是有效电平是高电平,REF有效时,输出高电平;
    TIM_OCPolarity_Low低极性,就是REF电平取反,或者说是有效电平为低电平;

    TIM_OutputState

    输出状态使能或者失能

    #define TIM_OutputState_Disable            ((uint16_t)0x0000)
    #define TIM_OutputState_Enable             ((uint16_t)0x0001)
    #define IS_TIM_OUTPUT_STATE(STATE) (((STATE) == TIM_OutputState_Disable) || \
                                        ((STATE) == TIM_OutputState_Enable))
    

    TIM_Pulse

    pulse 脉冲,用来设置CCR寄存器值的
    参数可以为0~FFFF之间的一个值,就是16位的范围

    引脚重映射



    在引脚表中可以可以看到TIM2的CH1可以从PA0挪到PA15引脚上
    引脚重映射需要开启AFIO时钟,以及引脚重映射配置函数

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
    


    没有重映射,PA0、PA1、PA2、PA3还是他们;
    部分重映射,PA0->PA15,PA1->PB3,其他不变;
    部分重映射,PA2->PB10,PA3->PB11,其他不变;
    全部重映射,全部都变。

    在stm32f10x_gpio.c里面可以看到TIM2有部分重映射1、部分重映射2和完全重映射
    选择部分重映射1

    GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
    

    还需注意PA15端口它是调试端口JTDI,如果想让PA15作为普通GPIO或者复用定时器的通道,应该先关闭调试端口复用。

    第一个是解除NJTRST,PB4当作GPIO口使用;
    第二个是解除JTAG调试端口复用,PA15、PB3、PB4变回GPIO;
    第三个是解除SWD和JTAG的调试端口,PA15,14,13、PB3、PB4变回GPIO;
    第三个使用有风险,使用后STLINK就无法下载程序了,这个时候只能使用串口下载程序了。

    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    

    总结
    如果想把PA15、PB3、PB4当作GPIO使用,需要下面第一行和第三行;
    如果想重映射定时器或者其他外设的复用引脚,需要下面第一行和第二行;
    如果上面都想,就使用下面三行代码;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
    GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    

    注意调用上面程序后,GPIO初始化需要把PA0改成PA15。

    同一个定时器不同通道输出PWM的特点
    对于同一个定时器的不同通道输出的PWM,它们的频率,因为不同的通道是共用应该计数器的,使用他们的频率是一样的。他们的占空比由各自的CCR决定,所以占空比可以各自设定,还有他们的相位,由于计数器更新,所有PWM会同时跳变,因此他们的相位是同步的。
    如果驱动多个舵机或者直流电机,使用一个定时器不同通道的PWM,就完全可以。

    作者:qq_52658815

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32输出PWM波形进行比较

    发表回复