STM32F4X 定时器PWM

STM32F4X 定时器PWM

  • 什么是PWM
  • STM32F4X PWM使用
    • GPIO引脚复用
    • STM32F4X PWM配置参数
      • 定时器PWM输出通道
      • 定时器PWM输出模式
      • 定时器PWM有效电平
      • 定时器PWM工作过程
      • 定时器PWM频率计算
    • STM32F4X PWM配置步骤
    • STM32F4X PWM配置函数

上节说到了定时器的定时功能,这节说一下定时器跟GPIO结合,输出PWM波形的功能。

什么是PWM

PWM是Pulse Width Modulation 的缩写,也叫脉冲宽度调节,PWM被广泛应用在产品中,比如常用的有LED灯调节、电机脉冲调节等。PWM有以下几个参数需要了解,分别是周期、高电平持续时间、低电平持续时间和占空比。下面就来简单了解一下PWM的概念。
STM32F4X 定时器PWM_第1张图片
T:PWM周期,周期是指高低电平的持续时间为一个周期。
T1:高电平时间
T2:低电平时间
占空比:占空比为 (高电平时间 / 周期) * 100%
比如上图中,T为1ms,T1为600us,T2为400us,那么占空比就为 600 / (1 * 1000) * 100% = 60%

STM32F4X PWM使用

GPIO引脚复用

前面的章节讲过,STM32F4X的GPIO除了用作普通的输入输出接口之外,还可以复用成其他的功能。本节就将GPIO接口复用成定时器模式,具体可以在STM32F4的数据手册中找到GPIO的复用表。下面就以PF9为例,下面的表格可以看到,STM32F4X的PF9引脚可以复用成定时器14的通道1,所以后面的例程就用定时器14的通道1来输出PWM波形。
在这里插入图片描述

STM32F4X PWM配置参数

定时器PWM输出通道

在STM32F4X中,每个定时器都会有几路PWM的输出,具体是使用哪一路的PWM要根据GPIO的复用表格进行确定,像PF9在表格中就复用成了TIM14_CH1,也就是定时器的通道1,在后面的编程中要注意通道不能用错。

定时器PWM输出模式

在定时器的PWM模式中,有两种输出模式,分别是PWM1和PWM2,这两种模式有以下区别。
STM32F4X 定时器PWM_第2张图片
TIMx_CNT表示定时器当前计数器的值
TIMx_CCRn表示捕获/比较寄存器的值

定时器PWM有效电平

有效电平通常要跟上面所说的PWM模式结合来使用,在STM32F4X中的PWM有效电平可以配置成高电平有效或者低电平有效。

定时器PWM工作过程

下面来简单讲一下STM32F4X的PWM工作过程。以PWM模式2、定时器向上计数模式和有效电平为高电平的情况来进行讲解。如下图所示

STM32F4X 定时器PWM_第3张图片
CNT代表定时器当前计数值
ARR为重装载寄存器值
CCRx为捕获/比较寄存器值
通过定时器PWM输出模式的表格可以知道,在向上计数模式和PWM2模式下,当CNTCCR时,电平有效,输出高电平。也就是上图会输出如下的PWM波形。
STM32F4X 定时器PWM_第4张图片

定时器PWM频率计算

在向上计数模式、PWM1模式和高电平有效的条件下。假设定时器时钟源为84MHZ,定时器分频系数为83(PSC),重装载值为5999(ARR),输出比较寄存器CCR为2000,通过下面公式可以算出定时器的中断频率。
Tout:定时器溢出值
Tclk:84MHZ
psc:83
arr:5999
Tout = (1 / (Tclk / (psc + 1))) * (arr + 1)
Tout等于1us中断一次
就可以算出PWM的周期为6000 * 1us = 6000us = 6ms。
而高电平的时间就为CCR * 1us = 2000us = 2ms
占空比就为2 / 6 * 100% = 33%

STM32F4X PWM配置步骤

  • 使能GPIO时钟和定时器时钟
  • 配置GPIO引脚为定时器模式
  • 配置定时器工作频率
  • 配置定时器PWM模式
  • 使能定时器
  • 如果需要可以修改PWM占空比
    经过上面的步骤就可以使用PWM功能了。

STM32F4X PWM配置函数

/*
定时器初始化函数
TIMx:定时器索引
TIM_TimeBaseInitStruct:定时器初始化结构体
*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)

/*
定时器通道初始化函数
TIMx:定时器索引
TIM_OCInitStruct:比较输出初始化结构体
*/
void TIM_OCXInit(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)

/*
定时器比较初始化寄存器设置函数
TIMx:定时器索引
Comparex:CCR值
*/
void TIM_SetComparex(TIM_TypeDef* TIMx, uint32_t Comparex)

PWM程序例程


void bsp_pwm_init(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	TIM_OCInitTypeDef TIM_OCInitStruct;
	GPIO_InitTypeDef GPIO_InitStruct;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE); // 使能定时器14时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 	//使能PORTF时钟	
	
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;           //GPIOF9
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;        //复用功能
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;      //推挽复用输出
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;        //上拉
	GPIO_Init(GPIOF,&GPIO_InitStruct);              //初始化PF9
	
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); // PF9复用成TIM14
	
	TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; // 向上计数模式
	TIM_TimeBaseInitStruct.TIM_Period = 999; // 重装值为1000 1ms中断一次
	TIM_TimeBaseInitStruct.TIM_Prescaler = 83; // 预分配值为84 即84000000/84 = 1MHZ 1us计一次书
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseInitStruct); // 初始化定时器14
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1; // PWM模式1
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; // 有效电平为高电平
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; // 使能比较输出
	TIM_OCInitStruct.TIM_Pulse = 300; // CCR值为300
	TIM_OC1Init(TIM14,&TIM_OCInitStruct);
	
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);  //使能TIM14在CCR1上的预装载寄存器
 
	TIM_ARRPreloadConfig(TIM14,ENABLE);//ARPE使能 
	TIM_Cmd(TIM14,ENABLE); // 使能定时器14
	
}


int main(void)
{
	int dir,led0pwmval = 0;
	NVIC_PriorityGroupConfig(2);
	system_tick_init();
	
	bsp_usart_init(115200);
	bsp_pwm_init();

  while(1){
		delay_ms(1);
		if(dir)
			led0pwmval++;//dir==1 led0pwmval递增
		else 
			led0pwmval--;	//dir==0 led0pwmval递减 
 		if(led0pwmval>1000)
			dir=0;//led0pwmval到达1000后,方向为递减
		if(led0pwmval==0)
			dir=1;	//led0pwmval递减到0后,方向改为递增
 
		TIM_SetCompare1(TIM14,led0pwmval);	//修改比较值,修改占空比
	  
	}
  
}

你可能感兴趣的:(STM32学习,stm32,单片机,嵌入式硬件)