ESP32-C3入门教程 基础篇(七、LEDC — LED PWM 控制器)

测试第7课,补一补基本的PWM控制器的测试。
说明一下,ESP32-C3没有MCPWM硬件,所以测试只有LEDPWM,
如果想用ESP32-C3控制电机,可以考虑使用 RMT,后期有机会测试一下。

前言

接下来的ESP32-C3 功能测试都是基于自己设计的开发板:

自己画一块ESP32-C3 的开发板(第一次使用立创EDA)(PCB到手)

开发环境是乐鑫官方的 ESP-IDF, 基于VScode插件搭建好的:

ESP32-C3 VScode开发环境搭建(基于乐鑫官方ESP-IDF——Windows和Ubuntu双环境)

在开发板上,测试需要用到的东西比较简单,只需要使用到 用户 LED,如下图:

在这里插入图片描述

1、LED PWM控制器基础介绍

1.1 基本介绍

对于ESP32-C3 通用定时器的介绍,乐鑫的官网的说明链接如下:

乐鑫官方ESP32-C3 LED PWM部分说明

ESP32­C3 技术参考手册 在第 26章: LED PWM 控制器(LEDC)

在这里插入图片描述

PWM的基础知识不过多介绍,用一张资料中的截图表示:

在这里插入图片描述
关于PWM的渐变,是通过改变Lpointn的值,开启了占空比渐变,Lpointn的值会在计数器溢出固定次数后(可配置)递增或递减(可配置),渐变值也可以配置:

在这里插入图片描述

1.2 使用步骤

老子样子,看一下PWM的使用步骤,根据示例代码分析一下就可以测试了:

在这里插入图片描述

1、配置定时器,使用 ledc_timer_config函数,参数为ledc_timer_config_t结构体:

在这里插入图片描述

在示例中,有如下配置:

在这里插入图片描述

注意:PWM 频率越高,占空比分辨率越低,反之则越高。对应关系如下:

在这里插入图片描述

2、 配置通道ledc_channel_config,参数为ledc_channel_config_t结构体:

在这里插入图片描述

在示例中,有如下配置,选取一个通道为例 :

在这里插入图片描述

注意一下,ESP32-C3只有6个通道:

在这里插入图片描述

3、完成上述配置后,就可以通过对应的操作控制LED渐变,这里可以使用软件,也可以使用硬件,硬件渐变不需要额外的干涉,使用ledc_fade_func_install(0);使能即可:

在这里插入图片描述

在示例程序中的代码如下:

在这里插入图片描述

2、LED PWM示例测试

在官方例程中,我们参考的示例程序为ledc

在这里插入图片描述

2.1 基础测试

对于官方的例程,使用到了4路输出,但是我们的板子上并没有这么多IO用于控制LED灯,而且例程使用了一些宏定义,所以针对我们的板子上只有一个LED的IO口 GPIO1 ,只有一个LED灯,我们把例程改简单点,也更加直观, 下面直接上修改的代码:

void app_main(void)
{
    ledc_timer_config_t ledc_timer = {
        .duty_resolution = LEDC_TIMER_13_BIT, // resolution of PWM duty
        .freq_hz = 5000,                      // frequency of PWM signal
        .speed_mode = LEDC_LOW_SPEED_MODE,           // timer mode
        .timer_num = LEDC_TIMER_0,            // timer index
        .clk_cfg = LEDC_AUTO_CLK,              // Auto select the source clock
    };
    ledc_timer_config(&ledc_timer);

    ledc_channel_config_t ledc_channel= {
        .channel    = LEDC_CHANNEL_1,
        .duty       = 0,
        .gpio_num   = 1,
        .speed_mode = LEDC_LOW_SPEED_MODE,
        .hpoint     = 0,
        .timer_sel  = LEDC_TIMER_0
    };
    ledc_channel_config(&ledc_channel);
    
    // Initialize fade service.
    ledc_fade_func_install(0);

    while (1) {
        ledc_set_fade_with_time(ledc_channel.speed_mode,ledc_channel.channel, 8000, 3000);
        ledc_fade_start(ledc_channel.speed_mode,ledc_channel.channel, LEDC_FADE_NO_WAIT);
        vTaskDelay(3000 / portTICK_PERIOD_MS);
    }
}

上面的例子是一个通道输出,一个LED灯,初始化的时候占空比为0,起初LED灯是最亮的,然后目标占空比为 8000(分辨率为LEDC_TIMER_13_BIT,最大值8192),设置在 3000ms 内完成渐变。

上面的例子烧录后,可以看到LED 灯在 3s 内由亮变暗,不会熄灭,需要设置为 8192 才会完全灭。

只是上面只会执行一次,那么需要每次都由亮便变灭,就需要在渐变前,把占空比设置为0,如下:

在这里插入图片描述

根据上面的测试,所以一个完成的呼吸灯程序,应该是下面这样的:

在这里插入图片描述

2.2 ESP32-C3 与 ESP32 LEDC的区别

为什么区别放在这里,因为这些区别都是通过示例代码测试,自己修改配置和看底层驱动判断过的。

2.2.1 通道数量

在前面基础介绍中有提到过,ESP32-C3的PWM通道只有6个, ESP32是8个。这个在 ESP32­C3 技术参考手册 中也有提到。

2.2.2 速度模式

在示例原本的程序中,我们看到如果是使用ESP32-C3,都是使用的LEDC_LOW_SPEED_MODE低速模式,我们可以看到ledc_mode_t结构体的定义:

在这里插入图片描述

在官网介绍的时候提到过 高速模式:

在

但是在 ESP32­C3 技术参考手册 中没有关于高速模式的说明(我没有找到= =!),然后测试过程我试着把速度模式设置为高速:

.speed_mode = LEDC_HIGH_SPEED_MODE,           // timer mode

确实是报错了。基本说明 ESP32-C3 的PWM不支持高速模式

然后在ESP32芯片的配置文件下是能够找到定义,他确实可以使用高速通道(通过代码判断是因为代码驱动是官方提供的,肯定是根据芯片手册来写的驱动 ):

在这里插入图片描述

在 ESP32-C3 配置文件下没有相关宏定义:

在这里插入图片描述

2.2.3 分辨率

对于分辨率结构体ledc_timer_bit_t,不同芯片也有不同支持的分辨率:

在这里插入图片描述

对于目前我们使用的 ESP32-C3 而言,最大只能支持到14位:

在这里插入图片描述

而 ESP32 能够支持到20位:

在这里插入图片描述

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ESP32-C3定时器开发文档 ESP32-C3是一款低功耗、高性能的Wi-Fi和蓝牙双模SoC,它集成了多个定时器,可以用于各种应用场景,如PWM控制、定时中断、计时等。本文将介绍ESP32-C3定时器的使用方法。 一、ESP32-C3定时器的类型 ESP32-C3有四种类型的定时器,分别为:通用定时器、高精度定时器、看门狗定时器、RTC定时器。 1.通用定时器 ESP32-C3有两个通用定时器,可以用于PWM控制、定时中断、计时等。这两个定时器分别为定时器0和定时器1,每个定时器有16位的自由运行计数器和一个16位的比较器。通用定时器的主要特点如下: - 可以配置为定时器或计数器 - 支持自由运行计数器和比较器 - 支持自动重载计数器 - 支持PWM输出 - 支持定时中断 2.高精度定时器 ESP32-C3有一个高精度定时器,可以用于需要高精度计时的应用场景。这个定时器是单向计时器,可以自由设置计时周期和定时中断时间。高精度定时器的主要特点如下: - 可以设置自由运行计数器的计数周期 - 可以设置定时中断时间 - 支持单向计时模式 - 支持自动重载计数器 3.看门狗定时器 ESP32-C3有一个看门狗定时器,可以用于应用程序中的异常保护。当应用程序出现异常时,看门狗定时器会自动重启系统。看门狗定时器的主要特点如下: - 可以设置看门狗定时器的计数周期 - 支持看门狗定时器中断 - 支持自动重载计数器 4.RTC定时器 ESP32-C3有一个RTC定时器,可以用于实时时钟应用。RTC定时器的主要特点如下: - 可以设置RTC计数器的计数周期 - 支持RTC定时器中断 - 支持自动重载计数器 二、ESP32-C3定时器的使用步骤 1.初始化定时器 在使用定时器前,需要先初始化定时器。以定时器0为例,初始化代码如下: // 配置定时器0的参数 timer_config_t timer_cfg = { .divider = 16, // 定时器分频系数 .counter_dir = TIMER_COUNT_UP, // 定时器计数器方向 .counter_en = TIMER_PAUSE, // 定时器计数器是否启动 .alarm_en = TIMER_ALARM_EN, // 定时器报警是否启动 .auto_reload = TIMER_AUTORELOAD_EN, // 定时器是否自动重载 .counter_bit_width = TIMER_DATA_WIDTH_16BIT, // 定时器计数器位宽 .alarm_value = 10000, // 定时器报警值 }; // 初始化定时器0 timer_init(TIMER_GROUP_0, TIMER_0, &timer_cfg); 2.启动定时器 初始化定时器后,需要启动定时器才能开始计时。以定时器0为例,启动代码如下: timer_start(TIMER_GROUP_0, TIMER_0); 3.设置定时器中断 如果需要在定时器到达一定时间后触发中断,则需要设置定时器中断。以定时器0为例,设置中断代码如下: // 配置定时器0中断参数 timer_isr_t isr_cfg = { .func = timer0_isr, // 定时器中断处理函数 .arg = NULL, // 中断处理函数参数 }; // 注册定时器0中断 timer_isr_register(TIMER_GROUP_0, TIMER_0, &isr_cfg, NULL, 0); 4.停止定时器 如果需要停止定时器,则可以使用以下代码: timer_pause(TIMER_GROUP_0, TIMER_0); 5.重启定时器 如果定时器已经停止,则可以使用以下代码重启定时器: timer_start(TIMER_GROUP_0, TIMER_0); 6.设置定时器报警值 如果需要定时器到达一定时间后触发报警,则需要设置定时器报警值。以定时器0为例,设置报警值代码如下: timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 20000); 7.获取定时器计数器值 如果需要获取定时器的计数器值,则可以使用以下代码: uint64_t timer_value; timer_get_counter_value(TIMER_GROUP_0, TIMER_0, &timer_value); 8.清除定时器中断标志 当定时器中断被触发后,需要清除中断标志才能继续触发中断。以定时器0为例,清除中断标志代码如下: timer_group_clr_intr_status(TIMER_GROUP_0, TIMER_0); 三、ESP32-C3定时器应用示例 以下是一个使用定时器0实现PWM输出的示例代码: #include "driver/timer.h" #define LED_PIN 2 #define PWM_FREQ 1000 #define PWM_MAX_DUTY 1023 void timer0_isr(void *arg) { timer_group_clr_intr_status(TIMER_GROUP_0, TIMER_0); static uint32_t pwm_count = 0; static uint16_t pwm_duty = 0; pwm_count++; if (pwm_count >= (1000000 / PWM_FREQ)) { pwm_count = 0; pwm_duty++; if (pwm_duty > PWM_MAX_DUTY) { pwm_duty = 0; } timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, (1000000 / PWM_FREQ)); timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0); ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, pwm_duty); ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0); } } void app_main() { // 初始化LED gpio_pad_select_gpio(LED_PIN); gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT); gpio_set_level(LED_PIN, 0); // 配置定时器0的参数 timer_config_t timer_cfg = { .divider = 16, // 定时器分频系数 .counter_dir = TIMER_COUNT_UP, // 定时器计数器方向 .counter_en = TIMER_PAUSE, // 定时器计数器是否启动 .alarm_en = TIMER_ALARM_EN, // 定时器报警是否启动 .auto_reload = TIMER_AUTORELOAD_EN, // 定时器是否自动重载 .counter_bit_width = TIMER_DATA_WIDTH_16BIT, // 定时器计数器位宽 .alarm_value = (1000000 / PWM_FREQ), // 定时器报警值 }; // 初始化定时器0 timer_init(TIMER_GROUP_0, TIMER_0, &timer_cfg); // 注册定时器0中断 timer_isr_t isr_cfg = { .func = timer0_isr, // 定时器中断处理函数 .arg = NULL, // 中断处理函数参数 }; timer_isr_register(TIMER_GROUP_0, TIMER_0, &isr_cfg, NULL, 0); // 设置PWM输出 ledc_timer_config_t ledc_timer_cfg = { .duty_resolution = LEDC_TIMER_10_BIT, // PWM位宽 .freq_hz = PWM_FREQ, // PWM频率 .speed_mode = LEDC_LOW_SPEED_MODE, // PWM速度模式 .timer_num = LEDC_TIMER_0, // PWM定时器号 .clk_cfg = LEDC_AUTO_CLK, // PWM时钟配置 }; ledc_timer_config(&ledc_timer_cfg); ledc_channel_config_t ledc_channel_cfg = { .channel = LEDC_CHANNEL_0, // PWM通道号 .duty = 0, // PWM占空比 .gpio_num = LED_PIN, // PWM输出引脚 .speed_mode = LEDC_LOW_SPEED_MODE, // PWM速度模式 .timer_sel = LEDC_TIMER_0, // PWM定时器号 }; ledc_channel_config(&ledc_channel_cfg); ledc_fade_func_install(0); // 启动定时器0 timer_start(TIMER_GROUP_0, TIMER_0); }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

矜辰所致

您们的鼓励是我奋斗的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值