STM32定时器使用教程:生成PWM波形

  1. 输出比较(OC)功能介绍
  2. pwm的介绍
  3. 输出比较通道的基本结构,以及pwm实现步骤
  4. 相关函数介绍
  5. 目标及代码

一、输出比较(OC)功能介绍

1.介绍:OC(Output Compare)输出比较,通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形(需要使用此功能输出pwm波)

2.资源说明:每个高级定时器和通用定时器都拥有4个输出比较通道,高级定时器的前3个通道额外拥有死区生成和互补输出的功能


二、pwm的基本结构,以及实现步骤

1.介绍:pwm(脉宽调制)利用微处理器的数字输出对模拟电路进行控制的一种技术,通过改变脉冲宽度改变电压的输出(改变高电平和低电平的时间,实现改变平均电压,可以控制led灯的亮度,马达转速,舵机等等)

2.pwm的相关参数

  • 频率 = 1 /T        这个不用多说就是一个周期的倒数 
  • 占空比 = T'(高电平时间)/ T        高电平的时间毕上一个周期
  • 分辨率 = 占空比变化步距        比如占空比从1%,2%…这样变化,分辨率就是1%

  • 三、输出比较通道的基本结构,以及pwm实现步骤

    1.输出比较通道的基本结构见下图

  • 大致原理是通过配置输出模式控制器,然后比较CNT与CCR的值实现电平的操纵。配置完成后信号会输出到对应的通道
  • 我们要实现pwm选择任意一个pwm模式就行(这里选择pwm模式1,向上计数。下图)
  • 2.实现pwm的基本结构

  • 如图所示,实现pwm需要以下的步骤:RCC配置需要的时钟–>配置好开启的时基单元和需要用到的GPIO口(GPIO改成复用推挽输出,将控制权交给片上外设的通道)–>配置输出比较单元–>使用TIM_Cmd运行
  • 3.关于pwm的参数计算

  • 如图所示,参数的计算与时基单元(上一节有介绍)有关
  • 图中CNT一直增加到ARR(99)总共计了100次数,CCR设置为30
  • 由图知pwm的频率对应着计数器更新频率
  • 在CNT<CCR是时间内为高电平可以推出占空比
  • ARR越大,CCR打范围就越大,对应的分辨率就越高

  • 四、相关函数介绍

  • TIM_InternalClockConfig:开启对应的定时器
  • TIM_OC1Init初始化输出比较单元(需要结构体参数,配置五),因为输出比较单元有4个,所以数字1改成2、3就可以配置别的输出比较单元
  • TIM_OCStructInit:结构体初始化
  • TIM_CCxCmd与TIM_CCxNCmd:单独修改输出使能
  • TIM_SetCompare1:单独修改通道1CCR的值
  • 注:PWM的输出需要使用GPIO口,具体那个GPIO能用记得查引脚定义表

  • 五、目标及代码

    1.使用pwm配置led呼吸灯

  • 第一步,RCC配置
  • 	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//这里用的Tim2,是APB1的外设
    
        /*注意pwm的输出波形输出在PA0上,这里再初始一下GPIOA*/
    	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//配置PA0,让它能输出pwm波
  • 第二步,配置时基单元,和需要的GPIO口
  •     /*配置时基单元*/
    	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);//需要结构体参数,记得取地址符
    
        /*配置GPIO*/
    	GPIO_InitTypeDef GPIO_InitStruture;
    	GPIO_InitStruture.GPIO_Mode = GPIO_Mode_AF_PP;//改成复用推挽输出,将控制权交给片上外设TIM2的CH1通道
    	GPIO_InitStruture.GPIO_Pin = GPIO_Pin_0;//在PA0上输出pwm波
    	GPIO_InitStruture.GPIO_Speed = GPIO_Speed_50MHz;
    	GPIO_Init(GPIOA,&GPIO_InitStruture);
  • 第三步,配置输出比较单元
  •     /*配置结构体的时候有很多参数(带n的参数,ldleState的...)是高级定时器才用的,这里只配置了一些用的到的*/
    	TIM_OCInitTypeDef TIM_OCInitStruct;
    	TIM_OCStructInit(&TIM_OCInitStruct);//给结构体赋初始值,防止有的参数每赋值出现问题
    	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;//模式,pwm1
    	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;//极性,决定有效电平是高是低
    	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable;//输出使能
    	TIM_OCInitStruct.TIM_Pulse = 50;//CCR,如果将ARR+1配成100,那占空比就是CCR%
    	TIM_OC1Init(TIM2,&TIM_OCInitStruct);
  • 第四步,Cmd运行
  • TIM_Cmd(TIM2,ENABLE);
  • 为了实现呼吸灯程序,还需要一个函数实现CCR值的不断改变
  • /**
      *@brief    更改CCR即更改pwm占空比
      *@param CCR值
      *@retval  无
      */
    void PWM_SetCompare1(uint16_t Compare)
    {
    	TIM_SetCompare1(TIM2,Compare);//CCR更改位Compare,注意第一个参数
    }
  • 主函数如下,其他.h文件前几节都有,pwm的.c文件啥的再写一下就可以了
  • #include "stm32f10x.h"                  // Device header
    #include "Delay.h"
    #include "OLED.h"
    #include "pwm.h"
    
    uint8_t i;
    
    int main(void)
    {
    	pwm_Init();
    	while(1)
    	{
    		/*占空比升高变亮*/
    		for(i=0;i<=100;i++)
    		{
    			PWM_SetCompare1(i);
    			Delay_ms(10);//防止过快不明显
    		}
    		/*占空下降高变暗*/
    		for(i=100;i>0;i--)
    		{
    			PWM_SetCompare1(i);
    			Delay_ms(10);
    		}
    	}
    }
    

    作者:numbers0410

    物联沃分享整理
    物联沃-IOTWORD物联网 » STM32定时器使用教程:生成PWM波形

    发表回复