ESP-IDF+vscode开发ESP32第十一讲——LEDC

目录

前言

一、知识前提

二、工程编写

[2.1 LEDC.c](#2.1 LEDC.c)

[2.2 LEDC.h](#2.2 LEDC.h)

[2.3 main.c](#2.3 main.c)

[2.4 代码说明](#2.4 代码说明)


前言

本章是一个基础的PWM波产生工程,主要用于控制LED灯,可以实现精准的颜色和呼吸变化。也可用于其他需要PWM的控制设备。本文不解释PWM的形成和作用。

开发板是微雪的**ESP32-P4-Module-DEV-KIT。**ESP-IDF版本是6.0.1。基于第一章的工程模板。


一、知识前提

在实现之前,需要同学们了解什么是PWM以及PWM的作用,一个PWM所有参数只有频率、占空比和相位,一般相位不重要也不设置。

官方给的LEDC讲解很细致,建议阅读《LED PWM 控制器

使用PWM输出需要完成定时器配置、通道配置和PWM信号设置。定时器用于指定 PWM 信号的频率和占空比分辨率。通道用于绑定定时器和输出 PWM 信号的 GPIO。

官方文档中对于改变PWM信号分为使用软件改变和使用硬件改变,但是并没有说明两种区别。其实软件改变就是用户靠一行代码设置PWM占空比,硬件改变就是按照用户预先设定的一套PWM占空比变化方式,接着LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比。

ESP32-P4的LED PWM控制器特性如下:

  • 八个独立的 PWM 生成器(即八个通道)
  • PWM 占空比最大精度为 20 位;PWM 输出信号相位可调节
  • 占空比自动渐变---即 PWM 信号占空比可逐渐增加或减小,无须处理器干预,渐变完成时产生中断
  • 每个 PWM 生成器包含 16 个占空比渐变区间,用于生成占空比伽马曲线渐变的信号。每个区间都可以独立配置占空比变化方向(增加或减少)、变化步长、变化次数以及变化频率
  • 低功耗模式 (Light-sleep mode) 下可输出 PWM 信号

LED PWM 控制器通过 GPIO 交换矩阵可配置使用任意GPIO管脚

ESP32-P4的LED PWM控制器可设置时钟源频率最大为80M,那么最大PWM频率可为 40 MHz,但此时占空比只能设置为50%;当PWM 频率为 50 kHz 时,占空比分辨率最大可为 10 bit,通过示波器查看,精度还是很高的,跳变沿只有10ns,没有过冲。能驱动市面上大量的PWM控制设备。

二、工程编写

首先自定义组件LEDC。CMakeLists.txt添加依赖

bash 复制代码
idf_component_register(SRCS "LEDC.c"
                    INCLUDE_DIRS "include"
                    PRIV_REQUIRES esp_driver_ledc)

2.1 LEDC.c

cpp 复制代码
#include "LEDC.h"
#include "driver/ledc.h"         // ESP32 LEDC驱动函数

static const char *TAG = "LEDC"; // 日志标签
/*--------------------------------------------------------------------------*/
/**
 * @brief 一个简单低速的PWM输出示例,输出频率为10kHz,占空比为50%
 * @param[in] void
 * @note 
 * @return void
 */
/*--------------------------------------------------------------------------*/
void LEDC_PWMOUT_INIT(void)
{
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_LOW_SPEED_MODE, // 低速模式
        .timer_num        = LEDC_TIMER_0,        // 定时器0
        .duty_resolution  = LEDC_TIMER_10_BIT,   // 10位分辨率
        .freq_hz          = 10000,               // 频率10kHz
        .clk_cfg          = LEDC_AUTO_CLK         // 自动选择时钟源
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); // 配置LEDC定时器
    ESP_LOGI(TAG, "最大占空比分辨率: %d bits", ledc_find_suitable_duty_resolution(80000, ledc_timer.freq_hz/1000)); // 查找合适的占空比分辨率
    ledc_channel_config_t ledc_channel = {
        .gpio_num       = PWM_OUTIO,            // PWM输出引脚
        .speed_mode     = LEDC_LOW_SPEED_MODE, // 低速模式
        .channel        = LEDC_CHANNEL_0,      // 通道0
        .timer_sel      = LEDC_TIMER_0,       // 使用定时器0
        .duty           = 0,                  // 初始占空比为0
        .hpoint         = 0                   // 初始hpoint为0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); // 配置LEDC通道
    // Set duty to 50%
    ESP_ERROR_CHECK(ledc_set_duty_and_update(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 512, 0)); // 占空比512/1024 = 50%
    vTaskDelay(pdMS_TO_TICKS(100)); // 等待1秒钟
    ESP_LOGI(TAG,"当前占空比为: %d%%", ledc_get_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)*100/(1<<10)); // 获取当前占空比
}
/*--------------------------------------------------------------------------*/
/**
 * @brief 一个在时间周期内渐变的PWM输出示例,输出频率为5kHz,占空比从0%渐变到100%,再从100%渐变到0%,循环进行
 * @param[in] void
 * @note 
 * @return void
 */
/*--------------------------------------------------------------------------*/
void LEDC_led_fade(void)
{
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_LOW_SPEED_MODE, // 低速模式
        .timer_num        = LEDC_TIMER_1,        // 定时器1
        .duty_resolution  = LEDC_TIMER_10_BIT,   // 10位分辨率
        .freq_hz          = 50000,               // 频率50KHz
        .clk_cfg          = LEDC_AUTO_CLK         // 自动选择时钟源
    };
    ESP_LOGI(TAG, "最大占空比分辨率: %d bits", ledc_find_suitable_duty_resolution(80000, ledc_timer.freq_hz/1000)); // 查找合适的占空比分辨率
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); // 配置LEDC定时器
    ledc_channel_config_t ledc_channel = {
        .gpio_num       = PWM_FADEIO,            // PWM输出引脚
        .speed_mode     = LEDC_LOW_SPEED_MODE, // 低速模式
        .channel        = LEDC_CHANNEL_1,      // 通道1
        .timer_sel      = LEDC_TIMER_1,       // 使用定时器1
        .duty           = 0,                  // 初始占空比为0
        .hpoint         = 0                   // 初始hpoint为0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); // 配置LEDC通道
    ledc_fade_func_install(0); // 安装LEDC渐变功能
    ESP_LOGI(TAG, "LED渐变: 从0到100再从100到0,循环进行");
    while(1)
    {
        ledc_set_fade_time_and_start(ledc_channel.speed_mode, ledc_channel.channel, 1024, 2000,LEDC_FADE_WAIT_DONE); // 从0%渐变到100%,时间1秒
        ledc_set_fade_time_and_start(ledc_channel.speed_mode, ledc_channel.channel, 0, 2000,LEDC_FADE_WAIT_DONE); // 从100%渐变到0%,时间1秒
    }
}

2.2 LEDC.h

cpp 复制代码
#ifndef __LEDC_H
#define __LEDC_H

#include <stdio.h>               // 输入输出函数
#include <string.h>              // 字符串处理函数
#include "esp_log.h"             // ESP32日志函数
#include "FreeRTOS/FreeRTOS.h"   // FreeRTOS函数
#include "FreeRTOS/task.h"       // FreeRTOS任务管理函数
#include "FreeRTOS/semphr.h"     // FreeRTOS信号量管理函数

#define     PWM_OUTIO      27  // 定义PWM输出引脚为GPIO27
#define     PWM_FADEIO     4  // 定义PWM渐变引脚为GPIO4

void LEDC_PWMOUT_INIT(void);
void LEDC_led_fade(void);
#endif                          // __LEDC_H

2.3 main.c

cpp 复制代码
#include <stdio.h>
#include "user.h"
#include "LEDC.h"
void app_main(void)
{
    CONSOLE_REPL_INIT(); // 初始化控制台REPL环境
    //LEDC_PWMOUT_INIT();
    LEDC_led_fade();
    while(1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

2.4 代码说明

LEDC.c中有两个代码,LEDC_PWMOUT_INIT只用来输出一个固定PWM占空比的信号,LEDC_led_fade可用来输出周期内渐变的PWM占空比信号。其中的个函数比较简单,可以看官方手册或者我总结的文档《ESP32实用API指南3-CSDN博客

相关推荐
一帘忧梦9 小时前
vscode 搭建stm32开发环境 +HAL 库
ide·vscode·编辑器
Robot_Nav1 天前
AI 编程助手 Skill 完全指南:VS Code · Trae CN · Claude Code
人工智能·vscode·skill·trae·claude code
生而为虫1 天前
在VScode中使用Claude Code agent并配置模型(仅mac电脑实际操作,windows电脑未实际操作如有问题可留言)
windows·vscode·macos
千码君20162 天前
flutter: 分享一下基于trae cn 构建的过程
java·vscode·flutter·kotlin·trae
我才是一卓2 天前
2026 Python 入门教程,结合 vscode 和 miniforge/miniconda
开发语言·vscode·python
lzl20402 天前
VSCode中Codex CLI登录卡在‘Sign in with ChatGPT‘屏幕
ide·vscode·chatgpt·codex
SkyXZ~2 天前
Mac上使用VScode优雅开发STM32
vscode·stm32·macos
xskukuku3 天前
VSCode中的Codex插件如何调用第三方API
vscode·ai·codex
lijfrank3 天前
MacOS 下 VS Code + LaTeX + Skim 双向同步配置
vscode·macos·pdf·latex·mactex