搜索
bottom↓
回复: 0

《DNESP32S3使用指南-IDF版_V1.6》第十七章 SW_PWM实验

[复制链接]

出0入234汤圆

发表于 4 天前 | 显示全部楼层 |阅读模式
本帖最后由 正点原子 于 2024-7-19 09:34 编辑

2.jpg
1)实验平台:正点原子ESP32S3开发板
2)购买链接:https://detail.tmall.com/item.htm?id=768499342659
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-347618-1-1.html
4)正点原子官方B站:https://space.bilibili.com/394620890
5)正点原子手把手教你学ESP32S3快速入门视频教程:https://www.bilibili.com/video/BV1sH4y1W7Tc
6)正点原子FPGA交流群:132780729
1.png
3.png

第十七章 SW_PWM实验

       本章将介绍使用ESP32-S3 LED控制器(LEDC)。LEDC主要用于控制LED,也可产生PWM信号用于其他设备的控制。该控制器有8路通道,可以产生独立的波形,驱动RGB LED等设备。LED PWM控制器可在无需CPU干预的情况下自动改变占空比,实现亮度渐变。ESP32-S3 IDF提供了两种方式改变PWM,一种是通过软件改变PWM占空比,另一种是通过硬件改变PWM占空比,这两种方式我们都会一一进行讲解。通过本章的学习,开发者将学习到软件改变PWM占空比的运用。本章分为如下几个小节:
       17.1 PWM简介
       17.2 硬件设计
       17.3 程序设计
       17.4 下载验证

       17.1 PWM简介

       1,PWM原理解析
       PWM(Pulse Width Modulation),简称脉宽调制,是一种将模拟信号变为脉冲信号的计数。PWM可以控制LED亮度、直流电机的转速等。
       PWM的主要参数如下:

       ①:PWM频率。PWM频率是PWM信号在1s内从高电平到低电平再回到高电平的次数,也就是说1s内有多少个PWM周期,单位为Hz。

       ②:PWM周期。PWM周期是PWM频率的倒数,即T=1/f,T是PWM周期,f是PWM频率。如果PWM频率为50Hz,也就是说PWM周期为20ms,即1s由50个PWM周期。

       ③:PWM占空比。PWM占空比是指在一个PWM周期内,高电平的时间与整个周期时间的比例,取值范围为0%~100%。PWM占空比如下图所示。

第十七章 SW638.png
图17.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占空比和亮度的关系如下图所示。

第十七章 SW984.png
图17.1.2 PWM占空比和亮度的关系

       2,ESP32的LED PWM控制器介绍
       ESP32-S3的LED PWM控制器,简写为LEDC,用于生成控制LED的脉冲宽度调制信号。
       LED PWM控制器具有八个独立的PWM生成器(即八个通道)。每个PWM生成器会从四个通用定时器中选择一个,以该定时器的计数值作为基准生成PWM信号。LED PWM定时器如下图所示。

第十七章 SW1168.png
图17.1.1.1 LED_PWM的定时器

       为了实现PWM 输出,先需要设置指定通道的PWM参数:频率、分辨率、占空比,然后将该通道映射到指定引脚,该引脚输出对应通道的PWM信号,通道和引脚的关系所下图所示。

第十七章 SW1275.png
图17.1.1.2 LED PWM输出示意图

       另外,LED PWM控制器可在没有CPU干预的情况下自动改变占空比,实现亮度以及颜色渐变。

       17.2 硬件设计

       17.2.1 例程功能

       1. 通过软件改变PWM的形式使得LED由亮到暗,再由暗到亮,依次循环。

       17.2.2 硬件资源

       1. LED
              LED-IO1

       2. 定时器1
              通道1 - IO1

       17.2.3 原理图
       本章实验使用的定时器1为ESP32-S3的片上资源,因此没有对应的连接原理图。

       17.3 程序设计

       17.3.1 程序流程图
       程序流程图能帮助我们更好的理解一个工程的功能和实现的过程,对学习和设计工程有很好的主导作用。下面看看本实验的程序流程图:

第十七章 SW1612.png
图17.3.1.1 SW_PWM实验程序流程图

       17.3.2 SW_PWM函数解析
       ESP-IDF提供了一套API来配置PWM。要使用此功能,需要导入必要的头文件:
  1. #include "driver/ledc.h"
复制代码
       接下来,作者将介绍一些常用的SW_PWM函数,这些函数的描述及其作用如下:

       1,配置LEDC使用的定时器为定时器1
       需要注意的一点是,在首次配置LEDC时,建议先配置定时器(调用函数ledc_timer_config()),再配置通道(调用函数ledc_channel_config())。这样可以确保IO引脚上的PWM信号自输出开始那一刻起,其频率就是正确的。
       方才提到,要设置定时器,可调用函数ledc_timer_config(),需要将一些参数的数据结构传递给该函数,该函数原型如下所示:
  1. esp_err_t ledc_timer_config(const ledc_timer_config_t *timer_conf);
复制代码
       该函数的形参描述,如下表所示:

1.png
表17.3.2.1 函数ledc_timer_config ()形参描述

       返回值:ESP_OK表示配置成功,其他配置失败。
       该函数使用ledc_timer_config_t类型的结构体变量传入,该结构体的定义如下所示:

2.png
表17.3.2.2 ledc_timer_config_t 结构体参数值描述

       完成上述结构体参数配置之后,可以将结构传递给 ledc_timer_config () 函数,用以实例化SW_PWM并返回SW_PWM句柄。另外值得一提的是,时钟源同样可以限制PWM频率。选择的时钟源频率越高,可以配置的PWM频率上限就越高。

       2,通道配置函数
       该函数原型如下所示:
  1. esp_err_t ledc_channel_config(const ledc_channel_config_t *ledc_conf);
复制代码
       该函数的形参描述,如下表所示:

3.png
表17.3.2.3 函数ledc_channel_config ()形参描述

       返回值:ESP_OK表示配置成功,其他配置失败。
       该函数使用ledc_channel_config_t类型的结构体变量传入,该结构体的定义如下所示:

4.png
表17.3.2.4 ledc_channel_config_t结构体参数值描述

       完成上述结构体参数配置之后,可以将结构传递给 ledc_channel_config() 函数,用以实例化PWM通道。

       3,改变PWM占空比
       调用函数ledc_set_duty()可以设置新的占空比。之后,调用函数ledc_update_duty()使新配置生效。要查看当前设置的占空比,可使用get 函数ledc_get_duty(),该函数原型如下所示:
  1. esp_err_t ledc_set_duty(ledc_mode_t speed_mode,
  2.                                                  ledc_channel_t channel,
  3.                                                  uint32_t duty);
复制代码
       该函数的形参描述,如下表所示:

5.png
表17.3.2.5 函数ledc_set_dut ()形参描述

       返回值:ESP_OK表示配置成功,其他配置失败。

       4,改变PWM占空比
       在上一步调用ledc_set_duty()设置新的占空比后,调用函数ledc_update_duty()使新配置生效,该函数原型如下所示:
  1. esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
复制代码
       该函数的形参描述,如下表所示:

6.png
表17.3.2.6 函数ledc_update_duty()形参描述

       返回值:ESP_OK表示配置成功,其他配置失败。

       17.3.3 SW_PWM驱动解析
       在IDF版的08-1_sw_pwm例程中,作者在08-1_sw_pwm \components\BSP路径下新增了一个PWM文件夹,用于存放pwm.c和pwm.h这两个文件。其中,pwm.h文件负责声明SW_PWM相关的函数和变量,而pwm.c文件则实现了SW_PWM的驱动代码。下面,我们将详细解析这两个文件的实现内容。

       1,pwm.h文件
  1. /* 引脚以及重要参数定义 */
  2. #define LEDC_PWM_TIMER                  LEDC_TIMER_1        /* 使用定时器1 */
  3. #define LEDC_PWM_CH0_GPIO               GPIO_NUM_1                 /* LED控制器通道对应GPIO */
  4. #define LEDC_PWM_CH0_CHANNEL            LEDC_CHANNEL_1        /* LED控制器通道号 */
复制代码

       2,pwm.c文件
  1. /**
  2. * @brief                初始化PWM
  3. * @param               resolution: PWM占空比分辨率
  4. *                                freq: PWM信号频率
  5. * @retval              无
  6. */
  7. void pwm_init(uint8_t resolution, uint16_t freq)
  8. {
  9.     ledc_timer_config_t ledc_timer;                         /* LEDC定时器句柄 */
  10.     ledc_channel_config_t ledc_channel;                     /* LEDC通道配置句柄 */

  11.     /* 配置LEDC定时器 */
  12.     ledc_timer.duty_resolution = resolution;                /* PWM占空比分辨率 */
  13.     ledc_timer.freq_hz = freq;                              /* PWM信号频率 */
  14.     ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE;            /* 定时器模式 */
  15.     ledc_timer.timer_num = LEDC_PWM_TIMER;                  /* 定时器序号 */
  16.     ledc_timer.clk_cfg = LEDC_AUTO_CLK;                     /* LEDC时钟源 */
  17.     ledc_timer_config(&ledc_timer);                         /* 配置定时器 */

  18.     /* 配置LEDC通道 */
  19.     ledc_channel.gpio_num = LEDC_PWM_CH0_GPIO;              /* LED控制器通道对应引脚 */
  20.     ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE;                /* LEDC高速模式 */
  21.     ledc_channel.channel = LEDC_PWM_CH0_CHANNEL;                /* LEDC控制器通道号 */
  22.     ledc_channel.intr_type = LEDC_INTR_DISABLE;             /* LEDC失能中断 */
  23.     ledc_channel.timer_sel = LEDC_PWM_TIMER;                /* 定时器序号 */
  24.     ledc_channel.duty = 0;                                  /* 占空比值 */
  25.     ledc_channel_config(&ledc_channel);                     /* 配置LEDC通道 */
  26. }

  27. /**
  28. * @brief       PWM占空比设置
  29. * @param       duty:PWM占空比
  30. * @retval      无
  31. */
  32. void pwm_set_duty(uint16_t duty)
  33. {
  34. ledc_set_duty(LEDC_LOW_SPEED_MODE,
  35.                                   LEDC_PWM_CH0_CHANNEL,
  36.                                   duty);                                                                /* 设置占空比 */
  37. ledc_update_duty(LEDC_LOW_SPEED_MODE,
  38.                                          LEDC_PWM_CH0_CHANNEL);                            /* 更新占空比 */
  39. }
复制代码
       LEDC定时器设置好后,请配置所需的通道(ledc_channel_t)。配置通道需调用函数ledc_channel_config()。通道的配置与定时器设置类似,需向通道配置函数传递相应的结构体ledc_channel_config_t。此时,通道会按照ledc_channel_config_t的配置开始运作,并在选定的GPIO上生成由定时器指定的频率和占空比的PWM信号。
       调用函数ledc_set_duty()可以设置新的占空比。之后,调用函数ledc_update_duty()使新配置生效。为了方便使用,笔者将这两个函数进行了“封装”,通过传参的形式来配置PWM占空比。
       关于配置过程中所涉及到的结构体成员变量的含义以及用法,请读者们回顾本章节前面的内容。

       17.3.4 CMakeLists.txt文件
       打开本实验BSP下的CMakeLists.txt文件,其内容如下所示:
  1. set(src_dirs            
  2.             PWM)

  3. set(include_dirs
  4.             PWM)

  5. set(requires
  6.             driver)

  7. idf_component_register(SRC_DIRS ${src_dirs}
  8. INCLUDE_DIRS ${include_dirs} REQUIRES ${requires})

  9. component_compile_options(-ffast-math -O3 -Wno-error=format=-Wno-format)
复制代码
       上述的红色SW_PWM驱动需要由开发者自行添加,以确保SW_PWM驱动能够顺利集成到构建系统中。这一步骤是必不可少的,它确保了SW_PWM驱动的正确性和可用性,为后续的开发工作提供了坚实的基础。

       17.3.5 实验应用代码
       打开main/main.c文件,该文件定义了工程入口函数,名为app_main。该函数代码如下。
  1. int main(void)
  2. {
  3. esp_err_t ret;
  4.     uint8_t dir = 1;
  5.     uint16_t ledrpwmval = 0;
  6.    
  7.     ret = nvs_flash_init();        /* 初始化NVS */

  8. if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
  9.             ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
  10.     {
  11.         ESP_ERROR_CHECK(nvs_flash_erase());
  12.         ret = nvs_flash_init();
  13.     }
  14.    
  15. pwm_init(10, 1000);     /* 初始化PWM */

  16.     while (1)
  17.     {
  18.         vTaskDelay(10);
  19.         
  20.         if (dir == 1)
  21.         {
  22. /* dir==1,ledrpwmval递增 */
  23.             ledrpwmval += 5;
  24.         }
  25.         else
  26.         {
  27. /* dir==0,ledrpwmval递减 */
  28.             ledrpwmval -= 5;
  29.         }
  30.         
  31.         if (ledrpwmval > 1005)
  32.         {
  33.             /* ledrpwmval到达1005后,方向改为递减 */
  34.             dir = 0;
  35.         }
  36.         
  37.         if (ledrpwmval < 5)
  38.         {
  39.             /* ledrpwmval递减到5后,方向改为递增 */
  40.             dir = 1;
  41.         }
  42.         /* 设置占空比 */
  43.         pwm_set_duty(ledpwmval);
  44. }
  45. }
复制代码
       从上面的代码中可以看到,在初始化LEDC定时器,并输出PWM后,就不断地改变定时器0的值,以达到改变PWM占功比的目的。又因为PWM由IO1引脚输出,IO1引脚连接至LED,所以LED的亮度也会随之发生变化,从而实现呼吸灯的效果。

       17.4 下载验证
       在完成编译和烧录后,可以看到板子上的LED先由暗再逐渐变亮,以此循环,实现了呼吸灯的效果。

阿莫论坛20周年了!感谢大家的支持与爱护!!

知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-7-22 20:20

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表