1.前言
上一篇文章介绍了通用定时器控制LED的闪烁,这篇文章我们来介绍一下STM32单片机中的定时器发生PWM的部分,使用定时器来产生呼吸灯的效果。同样地,我们所使用的硬件设备仍然是STM32RCT6单片机等基础设备,关于单片机的原理图以及LED灯的引脚在前文均已详细介绍,这里我们就不再赘述。
2.PWM详解
定义
PWM,是脉冲宽度调制,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于有效电平的时间占据整个信号周期的百分比。
时序
关于PWM的输入时序,在中文手册中有这样的描述:
PWM的复用引脚
这里以TIM1为例,列出了其四个通道对应的复用功能引脚,也就是说这些引脚可以直接输出PWM信号,其他定时器的四通道复用功能引脚在中文手册中均有详细说明。
PWM的原理
PWM发生的实质就是设定一个比较值,在原波形中大于该设定值的部分将其置一,小于该设定值的部分将其置零,从而能够得到周期性的矩形波,这就是PWM。
3.软件部分
引脚配置
首先是复用引脚的IO配置,这里将IO口配置成复用输出模式。
static void GENERAL_TIMx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GENERAL_TIM_APBxClock_FUN (GENERAL_TIM_CLK, ENABLE);
GENERAL_TIM_GPIO_APBxClock_FUN(GENERAL_TIM_GPIO_CLK1|GENERAL_TIM_GPIO_CLK1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_PORT1, &GPIO_InitStructure);
}
NVIC初始化配置
static void NVIC_Config_PWM(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIMx_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
通用定时器配置
因为是定时器发生PWM,所以要对定时器进行相应配置。这里我们将周期设置为255,预分频系数为1999,将定时器模式设置为PWM1模式,为向上计数,最后再使能相应的PWM输出状态和NVIC的配置。
static void GENERAL_TIMx_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Period = 255;
TIM_TimeBaseStructure.TIM_Prescaler = 1999;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(GENERAL_TIMx, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
GENERAL_TIM_OCxInit(GENERAL_TIMx, &TIM_OCInitStructure);
GENERAL_TIM_OCxPreloadConfig(GENERAL_TIMx, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(GENERAL_TIMx, ENABLE);
TIM_Cmd(GENERAL_TIMx, ENABLE);
NVIC_Config_PWM();
TIM_ITConfig(GENERAL_TIMx, TIM_IT_Update, ENABLE);
}
4.完整代码
main.c
int main(void)
{
GENERAL_TIMx_PWM_Init();
while (1)
{
}
}
这里就是初始化PWM,能够自动输出PWM。
bsp_GeneralTim.c
#include "bsp/GeneralTIM/bsp_GeneralTIM.h"
uint8_t indexWave[] = {1,1,2,2,3,4,6,8,10,14,19,25,33,44,59,80,107,143,191,255,
255,191,143,107,80,59,44,33,25,19,14,10,8,6,4,3,2,2,1,1};
static void GENERAL_TIMx_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
GENERAL_TIM_APBxClock_FUN (GENERAL_TIM_CLK, ENABLE);
GENERAL_TIM_GPIO_APBxClock_FUN(GENERAL_TIM_GPIO_CLK1|GENERAL_TIM_GPIO_CLK1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_PIN1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GENERAL_TIM_PORT1, &GPIO_InitStructure);
}
static void NVIC_Config_PWM(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIMx_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
/*
* TIMxCLK/CK_PSC --> TIMxCNT --> TIMx_ARR --> TIMxCNT ÖØмÆÊý
* TIMx_CCR(µçƽ·¢Éú±ä»¯)
* ÐźÅÖÜÆÚ=(TIMx_ARR +1 ) * ʱÖÓÖÜÆÚ
* Õ¼¿Õ±È=TIMx_CCR/(TIMx_ARR +1)
* _______ ______ _____ ____ ___ __ _
* |_| |__| |___| |____| |_____| |______| |_______| |________|
*
*/
static void GENERAL_TIMx_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_TimeBaseStructure.TIM_Period = 255;
TIM_TimeBaseStructure.TIM_Prescaler = 1999;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1 ;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(GENERAL_TIMx, &TIM_TimeBaseStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
GENERAL_TIM_OCxInit(GENERAL_TIMx, &TIM_OCInitStructure);
GENERAL_TIM_OCxPreloadConfig(GENERAL_TIMx, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(GENERAL_TIMx, ENABLE);
TIM_Cmd(GENERAL_TIMx, ENABLE);
NVIC_Config_PWM();
TIM_ITConfig(GENERAL_TIMx, TIM_IT_Update, ENABLE);
}
void GENERAL_TIMx_PWM_Init(void)
{
GENERAL_TIMx_GPIO_Config();
GENERAL_TIMx_Configuration();
}
5.实验效果
呼吸灯
6.结束语
本次实验讲解了使用Stm32的定时器发生PWM产生呼吸灯的效果,这也是STM32单片机应用很多的一部分内容,希望以上内容对各位朋友有所帮助。
最后,欢迎大家在评论区留言批评指正。谢谢!