实验目的
使用TIM3和TIM4,分别输出一个PWM波形,PWM的占空比随时间变化,去驱动你外接的一个LED以及最小开发板上已焊接的LED(固定接在 PC13 GPIO端口),实现2个 LED呼吸灯的效果。
实验材料
硬件
- STM32F103C8T6最小开发板
- CH340模块
- LED灯一个
- 杜邦线若干
- 面包板一块
软件
- KEIL5
- FLYMCU
实验原理
呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减, 很有节奏感地一起一伏,就像是在呼吸一样。要控制 LED 灯达到呼吸灯的效果,实际上就是要控制 LED 灯的亮度拟合呼吸特性曲线。
因为引脚要么输出1,要么0,没有“慢慢升高或降低”这一说法,因此要实现呼吸灯,需要使用到PWM。所谓PWM,就是通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。
以正弦信号为例,通过一系列不同的脉冲宽度的信号,可以等效地得到正弦信号:
对于呼吸特性曲线,也一样可以用这种方法拟合,让LED灯阴极引脚输出呼吸特性曲线的等效脉冲信号波形,就可以实现呼吸灯。
项目制作
CubeMX初始化
1、时钟配置
按上图依次配置,将PCLK1配置为36MHz。
2、定时器配置
因为实验要求控制两个LED,因此我使用TIM3与TIM4进行输出PWM。上图以配置TIM3介绍过程。
点击TIM3,再勾选内部时钟,并选择通道2输出PWM。这里也可以选用其他通道,不过这会导致PWM输出的GPIO口不同,要注意一下。
再选择分频为71,计数为500。这里的计数不用写太大。
配置一下项目路径与名称,以及使用的ide,生成项目。
代码实现
源码在这里:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_TIM3_Init();
MX_TIM4_Init();
HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_2);
HAL_TIM_PWM_Start(&htim4,TIM_CHANNEL_2);
uint16_t status = 0;
int16_t duty_num = 0;
while (1)
{
HAL_Delay(50);
if (status == 0){
duty_num = duty_num + 17;
if(duty_num > 500)
{
status = 1;
duty_num = 493;
}
}
else{
duty_num = duty_num - 17;
if(duty_num < 17)
{
status = 0;
duty_num = 17;
}
}
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_2,duty_num);
__HAL_TIM_SetCompare(&htim4,TIM_CHANNEL_2,duty_num);
}
}
呼吸灯有两个过程,一个过程是慢慢亮灯,一个是慢慢灭灯。一个周期中低电平占比越多,灯就越亮。这里变量duty_num用来设置一个周期中高电平的时间。我的定时器一个周期计数个数为500,因此duty_num的范围就是0-500之间。
想要慢慢变亮,就慢慢降低高电平所占一个周期的时间,即每隔一段时间降低duty_num的值;想要慢慢变暗,就慢慢提升高电平所占一个周期的时间,即每隔一段时间增大duty_num的值。
那每次增大多少呢?
主循环第一行,设置的每50ms改一次占空比。首先要知道你想让一个呼吸灯亮灭的周期是多少,比如我想让led灯一呼一吸是3秒,那么就是3000ms,要设置60次占空比。
前面说过,呼吸灯有两个过程,一个过程是慢慢亮灯,一个是慢慢灭灯,两个过程时间一样,那么每个过程要设置30次占空比。设置占空比就是设置高电平在一个中断周期中所占时间,前面说了一个中断周期数500个数,灯最亮的时候高电平时间为0,为了30次将0变成500,每次让duty_num增大500/30,就是17。灯由灭变亮同理。
知道了每次duty_num变化量,那么就可以将新的duty_num值用于设置高电平计数个数。
但是由于每次是加17,因此当493加到510时,会超过一个中断周期的500计数,因此要检测溢出。如果检测到duty_num为510,就改成500,并开始逐渐减小。
因为减小的时候是500开始减,每次减17,因此最后会出现负数。也要做一样的操作。
实验现象
接3.3V到面包板外围,LED灯正极接面包板正极,阴极接TIM3的PWM输出口;拿一个杜邦线一端插入TIM4的PWM输出口,另一端插入PC13口(自带的LED灯阴极是这个口)。
连接好串口模块,烧录程序,发现外接的LED与自带的LED一起变成了呼吸灯:
总结
使用PWM来拟合呼吸波曲线,来控制LED灯的亮度。使用HAL库配置定时器,使定时器按照占空比输出高低电平。并以一定时间间隔修改占空比。
参考资料
http://www.mcublog.cn/stm32/2021_01/stm32cubemx-pwm-huxideng/