STM32定时器输出PWM

一、PWM

1.定义
英文全称:PULSE WIDTH MODULATION,脉冲宽度调制。
脉冲:频率,方波
宽度:占空比(duty),高电平的宽度

2.用途
(1)控制输出的电压和电流
(2)灯光的亮度
(3)电机

二、编程细节

PWM输出是没有中断触发的,PWM由硬件输出波形,用了中断反而会影响系统定时的效率。

所以,记住以后使用定时器输出PWM都不需要使用到中断

1.如配置STM32F407的TIM14的通道1,10ms即100Hz.

1ms = 0.01s=100HZ
84000000 /8400 = 10000
10000/x = 100
x=100
得到周期8400-1,分频系数10-1

基本配置如下
在这里插入图片描述

2.然后还要再配置定时器的输出功能,可以参考固件库手册的例子TIM_PWMOutPut
这里涉及到了一个寄存器
TIMx_CCMR1:capture/compare mode register 1 --捕获/比较模式寄存器1
在这里插入图片描述
从上图可以看出,我们设置占空比是可以动态调整的,关键就在于设置中间这个比较值的大小。
我们会使用到下面这个函数设置TIMx通道1比较值函数,如果使用到通道2,改1为2即可。
假如100hz内,比较值设置为80hz,那么0-79为高电平,80-100为低电平。

void TIM_SetCompare1(TIM_TypeDef* TIMx,uint16_t Comarex);

	/* PWM1 Mode configuration: Channel1 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//pwm模式1,解释如上图所示
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//允许输出
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//有效的时候,输出高电平
	TIM_OC1Init(TIM14, &TIM_OCInitStructure);
	
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);//因为要周期性输出,所以要自动重装载初值,不断输出PWM脉冲
	TIM_ARRPreloadConfig(TIM14,ENABLE);//自动重载使能

3.下面讲一下设置gpio的注意事项
(1)将引脚设置为复用功能
(2)将引脚与定时器进行绑定,告知是复用定时器功能

GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM14)

(3)最好是按照固件库手册的例程来写,有些定时器使能需要配置下面这个函数

TIM_CtrlPWMOutputs(TIM1,ENABLE)

4.主函数部分

uint32_t pwm_cmp = 0;//新建一个比较值
添加两个延时函数

while(1)
{
    
    
	for(pwm_cmp =1;pwm_cmp<100;pwm_cmp++)
	{
    
    
		//设置比较值,查看所接的LED渐灭,因为0点亮
		//如果想要渐亮,设置pwm_cmp为从100--1即可
		TIM_SetCompare1(TIM14,pwm_cmp);
		delay_ms(10);
	}
	
	for(pwm_cmp=99;pwm_cmp>0;pwm_cmp--)
	{
    
    
		TIM_SetCompare1(TIM14,pwm_cmp);
		delay_ms(10);
	}
	
}

下面是使用野火开发板STM32F429写的PWM输出

#include "stm32f4xx.h"


//R 红色灯
#define LED1_PIN                  GPIO_Pin_10                 
#define LED1_GPIO_PORT            GPIOH                      
#define LED1_GPIO_CLK             RCC_AHB1Periph_GPIOH

static __IO u32 TimingDelay;
 
/**
  * @brief  启动系统滴答定时器 SysTick
  * @param  无
  * @retval 无
  */
void SysTick_Init(void)
{
    
    
	/* SystemFrequency / 1000    1ms中断一次
	 * SystemFrequency / 100000	 10us中断一次
	 * SystemFrequency / 1000000 1us中断一次
	 */
	if (SysTick_Config(SystemCoreClock / 100000))
	{
    
     
		/* Capture error */ 
		while (1);
	}
}

/**
  * @brief   us延时程序,10us为一个单位
  * @param  
  *		@arg nTime: Delay_us( 1 ) 则实现的延时为 1 * 10us = 10us
  * @retval  无
  */
void Delay_us(__IO u32 nTime)
{
    
     
	TimingDelay = nTime;	

	while(TimingDelay != 0);
}

/**
  * @brief  获取节拍程序
  * @param  无
  * @retval 无
  * @attention  在 SysTick 中断函数 SysTick_Handler()调用
  */
void TimingDelay_Decrement(void)
{
    
    
	if (TimingDelay != 0x00)
	{
    
     
		TimingDelay--;
	}
}

/*
1-初始化LED灯所在的GPIO引脚

PH10  定时器5的CH1 

2-查看说明手册,判断定时器是否有输出功能

16 位(TIM3 和 TIM4)或 32 位(TIM2 和 TIM5) 递增、递减和递增/递减自动重载计 
数器。
说明可用

3-编写GPIO初始化
4-编写定时器初始化
5-主函数调用
*/
void tim14_init(void)
{
    
    
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef          GPIO_InitStructure;
		TIM_TimeBaseInitTypeDef   TIM_TimeBaseStructure;
		TIM_OCInitTypeDef					TIM_OCInitStructure;
	
		/*开启LED相关的GPIO外设时钟*/
		RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK, ENABLE); 
		RCC_APB1PeriphClockCmd ( RCC_APB1Periph_TIM5, ENABLE); 

		GPIO_PinAFConfig(GPIOH,GPIO_PinSource10,GPIO_AF_TIM5);								
		GPIO_InitStructure.GPIO_Pin = LED1_PIN;			/*选择要控制的GPIO引脚*/		
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;   		/*设置引脚模式为输出模式*/
    	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;    /*设置引脚的输出类型为推挽输出*/
   	    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;    /*设置引脚为上拉模式*/
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; 		/*设置引脚速率为2MHz */   
		GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);	/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/
		
	
	 	 //90Mhz 设置到100HZ输出,90000000/9000/100 = 100hz
		TIM_TimeBaseStructure.TIM_Period = 100-1;
  		TIM_TimeBaseStructure.TIM_Prescaler = 9000-1;
		TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
		TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
		TIM_TimeBaseInit(TIM5,&TIM_TimeBaseStructure);
	
		TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
		TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
		TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
		TIM_OC1Init(TIM5,&TIM_OCInitStructure);
		
		TIM_OC1PreloadConfig(TIM5,TIM_OCPreload_Enable);
		TIM_ARRPreloadConfig(TIM5,ENABLE);
			// 使能定时器
		TIM_Cmd(TIM5, ENABLE);	

}



int main(void)
{
    
    
		uint32_t pwm_cmp = 0;//新建一个比较值
		SysTick_Init();
		tim14_init();
		

	while(1)
	{
    
    
		for(pwm_cmp =1;pwm_cmp<100;pwm_cmp++)
		{
    
    
			//设置比较值,查看所接的LED渐灭,因为0点亮
			//如果想要渐亮,设置pwm_cmp为从100--1即可
			TIM_SetCompare1(TIM5,pwm_cmp);
			Delay_us(5000);    	// 1000 * 10us = 100ms
		}
		
		for(pwm_cmp=99;pwm_cmp>0;pwm_cmp--)
		{
    
    
			TIM_SetCompare1(TIM5,pwm_cmp);
			Delay_us(5000);    	// 100 * 10us = 1000us = 1ms    *100 = 100ms
		}
		
	}
}


/*********************************************END OF FILE**********************/

在stm32f4xx_it.c

void SysTick_Handler(void)
{
    
    
	TimingDelay_Decrement();
}

猜你喜欢

转载自blog.csdn.net/ABCisCOOL/article/details/115018361