十八、PWM呼吸灯
1. 配置流程
我们外接一个LED灯进行PWM实现,注意一下要选择合适规格的LED。
一般使用定时器PWM功能,都需要有以下几个步骤。
- 使能时钟
- 配置GPIO
- 配置定时器
- 配置PWM
- 使能TIMER
- 调整定时器输出通道占空比
1.1 使能时钟
这一章节就用PWM实现一个呼吸灯的效果。首先LED灯连接在PA5引脚上,查找用户手册的第147页可知,PB0有GTIM1通道3的复用功能,如图所示。
这里选择PB0的复用功能,也就是使用GTIM1_CH3进行PWM输出。
使能时钟:
__RCC_GPIOB_CLK_ENABLE(); // 使能GPIO时钟
__RCC_GTIM1_CLK_ENABLE(); // 使能通用定时器1时钟
2
1.2 配置GPIO
前面介绍过PWM输出是依赖于定时器的,所以要对定时器进行配置,但是我们不使用定时器的中断功能,顾不用对定时器的中断进行配置。
又因为我们使用的PB0是GTIM1的通道3,所以我们要配置PB0的GPIO参数。
首先是GPIO的参数结构体:
GPIO_InitTypeDef GPIO_InitStruct; // GPIO初始化结构体
然后GPIO配置参数:
GPIO_InitStruct.Pins = GPIO_PIN_0; // GPIO引脚
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; // 推挽输出
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; // 输出速度高
2
3
使用复用功能,将PB0复用为GTIM1通道3的通道
PB00_AFx_GTIM1CH3(); // 使用复用功能,复用为通用定时器1通道3
使能GPIO配置。
GPIO_Init(CW_GPIOB, &GPIO_InitStruct); // 初始化
1.3 配置定时器
要使用定时器参数配置有一个结构体,如图所示。
参数说明
uint32_t Mode: 这个字段用于指定GTIM的工作模式。
- GTIM_MODE_TIME:基本定时器模式。
- GTIM_MODE_COUNTER:计数器模式。
- GTIM_MODE_TRIGGER:触发模式,可能指定时器被用作触发源或响应于某个外部触发信号开始/停止计数。
- GTIM_MODE_GATE:门控模式,意味着定时器的计数操作受一个外部信号的控制,即只有当这个控制信号有效时,定时器才开始或继续计数。
uint32_t OneShotMode: 此字段决定定时器是工作在单次计数模式还是一直循环计数(连续计数)模式。如果设置为单次模式,定时器在达到重载值后会停止计数,直到复位或重新配置;如果是连续计数模式,则会在达到重载值后自动重置并继续计数。
FunctionalState ToggleOutState: 这个字段用于控制定时器的输出翻转功能是否使能。FunctionalState是一个类型定义,通常有两个的值:ENABLE和DISABLE,分别表示启用或禁用定时器的输出引脚翻转功能。当定时器计数达到特定条件时,其关联的输出引脚电平会翻转。
uint32_t Prescaler: 预分频器的设置值。预分频器用于降低提供给定时器时钟的频率,使得计数速度变慢,从而实现更宽范围的计时能力。
uint32_t ReloadValue: 重载值,也称为自动装载寄存器值。当计数值达到此值时,定时器会产生一个更新事件(如中断或DMA请求),并且计数器会根据OneShotMode的设置重置或继续计数。这个值决定了定时器溢出的周期,是定时操作的核心配置之一。
结构体定义:
GTIM_InitTypeDef GTIM_InitStruct; // 通用定时器初始化结构体
相关配置如下:
GTIM_InitStruct.Mode = GTIM_MODE_TIME; // 定时器模式
GTIM_InitStruct.OneShotMode = GTIM_COUNT_CONTINUE; // 连续计数模式
GTIM_InitStruct.Prescaler = GTIM_PRESCALER_DIV64; // DCLK = PCLK / 64 = 64MHz/64 = 1MHz
GTIM_InitStruct.ReloadValue = 5000; // 重装载值设置
GTIM_InitStruct.ToggleOutState = DISABLE; // 输出翻转功能
2
3
4
5
初始化配置:
GTIM_TimeBaseInit(CW_GTIM1, >IM_InitStruct); // 初始化
1.4 配置PWM
配置好GTIMER3参数之后,需要配置PWM输出。
GTIM_OCInit(CW_GTIM1, GTIM_CHANNEL3, GTIM_OC_OUTPUT_PWM_HIGH); // 配置输出比较通道3为PWM模式
可选参数
- GTIM_OC_OUTPUT_FORCE_LOW: 强制输出比较通道输出低电平(通常为0V),不论定时器的计数状态如何。
- GTIM_OC_OUTPUT_FORCE_HIGH: 强制输出比较通道输出高电平(通常为Vcc或逻辑1),不考虑定时器当前的计数值。
- GTIM_OC_OUTPUT_MATCH_LOW: 当定时器的计数值与预设的比较值匹配时,输出比较通道输出低电平。这是输出比较模式的基本应用,常用于生成脉冲或控制外部设备。
- GTIM_OC_OUTPUT_MATCH_HIGH: 类似于上面,但当计数值匹配时,输出比较通道切换到高电平。
- GTIM_OC_OUTPUT_MATHC_TOGGLE: 在计数值与比较值匹配时,输出比较信号进行翻转。如果当前是低电平,则变为高电平;如果是高电平,则变为低电平。这种模式可以生成方波输出或用于更复杂的控制逻辑。
- GTIM_OC_OUTPUT_PWM_HIGH: 配置输出比较通道为PWM(脉宽调制)模式,高电平主动。在此模式下,输出信号的高电平时间由定时器的比较值决定,而低电平时间则由自动装载周期减去高电平时间得到,常用于电机控制、LED亮度调节等。
- GTIM_OC_OUTPUT_PWM_LOW: 同样是PWM模式,但这里是低电平主动,意味着输出信号的低电平时间由比较值直接控制,而高电平时间则是剩余部分。这主要影响软件处理逻辑和一些硬件接口的兼容性。
1.5 使能TIMER
我们使用函数TIM_Cmd初始化函数:
GTIM_Cmd(CW_GTIM1, ENABLE); // 使能定时器
1.6 调整定时器输出通道占空比
void GTIM_SetCompare3(GTIM_TypeDef *GTIMx, uint32_t Value)
该函数GTIM_SetCompare3用于设置通用定时器(GTIM)的第3个通道(Channel 3)的比较值(Compare Value)
- GTIMx: 指向通用定时器的类型定义指针。这是一个重要的参数,用来指定要操作的具体定时器实例(例如 TIM1、TIM2 等)。使用前需要确保指针非空且指向有效的定时器。
- Value: 要设置的比较值,类型为无符号32位整数。这个值决定了定时器计数器何时与之“比较”,进而可能触发输出状态的改变(比如在PWM模式下改变占空比)
函数没有返回值(@retval None)。
注意
注意:每个通道有不同的函数。通道2是GTIM_SetCompare2,通道3是GTIM_SetCompare3,如此以此类推。。。。
在PWM(脉冲宽度调制)应用中,可以通过改变CCR3的值来调整PWM信号的占空比。例如,增加CCR3的值会增加PWM高电平的持续时间,从而增加占空比。
2. 呼吸灯函数
要实现一个呼吸灯的效果,首先我们来看呼吸灯产生的原理。呼吸灯产生的原理就是LED灯逐渐变亮再逐渐变暗,然后一直循环下去。控制LED灯的亮暗是通过改变PWM的占空比,占空比越大,LED灯越亮,占空比越小,LED灯越暗。所以,我们只需要调节PWM的占空比就可以实现呼吸灯的效果。设置PWM的占空比的函数在之前介绍过,编写呼吸灯代码如下:
void LED_PWM(void)
{
static uint8_t Dir = 1; // 计数方向 1增加,0 减少
static uint32_t PosWidth = 0; // 正脉宽,单位us
static uint16_t TimeCnt = 0; // 周期
if (TimeCnt++ >= 100)
{
TimeCnt = 0;
if (Dir)
{
PosWidth += 5;
}
else
{
PosWidth -= 5;
}
if (PosWidth >= 5000)
{
Dir = 0;
}
if (0 == PosWidth)
{
Dir = 1;
}
GTIM_SetCompare3(CW_GTIM1, PosWidth);
delay_ms(1);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
3. 实验现象
关于这一章节的代码,在立创·地文星CW32F030C8T6开发板资料/第03章软件资料/代码例程/008PWM呼吸灯。
烧写我们的代码之后,会观察到LED灯由暗变亮,继而由亮变暗的效果。