通用定时器之PWM
脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。简单一点,就是对脉冲宽度的控制,PWM 原理如图
STM32F4输出PWM的工作过程
通过定时器的控制按一定的周期输出PWM波
STM32F4 的定时器除了 TIM6 和 7。其他的定时器都可以用来产生 PWM 输出。通过查看我们开发板的原理图(如下图)发现,PF9引脚连接的是LED0,而且同时也是作TIM14_CH1的复用输出端口,这时候,我们可以使用PF9引脚,输出PWM波,来控制我们的LED0,使得LED0的亮灭有了更加美妙的呼吸状态。
通用定时器之PWM输出步骤
1、使能定时器14和相关IO口时钟。
使能定时器14时钟:RCC_APB1PeriphClockCmd();
使能GPIOF时钟:RCC_AHB1PeriphClockCmd ();
2、初始化IO口为复用功能输出。函数:GPIO_Init();
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIOF9复用映射到定时器14
GPIO_PinAFConfig(GPIOF,GPIO_PinSource9,GPIO_AF_TIM14);
3、初始化定时器:ARR,PSC等:
TIM_TimeBaseInit();
4、初始化输出比较参数:
TIM_OC1Init();
5、 使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
6、使能自动重装载的预装载寄存器允许位
TIM_ARRPreloadConfig(TIM14,ENABLE);
7、使能定时器。
TIM_Cmd(TIM14, ENABLE);
8、不断改变比较值CCRx,达到不同的占空比效果:
TIM_SetCompare1();
通用定时器之PWM输出步骤1~2
1)开启 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);
2)GPIOF PIN9的设置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //GPIOF9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //配置引脚为复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOF,&GPIO_InitStructure); //初始化 PF9,用库函数寄存器
通用定时器之PWM输出步骤3
3)初始化 TIM14定时器, 设置 TIM14 的装载,分频,计数模式等等
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//设置定时器的的自动重装载的值
TIM_TimeBaseStructure.TIM_Period=arr;
//设置定时器的分频值
TIM_TimeBaseStructure.TIM_Prescaler=psc;
//设置定时器为向上计数模式
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
//设置定时器的时钟分频因子
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM14,&TIM_TimeBaseStructure);//初始化定时器 14
4)设置 TIM14_CH1 的 PWM 模式 ,能使能 TIM14 的 CH1 (通道1)输出。
这里涉及一个MDK库的结构体
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;
} TIM_OCInitTypeDef;
参数 TIM_OCMode 设置模式是 PWM 还是输出比较,这里我们是 PWM 模式。
参数 TIM_OutputState 用来设置比较输出使能,也就是使能 PWM 输出到端口。
参数 TIM_OCPolarity 用来设置极性是高还是低。
其他的参数 TIM_OutputNState,TIM_OCNPolarity,TIM_OCIdleState 和 TIM_OCNIdleState 是高级定时器才用到的。
配置的方法:
//定时一个该结构体
TIM_OCInitTypeDef TIM_OCInitStructure;
//选择PWM的模式,选择PWM模式1
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
//用于设置输出的使能,使能PWM输出到端口
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
//输出的极性,输出是高电平还是低电平,这里选择低。
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
//根据设定信息配置TIM14 OC1
TIM_OC1Init(TIM14, &TIM_OCInitStructure);
PWM 通道设置是通过函数 TIM_OC1Init()~TIM_OC4Init()来设置的,不同的通道的设置函数不一样,这里
我们使用的是通道 1,所以使用的函数是 TIM_OC1Init()。
4) 使能预装载寄存器:
TIM_OC1PreloadConfig(TIM14, TIM_OCPreload_Enable);
5)使能自动重装载的预装载寄存器允许位 TIM_ARRPreloadConfig(TIM14,ENABLE);
最后,在经过以上设置之后,PWM 其实已经开始输出了,只是其占空比和频率都是固定的,而我们可以再程序中通过修改 TIM14_CCR1 则可以控制 CH1 的输出占空比。继而控制 DS0 的亮度。在库函数中,修改 TIM14_CCR1 占空比的函数是:
6)修改 TIM14_CCR1 来控制占空比。
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare2);
理所当然,对于其他通道,函数格式可为TIM_SetComparex(x=1,2,3,4)。