ITPub博客

首页 > 嵌入式/内核开发 > 嵌入式/内核开发 > 《ESP32S3 Arduino开发指南 V1.0 》第十三章 LED_PWM实验

《ESP32S3 Arduino开发指南 V1.0 》第十三章 LED_PWM实验

原创 嵌入式/内核开发 作者:正点原子 时间:2024-12-05 15:21:10 0 删除 编辑

第十三章 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,其定义如下:

/**
 * @brief   LED PWM初始化函数
 * @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灯的亮度会以一个平稳的速度从最暗变到最亮,然后再从最亮变到最暗,实现呼吸灯的效果。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70040860/viewspace-3054811/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2024-08-30

  • 博文量
    588
  • 访问量
    764200