第十三章 LED_PWM实验
本章,我们将学习ESP32-S3的LED PWM控制器,教会大家如何使用LED PWM控制器实现PWM信号输出。在本章中,驱动LED PWM控制器,输出PWM信号去控制LED的亮度,实现呼吸灯效果。 本章分为如下几个小节: 13.1 LED PWM控制器介绍 13.2 硬件设计 13.3 软件设计 13.4 下载验证
13.1 LED PWM控制器介绍 13.1.1 PWM介绍 PWM(Pulse Width Modulation),简称脉宽调制,是一种将模拟信号变为脉冲信号的技术。PWM可以控制LED亮度、直流电机的转速等。 PWM的主要参数如下: 1) PWM频率。PWM频率是PWM信号在1s内从高电平到低电平再回到高电平的次数,也就是说1s内有多少个PWM周期,单位为Hz。 2) PWM周期。PWM周期是PWM频率的倒数,即T=1/f,T是PWM周期,f是PWM频率。如果PWM频率为50Hz,也就是说PWM周期为20ms,即1s由50个PWM周期。 3) PWM占空比。PWM占空比是指在一个PWM周期内,高电平的时间与整个周期时间的比例,取值范围为0%~100%。PWM占空比如下图所示。 图13.1.1.1 PWM占空比 PWM周期是一个PWM信号的时间:脉宽时间是指高电平时间;脉宽时间占PWM周期的比例就是占空比。例如,如果PWM周期是10ms,而脉宽时间为8ms,那么PWM占空比就是8/10=80%,此时的PWM信号就是占空比为80%的PWM信号。PWM名为脉冲宽度调制,顾名思义,就是通过调节PWM占空比来调节PWM脉宽时间。 在使用PWM控制LED时,亮1s后灭1s,往复循环,就可以看到LED在闪烁。如果把这个周期缩小到200ms,亮100ms后灭100ms,往复循环,就可以看到LED灯在高频闪烁。继续把这个周期持续缩小,总有一个临界值使人眼分辨不出LED在闪烁,此时LED的亮度处于灭与亮之间亮度的中间值,达到了1/2亮度。PWM占空比和亮度的关系如下图所示。 图13.1.1.2 PWM占空比和亮度的关系 13.1.2 LED_PWM控制器介绍 ESP32-S3的LED PWM控制器,简写为LEDC,用于生成控制LED的脉冲宽度调制信号。 LED PWM控制器具有八个独立的PWM生成器(即八个通道)。每个PWM生成器会从四个通用定时器中选择一个,以该定时器的计数值作为基准生成PWM信号。LED PWM定时器如下图所示。 图13.1.2.1 LED_PWM的定时器 为了实现PWM 输出,先需要设置指定通道的PWM参数:频率、分辨率、占空比,然后将该通道映射到指定引脚,该引脚输出对应通道的PWM信号,通道和引脚的关系所下图所示。 图13.1.2.2 LED_PWM输出示意图 13.1.3 LED_PWM函数介绍 本小节介绍到的函数可在以下文件中找到: Arduino15\packages\esp32\hardware\esp32\2.0.11\cores\esp32\esp32-hal-ledc.c 接下来,我们介绍一下本章节所用到的LED PWM相关函数。 第一个函数:ledcSetup函数,该函数功能是指定LEDC通道的PWM信号频率和占空比分辨率。 double ledcSetup(uint8_t chan, double freq, uint8_t bit_num); 参数chan为LEDC通道号,取值为0~7,共8个通道; 参数freq为待设置的PWM脉宽信号的频率; 参数bit_num为计数位数,即PWM信号占空比的分辨率; 返回值:通道PWM信号的频率。 第二个函数:ledcAttachPin函数,该函数功能是将指定的LEDC通道绑定到指定GPIO引脚上,即由该引脚输出LEDC的PWM信号。 void ledcAttachPin(uint8_t pin, uint8_t chan); 参数pin为数字引脚编号; 参数chan为LEDC通道号,取值为0~7,共8个通道; 无返回值。 第三个函数:ledcWrite函数,该函数功能是设置指定通道输出的占空比数值。 void ledcWrite(uint8_t chan, uint32_t duty); 参数chan为LEDC通道号,取值为0~7,共8个通道; 参数duty为待设置的PWM占空比数值。该数值的范围由通道初始化设置函数ledcSetup()中的计数位数决定。例如,计数位数为8,那么占空比设置值的范围就为0~255。要输出占空比50%的PWM信号,该参数应设置为128。 无返回值。 13.2 硬件设计 1. 例程功能 实现LED0由暗变亮,再从亮变暗,依次循环。 2. 硬件资源 1)LED PWM LED-IO1 3. 原理图 本章实验使用的LED PWM为ESP32-S3的片上资源,因此并没有相应的连接原理图。 13.3 软件设计 13.3.1 程序流程图 下面看看本实验的程序流程图: 图13.3.1.1 程序流程图 13.3.2 程序解析 1. pwm驱动代码这里我们只讲解核心代码,详细的源码请大家参考光盘本实验对应源码。PWM驱动源码包括两个文件:pwm.cpp和pwm.h。 下面我们先解析pwm.h的程序。对LED PWM做了相关定义。 #define LED_PWM_PIN 1 /* PWM信号输出的引脚 */ #define LED_PWM_CHANNEL 0 /* LED PWM通道号 */ 我们选择使用LED PWM的通道0,将该通道映射到IO1,最终IO1引脚会输出通道0的PWM信号。 下面我们再解析pwm.cpp的程序,这里有两个函数led_pwm_init和pwm_set_duty,其定义如下: /** * @param frequency: PWM输出频率,单位HZ * @param resolution: PWM占空比的分辨率1-16,比如设置8,分辨率范围0~255 * @retval 无 */ void led_pwm_init(uint16_t frequency, uint8_t resolution) { ledcSetup(LED_PWM_CHANNEL, frequency, resolution); /* PWM初始化,引脚和通道由pwm.h的LED_PWM_PIN和LED_PWM_CHANNEL宏修改 */ ledcAttachPin(LED_PWM_PIN, LED_PWM_CHANNEL); /* 绑定PWM通道到LED_PWM_PIN上 */ } /** * @brief PWM占空比设置 * @param duty: PWM占空比 * @retval 无 */ void pwm_set_duty(uint16_t duty) { ledcWrite(LED_PWM_CHANNEL, duty); /* 改变PWM的占空比,通道由pwm.h的LED_PWM_CHANNEL宏修改 */ } led_pwm_init函数是初始化PWM输出功能,首先调用ledcSetup函数设置LEDC通道参数:PWM通道、PWM频率和占空比的分辨率。然后调用ledcAttachPin函数绑定PWM通道到IO1引脚。 pwm_set_duty函数就是调用ledcWrite函数去完成PWM占空比的修改。 2. 07_led_pwm.ino代码在07_led_pwm.ino里面编写如下代码: #include "pwm.h" uint16_t g_ledpwmval = 0; /* 占空比值 */ uint8_t g_dir = 1; /* 变化方向(1增大 0减小) */ /** * @brief 当程序开始执行时,将调用setup()函数,通常用来初始化变量、函数等 * @param 无 * @retval 无 */ void setup() { led_pwm_init(1000, 10);/* LED PWM初始化,PWM输出频率为1000HZ,占空比分辨率为10 */ } /** * @brief 循环函数,通常放程序的主体或者需要不断刷新的语句 * @param 无 * @retval 无 */ void loop() { if (g_dir) { g_ledpwmval += 5; } else { g_ledpwmval -= 5; } if (g_ledpwmval > 1005) { g_dir = 0; } if (g_ledpwmval < 5) { g_dir = 1; } pwm_set_duty(g_ledpwmval); delay(10); } 在setup函数中,调用led_pwm_init函数完成PWM输出的初始化。 在loop函数中,通过简单的逻辑判断,让g_ledpwmval变量可从小变大,又从大变小,最终通过pwm_set_duty函数传递g_ledpwmval参数去修改占空比,达到修改LED亮度效果。为了让效果更为明显,添加了延时10ms操作。 13.4 下载验证 下载代码完成后,ESP32-S3开发板上LED灯的亮度会以一个平稳的速度从最暗变到最亮,然后再从最亮变到最暗,实现呼吸灯的效果。
|