4.1 知识要点
PWM 基本知识
aRGB 三原色合成灯效讲解
cubeMX 中配置 PWM 定时器配置
4.2 课程内容
本课程中,将学习到 PWM 的基本原理,如何控制引脚输出 PWM 信号,aRGB 三原色合成灯效的原理。本节课将通过在 cubeMX 中进行引脚配置,建立工程,并使用 PWM 输出实现aRGB 合成等效。
4.3 基础学习
4.3.1 PWM 基本知识PWM 即脉冲宽度调制是英文“Pulse Width Modulation”的缩写,简称脉宽调试。是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。广泛应用在从测量、通信到功率控制与变换的许多领域中。
例如上图中,矩形脉冲是 stm32 输出的数字信号,当这个信号接到外设上时,效果可以等效为这个正弦波。一个周期内高电平的持续时间占总周期的比例成为占空比,通过修改占空比,可以改变输出的等效模拟电压。例如输出占空比为 50%,频率为 10Hz 的脉冲,高电平为 3.3V.则其输出的模拟效果相当于输出一个 1.65V 的高电平。此外 PWM 输出的频率也会影响最终的 PWM输出效果,PWM 输出的频率越高,最终输出的“连续性”越好,越接近模拟信号的效果,频率低则会增强离散性,最终的输出效果会有比较强的“突变”感。脉冲调制有两个重要的参数,第一个就是输出频率,频率越高,则模拟的效果越好。第二个就是占空比。占空比就是改变输出模拟效果的电压大小。占空比越大则模拟出的电压越大。
4.3.2 aRGB 三原色
aRGB 为一种色彩模式,aRGB 分别代表了 alpha(透明度)Red(红色)Green(绿色)和Blue(蓝色)四个要素,一般我们给每个要素设置十进制下 0-255 的取值范围,通过 16 进制表示就是 0x00-0xFF,因此一个 aRGB 值可以通过八位十六进制数来描述,从前到后每两位依次对应 a,R,G,B。在 aRGB 中,alpha 值越大色彩越不透明,RGB 中哪个值越大,对应的色彩就越强。比如纯红色可以用 8 位 16 进制表示为 0xFFFF0000,纯绿色可以表示为 0xFF00FF00,纯蓝色可以表示为 0xFF0000FF,黄色由蓝色和绿色合成,所以可以表示为 0xFF00FFFF。
4.4 程序学习
4.4.1 PWM 在 cubeMX 中配置
在 cubeMX 中设置定时器 5 的通道 1,2,3 为 PWM 输出。可以注意到三个通道对应的引脚正是之前的实验中使用的 LED 引脚。
定时器 5 如下配置,设置重载值为 65535。
时钟树配置如下:
点击 Generate Code,生成工程代码。
4.4.2 PWM 配置介绍
在上一节课中介绍了 STM32 的定时器,并提到 PWM 输出是 STM32 的定时器的功能之一,为了实现 PWM 功能,需要使用定时器中的比较寄存器(TIMx_CCRx)。当定时器以 PWM 模式工作时,会自动将 TIMx_CCRx 的值与 TIMx_CNT(计数寄存器)中的值做比较,当 TIMx_CNT 中的值小于 TIMx_CCRx 的值时,PWM 输出引脚输出高电平,大于时则输出低电平。因此知道了 PWM 信号的周期和占空比可以通过设置比较寄存器TIMx_CCRx 和定时器重载寄存器 TIMx_ARR 来控制。PWM 的占空比可以通过下图公式计算:
以下图为例,该定时器的重载值为 8,比较寄存器值为 4,输出信号为 OCXREF,则其占空比为 44.4%。
一个定时器工作在 PWM 输出模式下时,有 4 个通道可以进行 PWM 信号的输出,每一个定时器都有对应标号的比较寄存器,比如 5 号定时器的 1 号通道对应的比较寄存器为TIM5_CCR1。
修改比较寄存器 TIMx_CCRx 的值来控制 PWM 输出的占空比。在函数 aRGB_led_show中,首先通过与运算与移位运算提取出对应的 alpha,R,G 和 B 通道值,然后用透明度alpha 与 R,G,B 三者依次相乘,最后将其赋值通过__HAL_TIM_SetCompare 函数给对应的比较寄存器 TIM5->CCRx。通过控制不同的 PWM 占空比,控制某个颜色的 LED 的亮度,以这样的方式就可以通过设置 aRGB 的值来控制最后输出的 LED 灯效。
void aRGB_led_show(uint32_t aRGB)
{
static uint8_t alpha;
static uint16_t red,green,blue;
alpha = (aRGB & 0xFF000000) >> 24;
red = ((aRGB & 0x00FF0000) >> 16) * alpha;
green = ((aRGB & 0x0000FF00) >> 8) * alpha;
blue = ((aRGB & 0x000000FF) >> 0) * alpha;
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_1, blue);
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_2, green);
__HAL_TIM_SetCompare(&htim5, TIM_CHANNEL_3, red);}#define __HAL_TIM_SET_COMPARE(__HANANDLE__, __CHANNEL__, __COMPARE__) \(((__CHANNEL__) == TIM_CHANNEL_1) ? ((__HANDLE__)->Instance->CCR1 = (__COMPARE__)) :\((__CHANNEL__) == TIM_CHANNEL_2) ? ((__HANDLE__)->Instance->CCR2 = (__COMPARE__)) :\((__CHANNEL__) == TIM_CHANNEL_3) ? ((__HANDLE__)->Instance->CCR3 = (__COMPARE__)) :\((__HANDLE__)->Instance->CCR4 = (__COMPARE__)))
}
4.4.3 HAL_TIM_PWM_Start 函数介绍为了使定时器开始 PWM 输出,除了要通过 HAL_TIM_Base_Start 使定时器开始工作,还需要在初始化时调用 HAL 库提供的 PWM 初始化函数 HAL_TIM_PWM_Start。
4.4.4 程序流程