
前言 在本章中,演示如何使用计算法得到的呼吸曲线 PWM 波和 SPWM 波,并使用 STM32定时器 TIM的 PWM功能输出波形控制 LED 灯,实现三色LED的呼吸效果。 一、相关知识介绍 1.呼吸灯简介 呼吸灯,就是指灯光设备的亮度随着时间由暗到亮逐渐增强,再由亮到暗逐渐衰减, 很有节奏感地一起一伏,就像是在呼吸一样,因而被广泛应用于手机、电脑等电子设备的指示灯中 要控制 LED 灯达到呼吸灯的效果,实际上就是要控制 LED 灯的亮度拟合呼吸特性曲线。前面控制全彩 LED 灯时,通过控制脉冲的占空比来调整各个通道 LED 灯的亮度,从而达到混色的效果。若控制脉冲的占空比在 3 秒的时间周期内按呼吸特性曲线变化,那么就可以实现呼吸灯的效果了。 这种使用脉冲占空比拟合不同波形的方式称为 PWM(脉冲宽度调制)控制技术—— 通过对一系列脉冲的宽度进行调制,来等效地获得所需要波形(含形状和幅值)。 PWM 控制的基本原理为:冲量相等而开头不同的窄脉冲加在具有惯性的环节上时,其效果基本相同。其中冲量指窄脉冲的面积;效果相同指环节输出响应波形基本相同。 SPWM 波形——脉冲宽度按正弦规律变化而和正弦波等效的PWM 波形。SPWM 是一种非常典型的 PWM 波形,它在数字电路控制中应用非常广泛,如果使用低通滤波器,可以由 SPWM 波得到其等效的连续正弦半波。 若把拟合的波形改成呼吸特性曲线,即可得到控制呼吸灯使用的 PWM 波形,要生成拟合的 PWM 波形,通常使用计算法和调制法: (1) 计算法:根据拟合波形的频率、幅值和半周期脉冲数,准确计算 PWM 波各脉冲宽度和间隔,据此控制开关器件的通断,就可得到所需 PWM 波形; (2) 调制法:拟合波形作调制信号,进行调制得到期望的 PWM 波;该方法一般采用等腰三角波为载波,其任一点水平宽度和高度成线性关系且左右对称。载波(等腰三角波)与平缓变化的调制信号波(即要拟合的波形)相交,在载波与信号波的交点控制器件通断,就得宽度正比于信号波幅值的脉冲,符合 PWM 的要求 。相对于计算法,其处理过程计算简单。 2. 硬件简介 TIM—单色呼吸灯 使用呼吸曲线 PWM 波控制 LED 灯,可实现红、绿、蓝三种 颜色的单色呼吸灯。 RGB 灯,里面由红蓝绿三个小灯构成, 使用 PWM控制时可以混合成 256 不同的颜色 ![]() 本开发板中设计的 RGB 灯控制引脚是经过仔细选择的,因为使用STM32 的定时器控制输出 PWM脉冲,然而并不是任意 GPIO都具有 STM32 定时器的输出通道功能,所以 在设计硬件时,需要根据《STM32 中文数据手册》中的说明,选择具有定时器输出通道功能的引脚来控制 RGB 灯,如图 ![]() 本实训中的 RGB 灯使用阴极分别连接到了 PB5、PB0 及 PB1,它们分别是定时器 TIM3 的通道 2、3、4,其中 PB5用于定时器输出通道时,需要使用重定义功能。 二、实现呼吸灯 1.单色呼吸灯 要点 初始化 PWM 输出通道,初始化 PWM 工作模式; 计算获取 PWM数据表; 编写中断服务函数,在中断服务函数根据 PWM 数据表切换比较寄存器的值; LED灯硬件相关宏定义 breathing.h
为方便切换 LED 灯的颜色,定义了三组宏,通过修改代码中的 #define LIGHT_COLOR RED_LIGHT语句,可以切换使用红、绿、蓝三种颜色的呼吸灯。在每组宏定义中,与全彩 LED 灯类似,定义了定时器编号、定时器时钟使能库函数、引脚重映射操作、GPIO 端口和引脚号、通道对应的比较寄存器名以及中断通道和中断服务函数名。不同的是,这个定时器的比较寄存器 CCRx 在控制呼吸灯的单个周期内需要切换为 PWM 表中不同的数值,所以需要利用定时器中断。 2.初始化GPIO 初始化用于定时器输出通道的 GPIO breathing.c 文件:
由于直接使用定时器输出通道的脉冲信号控制 LED 灯,此处把 GPIO 相关的引脚配置成了复用推挽输出模式。其中由于红灯使用的引脚需要用到第二功能,本代码使用宏 BRE_GPIO_REMAP_FUN ()进行了该引脚的功能重定义操作。 3.定义 PWM表
该 PWM 表是利用本工程目录下的 python 脚本 index_wave.py 生成的 ![]() 该脚本运行后会在工程目录下生成一个包含该 PWM 表的 py_index_Wave.c文件,复制这些数据到 breathing.c 文件,即可得到本工程中的 indexWave 数组。实际上使用 C 语言也可以编写这样的脚本制作出 PWM 表,只是使用 python 脚本比较方便绘制图形而已。 该 python 脚本生成 PWM表数据的原理,实质是按照如下函数曲线进行采样: ![]() python 脚本在这样的函数曲线上取 110 个点,即可得到上述代码中 PWM 表数组indexWave。 这个 PWM 表记录了呼吸特性曲线,PWM 表的数据将会被赋值到定时器的 CCRx 比较寄存器,从而控制输出占空比呈呼吸特性曲线变化的 PWM波。至于计算 PWM 表时,为什么选择采样 110 个点以及为什么表中的最大元素为 1024,需要结合下面定时器和中断服务函数中的配置来理解。 4.定时器 PWM配置 ![]() 初始化了控制 RGB 灯用的定时器,被配置为向上计数,PWM 通道输出也被配置成当计数器 CNT 的值小于输出比较寄存器CCRx 的值时,PWM 通道输出低电平,点亮 LED 灯。在函数的最后还使能了定时器中断,每当定时器的一个计数周期完成时,产生中断,配合中断服务函数,即可切换 CCRx 比较寄存器的值。 代码中的 TIM_Period和 TIM_Prescaler是关键配置。其中 TIMPeriod 被配置为(1024-1),它控制定时器的定时周期,定时器的计数寄存器 CNT 从 0 开始,每个时钟会对计数器加 1,计数至 1023 时完成一次计数,产生中断,也就是说一共 1024 个计数周期,与 PWM 表元素中的最大值相同。若定时器的输出比较寄存器 CCRx 被赋值为 PWM 表中的元素,即可改变输出对应占空比的 PWM 波,控制 LED灯,如: ![]() 根据本工程中的 PWM 表更新 CCRx 的值,即可输出占空比呈呼吸特性曲线变化的PWM波形,达到呼吸灯的效果。最终,拟合曲线的周期由 TIMPeriod、PWM表的点数、TIM_Prescaler以及下面中断服务函数的 period_cnt比较值共同决定,本工程需要调整这些参数使得拟合曲线的周期约为 3秒,从而达到较平缓的呼吸效果。 5.定时器中断服务函数 stm32f10x_it.c 文件
在中断服务函数中,包含两个静态变量 period_cnt和 pwm_index。其中 pwm_index 比较容易理解,它用于指示当前要使用 PWM 表中的哪个元素,从而在“BRE_TIMx->BRE_CCRx = indexWave[pwm_index];‖语句中可以给 CCRx 赋予正确的数值,而且当 PWM 表中的数据都使用一遍时,pwm_index 将重新指向 PWM 表的开头,开始下一次呼吸循环。 在本工程的单次呼吸循环中,每个 PWM 表元素都会使用 10 次,代码中利用period_cnt 变量指示当前使用的次数,当 period_cnt> period_class 时(即period_cnt>10 时),pwm_index 才会指向下一个元素。每个 PWM表元素使用多次,主要是为了在 TIMPeriod、PWM 表的点数、TIM_Prescaler 都固定的情况下,通过调整每个元素的重复次数可以调整整个拟合波形的周期。如把代码中的比较值 period_class 改为 100,每个 PWM 表遍历一次的时间就变为原来配置的 10 倍,其拟合的呼吸周期也就相应地改变了。 6.计算拟合波形的周期 在本工程中,TIMPeriod、PWM 表的点数、TIM_Prescaler 以及 period_cnt 都会影响到拟合曲线的周期,而在实际应用中又有如下要求: TIMPeriod:定时器的计数周期,它的值必须与 PWM 表中的极大值相等(应用中赋值需要减 1),而 PWM 表的极大值决定了控制的分辨率。例如极大值为 10 时,PWM 占空比只有 10 个等级,精确到 0.1,当极大值为 1000 时,PWM 占空比有1000个等级,精确到 0.001。 TIM_Prescaler:定时器时钟分频因子,它控制定时器计数器 CNT 计数加 1 所需要的时间,它的值太大会导致输出的单个 PWM 波周期过长,影响控制的动态特性。如控制 LED 灯时,该值太大会导致 LED 灯开关时间变长,闪烁明显。一般来说,该值越小越好。 PWM 表的点数:PWM 表的点数即对拟合曲线的采样点数,采样点越多,能更好地还原拟合曲线,采样点太少,可能会导致失真, period_class:周期倍数,即 PWM 表中每个元素的循环次数,它影响拟合曲线的 周期。当 period_class=1时,可以输出本配置中周期最短的拟合曲线。 amplitude_class:幅值分级,可以把拟合曲线的幅值分成 N 个等级,控制时可以选择按某个幅值等级进行输出。本工程没有配置该参数,所以只能输出最大的等级,即amplitude_class=1。 以上各个参数虽然侧重点不同,但若修改其中的任何一个,最终都会影响到所拟合曲线的周期,所以在实际应用中,通常先设定好 TIMPeriod、TIM_Prescaler、PWM 表的点数以及幅值等级数 amplitude_class,得到适合的控制精度、动态特性拟合度以及幅值等级后,然后再调整 period_class 控制拟合曲线的周期,而且 period_class 在程序中动态修改非常方便,不需要重置定时器和 PWM表。 最终,我们把本工程配置中的拟合曲线周期计算公式概括如下: ![]() 通过公式的计算可知本工程的配置可使得输出的拟合曲线周期为 3.128 秒,是比较平缓的呼吸周期。 7.主函数
main 函数中直接调用了 TIMx_Breathing_Init 函数,而该函数内部又直接调用了前面讲解的 GPIO 和 PWM 配置函数:TIMx_GPIO_Config 和 TIMx_Mode_Config。初始化完成后,定时器开始工作,然后它会在中断服务函数中切换 PWM 数据,控制 LED 灯显示呼吸效果。 总结 本工程通过LED灯实现了呼吸灯效果,整体不难,使用呼吸曲线 PWM 波控制 LED 灯,可实现红、绿、蓝三种颜色的单色呼吸灯。实现全彩呼吸灯需要在单色呼吸灯的基础上,添加对 PWM 波的幅值控制,分为256 个等级,从而实现RGB888 全色彩的呼吸灯。 ———————————————— 版权声明:清道 夫 |