第 40 章 呼吸灯与 SPWM 波

本文详细介绍了使用STM32通过PWM技术实现呼吸灯效果的原理和步骤,包括呼吸灯和SPWM波形的生成。内容涵盖PWM控制基础,如脉冲宽度调制(PWM)的工作原理,以及如何利用STM32定时器配置PWM输出,通过计算法和调制法生成拟合呼吸曲线的PWM波形。此外,还提供了硬件设计建议和单色呼吸灯实验的编程要点,以及如何扩展到输出SPWM波形以控制RGB全彩LED灯。
40.1 呼吸灯简介

呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减,很有节奏感地一起一伏,就像是在呼吸一样。

40.2 呼吸灯与 PWM 控制原理

呼吸的特性是一种类似图指数曲线 中的指数曲线过程,吸气是指数上升过程,呼气是指数下降过程,成年人吸气呼气整个过程持续约 3 秒。

在这里插入图片描述

实现过程

要控制 LED 灯达到呼吸灯的效果,实际上就是要控制 LED 灯的亮度拟合呼吸特性曲线。前面控制全彩 LED 灯时,通过控制脉冲的占空比来调整各个通道 LED 灯的亮度,从而达到混色的效果。若控制脉冲的占空比在 3 秒的时间周期内按呼吸特性曲线变化,那么就可以实现呼吸灯的效果

运用原理

使用脉冲占空比拟合不同波形的方式称为 PWM(脉冲宽度调制) 控制技术——通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。

PWM 控制的基本原理为:冲量相等而开头不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。其中冲量指窄脉冲的面积;效果相同指环节输出响应波形基本相同。

PWM等效正弦波

• 把正弦半波 N 等分,可看成 N 个彼此相连的脉冲序列,宽度相等,但幅值不等;

• 用矩形脉冲代替,各个矩形脉冲等幅,不等宽,中点重合,脉冲宽度按正弦规律变化,脉冲的总面积(冲量)与正弦半波相等。
在这里插入图片描述

这种脉冲波形被称为 SPWM 波形——脉冲宽度按正弦规律变化而和正弦波等效的 PWM 波形。

若把拟合的波形改成呼吸特性曲线,即可得到控制呼吸灯使用的 PWM 波形,要生成拟合的 PWM波形,通常使用计算法调制法

(1) 计算法:根据拟合波形的频率、幅值和半周期脉冲数,准确计算 PWM 波各脉冲宽度和间隔,据此控制开关器件的通断,就可得到所需 PWM 波形;

(2) 调制法:拟合波形作调制信号,进行调制得到期望的 PWM 波;该方法一般采用等腰三角波为载波,其任一点水平宽度和高度成线性关系且左右对称。载波 (等腰三角波) 与平缓变化的调制信号波 (即要拟合的波形) 相交,在载波与信号波的交点控制器件通断,就得宽度正比于信号波幅值的脉冲,符合 PWM 的要求,见图调制法得到 PWM 波 。相对于计算法,其处理过程计算简单。
在这里插入图片描述

使用计算法得到的呼吸曲线 PWM 波和 SPWM 波,并使用 STM32定时器 TIM 的 PWM 功能输出波形控制 LED 灯,达到呼吸灯的效果。

40.3 硬件设计

在这里插入图片描述

因为本实验的软件将使用 STM32 的定时器控制输出 PWM 脉冲,然而并不是任意 GPIO 都具有 STM32 定时器的输出通道功能,所以在设计硬件时,需要根据《STM32 中文数据手册》中的说明,选择具有定时器输出通道功能的引脚来控制 RGB 灯

在这里插入图片描述

40.4 单色呼吸灯实验

4.1 编程要点
  1. 初始化 PWM 输出通道,初始化 PWM 工作模式;
  2. 计算获取 PWM 数据表;
  3. 编写中断服务函数,在中断服务函数根据 PWM 数据表切换比较寄存器的值;
4.2 代码分析
4.2.1 LED 灯硬件相关宏定义
4.2.2 初始化 GPIO
4.2.3 定义 PWM 表
4.2.4 定时器 PWM 配置
4.2.5 定时器中断服务函数
4.2.6 计算拟合波形的周期

• TIMPeriod:定时器的计数周期,它的值必须与 PWM 表中的极大值相等(应用中赋值需要减 1),而 PWM 表的极大值决定了控制的分辨率。例如极大值为 10 时,PWM 占空比只有10 个等级,精确到 0.1,当极大值为 1000 时,PWM 占空比有 1000 个等级,精确到 0.001。

• TIM_Prescaler:定时器时钟分频因子,它控制定时器计数器 CNT 计数加 1 所需要的时间,它的值太大会导致输出的单个 PWM 波周期过长,影响控制的动态特性。如控制 LED 灯时,该值太大会导致 LED 灯开关时间变长,闪烁明显。一般来说,该值越小越好。

• PWM 表的点数:PWM 表的点数即对拟合曲线的采样点数,采样点越多,能更好地还原拟合曲线,采样点太少,可能会导致失真,见图对呼吸特性曲线采样 110 个和 10 个点时的情况 。

在这里插入图片描述

• period_class:周期倍数,即 PWM 表中每个元素的循环次数,它影响拟合曲线的周期。当period_class=1 时,可以输出本配置中周期最短的拟合曲线。

• amplitude_class:幅值分级,在后面全彩呼吸灯和 SPWM 实验中,我们还会增加该变量,它可以把拟合曲线的幅值分成 N 个等级,控制时可以选择按某个幅值等级进行输出。本实验中没有配置该参数,所以只能输出最大的等级,即 amplitude_class=1。以上各个参数虽然侧重点不同,但若修改其中的任何一个,最终都会影响到所拟合曲线的周期,所以在实际应用中,通常先设定好 TIMPeriod、TIM_Prescaler、PWM 表的点数以及幅值等级数amplitude_class,得到适合的控制精度、动态特性拟合度以及幅值等级后,然后再调period_class控制拟合曲线的周期,而且 period_class 在程序中动态修改非常方便,不需要重置定时器和PWM表。

最终,我们把本工程配置中的拟合曲线周期计算公式概括如下:

(1) STM32 系统时钟默认频率和周期:f_pclk = 72000000 t_pclk = 1/f_pclk

(2) 定时器 update 事件周期,即定时器中断周期:

t_timer = t_pclk * TIMER_TIM_Prescaler * TIMER_TIM_Period

(3) 每个 PWM 点的时间:T_Point = t_timer * PERIOD_CLASS

(4) 最终,遍历 PWM 表的周期,即拟合曲线的周期:T_PWM = T_Point * POINT_NUM

例如,本工程配置中:

PWM 点数:POINT_NUM = 110

周期倍数:PERIOD_CLASS = 10

定时器定时周期:TIMER_TIM_Period = 1024

定时器分频:TIMER_TIM_Prescaler = 200

代入公式,计算得 T_PWM = 3.128 秒

通过公式的计算可知本工程的配置可使得输出的拟合曲线周期为 3.128 秒,是比较平缓的呼吸周期

4.2.7 主函数

main.c

#include "stm32f10x.h"
#include "./breathinglight/bsp_breathing.h"



/**
  * @brief  主函数
  * @param  无
  * @retval 无
  */
int main(void)
{
   
   			
	/* 初始化呼吸灯 */
	TIMx_Breathing_Init();

	while(1)
	{
   
   
	
	}		
}



/*********************************************END OF FILE**********************/


breathing.h

#ifndef __PWM_BREATHING_H
#define	__PWM_BREATHING_H

#include "stm32f10x.h"

/*PWM表中的点数*/
extern uint16_t  POINT_NUM	;
//控制输出波形的频率
extern __IO uint16_t period_class ;


#define RED_LIGHT 		1
#define GREEN_LIGHT 	2
#define BLUE_LIGHT		3

/*要使用什么颜色的呼吸灯,可选RED_LIGHT、GREEN_LIGHT、BLUE_LIGHT*/
#define LIGHT_COLOR 	RED_LIGHT

/********************定时器通道**************************/
#if  LIGHT_COLOR == RED_LIGHT
/************红灯***************/
	#define   BRE_TIMx                      TIM3

	#define   BRE_TIM_APBxClock_FUN        RCC_APB1PeriphClockCmd
	#define   BRE_TIM_CLK                   RCC_APB1Periph_TIM3
	#define   BRE_TIM_GPIO_APBxClock_FUN   RCC_APB2PeriphClockCmd
	#define   BRE_TIM_GPIO_CLK              (RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO)

	//红灯的引脚需要重映射
	#define   BRE_GPIO_REMAP_FUN()						GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE); 				

	#define  BRE_TIM_LED_PORT               GPIOB
	#define  BRE_TIM_LED_PIN                GPIO_Pin_5

	#define  BRE_TIM_OCxInit                TIM_OC2Init            //通道选择,1~4
	#define  BRE_TIM_OCxPreloadConfig       TIM_OC2PreloadConfig 
	#define  BRE_CCRx                       CCR2

	#define   BRE_TIMx_IRQn                TIM3_IRQn              //中断
	#define   BRE_TIMx_IRQHandler          TIM3_IRQHandler

#elif LIGHT_COLOR == GREEN_LIGHT
/************绿灯***************/
	#define   BRE_TIMx                      TIM3

	#define   BRE_TIM_APBxClock_FUN        RCC_APB1PeriphClockCmd
	#define   BRE_TIM_CLK                   RCC_APB1Periph_TIM3
	#define   BRE_TIM_GPIO_APBxClock_FUN   RCC_APB2PeriphClockCmd
	#define   BRE_TIM_GPIO_CLK              (RCC_APB2Periph_GPIOB)

	//绿灯不需要重映射
	#define   BRE_GPIO_REMAP_FUN()				


	#define  BRE_TIM_LED_PORT               GPIOB
	#define  BRE_TIM_LED_PIN                GPIO_Pin_0

	#define  BRE_TIM_OCxInit                TIM_OC3Init            //通道选择,1~4
	#define  BRE_TIM_OCxPreloadConfig       TIM_OC3PreloadConfig 
	#define  BRE_CCRx                       CCR3

	#define   BRE_TIMx_IRQn                TIM3_IRQn              //中断
	#define   BRE_TIMx_IRQHandler          TIM3_IRQHandler

#elif LIGHT_COLOR == BLUE_LIGHT
/************蓝灯***************/
	#define   BRE_TIMx                      TIM3

	#define   BRE_TIM_APBxClock_FUN        RCC_APB1PeriphClockCmd
	#define   BRE_TIM_CLK                   RCC_APB1Periph_TIM3
	#define   BRE_TIM_GPIO_APBxClock_FUN   RCC_APB2PeriphClockCmd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

入世浮尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值