欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

程序员文章站 2022-06-08 19:13:33
...

Conceit is the quicksand of success.

  自负是成功的流沙。

PWM实现呼吸灯

PWM概述

相关概念

PWM设置流程

呼吸灯实现例程

pwm.c

 main.c


PWM概述

        脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。脉冲宽度调制是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。简单一点,就是对脉冲宽度的控制,PWM 原理如图:

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

CNT:计数器

ARR:重装值寄存器

CCRx:比较寄存器

STM32F4输出PWM的工作过程

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

         STM32F4 的定时器除了 TIM6 和 TIM7。其他的定时器都可以用来产生 PWM 输出。通过查看我们开发板的原理图(如下图)发现,PF9引脚连接的是LED0,而且同时也是作TIM14_CH1的复用输出端口,这时候,我们可以使用PF9引脚,输出PWM波,来控制我们的LED0,使得LED0的亮灭有了更加美妙的呼吸状态。

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

相关概念

占空比:占空比是指在一个脉冲循环内,通电时间(可能是高电平也可能是低电平)相对于总时间所占的比例。

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

通用定时器 (TIM2 到 TIM5)计数模式为例:

  • 110:PWM 模式 1––在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为有 效状态,否则为无效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为 无效状态 (OC1REF=0),否则为有效状态 (OC1REF=1)。
  • 111:PWM 模式 2––在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为无 效状态,否则为有效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为 有效状态,否则为无效状态
  • 通道有效,则输出你设定的有效电平(极性电平)
  • 通道无效,则输出你设定与有效电平相反电平(极性电平)

PWM 模式 1

【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

  • PWM设置流程

    添加PWM开发库函数文件:stm32f4xx_tim.c

  • 以 IM14 -- APB1为例

  • 1、理解电路原理
    以LED0——PF9引脚为例

  •         LED0灯连接PF9,TIM14通道1
            IM14 -- APB1,定时器频率:84MHZ

  • 【STM32F4教程】第六节:通用定时器之PWM实现呼吸灯

2、使能定时器14和相关IO口时钟

//使能定时器14时钟: 
RCC_APB1PeriphClockCmd(); 

//使能GPIOF时钟: 
RCC_AHB1PeriphClockCmd ();

3、初始化IO口为复用功能输出

//由于使用到PF9的复用功能,利用库函数映射到定时TIM14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); 

GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_9; 		//GPIOF9
GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_AF; 	//配置引脚为复用功能
...
GPIO_Init(GPIOF,&GPIO_InitStruct); 	//初始化 PF9,用库函数寄存器

4、初始化定时器:ARR,PSC等

TIM_TimeBaseStruct.TIM_Prescaler        = 84-1 ; 	//设置定时器的分频值 1MHZ
TIM_TimeBaseStruct.TIM_Period           = 500-1; 	//设置定时器的的自动重装载的值 周期为500us
TIM_TimeBaseStruct.TIM_CounterMode      = TIM_CounterMode_Up;//设置定时器为向上计数模式
TIM_TimeBaseStruct.TIM_ClockDivision    = TIM_CKD_DIV1;      //设置定时器的时钟分频因子
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStruct);        //初始化定时器 14

5、初始化输出比较参数

//根据设定信息配置TIM14 OC1 -- 通道1
//TIM_OC1Init根据具体通道选择
TIM_OC1Init(TIM14, &TIM_OCInitStruct); 

6、使能预装载寄存器

//使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);

7、使能自动重装载的预装载寄存器允许位

//使能自动重装载的预装载寄存器允许位	
TIM_ARRPreloadConfig(TIM14,ENABLE);

8、使能定时器

//使能定时器。
TIM_Cmd(TIM14, ENABLE);

9、不断改变比较值CCRx,达到不同的占空比效果:

TIM_SetCompare1(TIM14, 499);	

呼吸灯实现例程

pwm.c

#include "pwm.h"

/*
引脚说明:

LED0灯连接PF9,TIM14通道1

TIM14 -- APB1,定时器频率:84MHZ


*/

void Pwm_Led0_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
	
	TIM_OCInitTypeDef  TIM_OCInitStruct; 	//定时一个该结构体
	
	
	//开启 TIM14 和 和 GPIO时钟,配置 PF9选择复用功能 AF9 (TIM14)输出。
	//库函数使能 TIM14 时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14,ENABLE);
	//还需要使用到GPIOF9,所以也要使能该引脚 
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); 
	
	
	//由于使用到PF9的复用功能,利用库函数使其引脚与TIM14定时器
	GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14); 
	
	
	GPIO_InitStruct.GPIO_Pin 	= GPIO_Pin_9; 		//GPIOF9
	GPIO_InitStruct.GPIO_Mode 	= GPIO_Mode_AF; 	//配置引脚为复用功能
	GPIO_InitStruct.GPIO_Speed 	= GPIO_Speed_50MHz; //速度 50MHz
	GPIO_InitStruct.GPIO_OType 	= GPIO_OType_PP; 	//推挽复用输出
	GPIO_InitStruct.GPIO_PuPd 	= GPIO_PuPd_UP; 	//上拉
	GPIO_Init(GPIOF,&GPIO_InitStruct); 	//初始化 PF9,用库函数寄存器


	TIM_TimeBaseStruct.TIM_Prescaler	= 84-1 ; 	//设置定时器的分频值 1MHZ
	TIM_TimeBaseStruct.TIM_Period		= 500-1; 	//设置定时器的的自动重装载的值 周期为500us
	TIM_TimeBaseStruct.TIM_CounterMode	= TIM_CounterMode_Up;//设置定时器为向上计数模式
	TIM_TimeBaseStruct.TIM_ClockDivision= TIM_CKD_DIV1;//设置定时器的时钟分频因子
	TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStruct);//初始化定时器 14
	

	
	TIM_OCInitStruct.TIM_OCMode			= TIM_OCMode_PWM1; 		//选择PWM的模式,选择PWM模式1
	TIM_OCInitStruct.TIM_OCPolarity 	= TIM_OCPolarity_Low; 	//输出的极性,输出是高电平还是低电平,这里选择低电平
	TIM_OCInitStruct.TIM_OutputState 	= TIM_OutputState_Enable; //用于设置输出的使能,使能PWM输出到端口
	//根据设定信息配置TIM14 OC1 -- 通道1
	TIM_OC1Init(TIM14, &TIM_OCInitStruct); 
	
	//使能预装载寄存器:
	TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable); 
	//使能自动重装载的预装载寄存器允许位	
	TIM_ARRPreloadConfig(TIM14,ENABLE);

	//使能定时器。
	TIM_Cmd(TIM14, ENABLE);

}

 main.c

#include "stm32f4xx.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "delay.h"
#include "tim.h"
#include "pwm.h"

int main(void)
{
	//NVIC分组(一个工程当中只能配置一次分组)抢占优先级2位,值范围:0~3;响应优先级2位,值范围:0~3;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    //定时器初始化
	Tim3_Init();

	//LED0的PWM初始化
	Pwm_Led0_Init();
	
	int i;
	while(1)
	{
		//值范围:0~499  灯渐亮
		for( i = 0; i<= 499 ; i++)
		{
			TIM_SetCompare1(TIM14, i);		
			Delay(5);
		}
		//灯渐灭
		for( i = 499; i>= 0 ; i--)
		{
			TIM_SetCompare1(TIM14, i);		
			Delay(5);
		}
		
	}
	
	return 0;
}