ESP32C3开发-PWM实现呼吸灯

16 篇文章 2 订阅
14 篇文章 5 订阅


前言

本次将学习ESP32C3的LED PWM,由于芯片硬件的限制ESP32C3仅支持LED PWM,不支持MCPWM和PCNT功能,但基本的PWM调制功能还是齐全的,除了控制官方开发的三色灯,还可以实现呼吸灯、舵机的控制,这次就是要实现基于ESP32C3的LED PWM呼吸灯的功能开发。


一、PWM

1.PWM介绍

PWM是英文“Pulse Width Modulation”的缩写,中文叫“脉冲宽度调制”,简称“脉宽调制”。
脉冲宽度调制主要是调整一个方波脉冲周期内高电平的占空比时间,例如:5KHz的脉冲,周期是200us,当高电平/低电平各占100us时,表示当前脉冲的占空比为50%,如下图:
在这里插入图片描述
脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断 (OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
在这里插入图片描述

2.PWM的应用

PWM主要由MCU控制芯片产生并用于控制外接的设备,也存在其他设备产生PWM输入给MCU进行分析。被广泛使用的STM32系列单片机可以通过定时器产生PWM调制方波。
PWM应用:电机调速、呼吸灯、舵机控制等。

二、ESP32C3的LED PWM

1.概述

ESP32C3受硬件的限制只有LED PWM ,LED PWM 控制器用于生成控制 LED 的脉冲宽度调制信号 (PWM),具有占空比自动渐变等专门功能。该外设也可成生成 PWM 信号用作其他用途。

2.特性

• 有六个独立的 PWM 生成器(即六个通道)
• 四个独立定时器,可实现小数分频
• 占空比自动渐变(即 PWM 信号占空比可逐渐增加或减小,无须处理器干预),渐变完成时产生中断
• PWM 输出信号相位可调节
• 低功耗模式 (Light-sleep mode) 下可输出 PWM 信号
• PWM 最大精度为 14 位
架构如图:
在这里插入图片描述
四个定时器可独立配置(可配置时钟分频器和计数器最大值),每个定时器内部有一个时基计数器(即基于基准时钟周期计数的计数器)。每个 PWM 生成器在四个定时器中择一,以该定时器的计数值为基准生成 PWM 信号。
在官方的工程库文件中有定义定时器的选择:

typedef enum {
    LEDC_TIMER_0 = 0, /*!< LEDC timer 0 */
    LEDC_TIMER_1,     /*!< LEDC timer 1 */
    LEDC_TIMER_2,     /*!< LEDC timer 2 */
    LEDC_TIMER_3,     /*!< LEDC timer 3 */
    LEDC_TIMER_MAX,
} ledc_timer_t;

3.相关配置部分

LED PWM 控制器的每个定时器内部都有一个时基计数器。下图(定时器和 PWM 生成器功能模块图)中时基计数器使用的时钟信号称为 ref_pulsex。所有定时器使用同一个时钟源信号 LEDC_CLKx,该时钟源信号经分频器分频后产生 ref_pulsex 供计数器使用。
在这里插入图片描述
时钟源信号:
有三个时钟源信号可以选择: APB_CLK、 RC_FAST_CLK 和 XTAL_CLK。为 LEDC_CLKx 选择时钟源信号的配置如下:
• APB_CLK:将 LEDC_APB_CLK_SEL[1:0] 置 1
• RC_FAST_CLK:将 LEDC_APB_CLK_SEL[1:0] 置 2
• XTAL_CLK:将 LEDC_APB_CLK_SEL[1:0] 置 3
之后, LEDC_CLKx 信号会进入时钟分频器。
分频器:
分频器(Divider):这是一个18位的分频器,用于对所选择的时钟进行分频,分频器的分频系数是可设置的分为:整数部分和小数部分。
分频系数=在这里插入图片描述
A为整数部分:LEDC_TIMERx_CONF_REG寄存器LEDC_CLK_DIV_TIMERx 字段的高 10 位,B为小数部分:LEDC_TIMERx_CONF_REG寄存器LEDC_CLK_DIV_TIMERx 字段的低 8 位。
下图展示分频系数非整数时,LEDC_CLKx 时钟周期和ref_pulsex 时钟脉冲的关系。
在这里插入图片描述
计数器:
LED PWM 控制器中定时器的计数器是14位的,所以PWM信号的最大精确度为 14 位。计数器最大可计数至 2**LEDC_T IMERx_DUT Y _RES − 1,然后溢出重新从 0 开始计数。软件可以读取、复位、暂停计数器。

计数器可在每次溢出时触发 (LEDC_TIMERx_OVF_INT) 中断,这个中断为硬件自动产生,不需要配置。计数器也可配置为在溢出 LEDC_OV F_NUM_CHn + 1) 次时触发 LEDC_OVF_CNT_CHn_INT 中断。

PWM 生成器输出信号 sig_outn 的频率取决于定时器的时钟源 LEDC_CLKx、时钟分频系数LEDC_CLK_DIV_TIMERx 以及计数器的计数范围 LEDC_TIMERx_DUTY_RES:
计算公式:
在这里插入图片描述
在运行时改变计数器的最大值,需先置位 LEDC_TIMERx_DUTY_RES 字段,然后置位 LEDC_TIMERx_PARA_UP字段。新的配置在计数器下一次溢出时生效。如果重新配置 LEDC_OVF_CNT_EN_CHn 字段,需置位 LEDC_PARA_UP_CHn应用新配置。总之,更改配置时需置位 LEDC_TIMERx_PARA_UP 或 LEDC_PARA_UP_CHn 应用新配置。LEDC_TIMERx_PARA_UP 和 LEDC_PARA_UP_CHn字段由硬件自动清除。
PWM生成器:
通过配置PWM生成器可调节输出脉冲的占空比。
每个 PWM 生成器主要包括一个高低电平比较器和两个选择器。 PWM 生成器将定时器的 14位计数值 (Timerx_cnt) 与高低电平比较器的值 Hpointn 和 Lpointn 比较。如果定时器的计数值等于 Hpointn 或Lpointn, PWM 信号可以输出高低电平:
• 如果 Timerx_cnt == Hpointn,则 sig_outn 为 1。
• 如果 Timerx_cnt == Lpointn,则 sig_outn 为 0。
下图展示了如何使用 Hpointn 和 Lpointn 生成占空比固定的 PWM 信号
在这里插入图片描述
每当所选定时器的计数器溢出时, PWM 生成器 (PWMn) 的 Hpointn 值更新为 LEDC_HPOINT_CHn。 Lpointn 的值同样在计数器每次溢出时更新,为 LEDC_DUTY_CHn[18:4] 和 LEDC_HPOINT_CHn 的和。通过配置 LEDC_DUTY_CHn[18:4]和 LEDC_HPOINT_CHn 两个字段,可设置 PWM 输出的相对相位和占空比。
在运行时,如果重新配置 LEDC_TIMER_SEL_CHn、LEDC_HPOINT_CHn、LEDC_DUTY_CHn[18:4] 和 LEDC_SIG_OUT_EN_CHn字段,需置位 LEDC_PARA_UP_CHn 应用新配置。新配置在计数器下次溢出时生效。 LEDC_TIMERx_PARA_UP字段由硬件自动清除。如下代码:

	// Set duty to 50%
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));
    // Update duty to apply the new value
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));

中断
• LEDC_OVF_CNT_CHn_INT:定时器计数器溢出 (LEDC_OVF_NUM_CHn + 1) 次且寄存器 LEDC_OVF_CNT_EN_CHn
置 1 时触发中断。
• LEDC_DUTY_CHNG_END_CHn_INT: PWM 生成器渐变完成后触发中断。
• LEDC_TIMERx_OVF_INT:定时器达到最大计数值时触发中断。

三、ESP32C3呼吸灯

采用PWM调节来实现LED灯电压的调节,从而实现呼吸灯的效果。
相关宏定义的定义

#define LEDC_TIMER              LEDC_TIMER_0
#define LEDC_MODE               LEDC_LOW_SPEED_MODE
#define LEDC_OUTPUT_IO          (4) // Define the output GPIO
#define LEDC_CHANNEL            LEDC_CHANNEL_0
#define LEDC_DUTY_RES           LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
#define LEDC_DUTY               (205)  // Set duty to 2.5%. ((2 ** 13) - 1) * 2.5% = 204.775
#define LEDC_FREQUENCY          (1000)    // Frequency in Hertz. Set frequency at 50 Hz
#define SERVO_MAX_DEGREE        (100)   // Maximum angle in degree upto which servo can rotate

初始化定时器和PWM输出

static void ledc_pwm_init(void)
{
    // Prepare and then apply the LEDC PWM timer configuration
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_MODE,
        .timer_num        = LEDC_TIMER,
        .duty_resolution  = LEDC_DUTY_RES,
        .freq_hz          = LEDC_FREQUENCY,  // Set output frequency at 5 kHz
        .clk_cfg          = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel = {
        .speed_mode     = LEDC_MODE,
        .channel        = LEDC_CHANNEL,
        .timer_sel      = LEDC_TIMER,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LEDC_OUTPUT_IO,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));
}

主函数

void app_main(void)
{
    // Set the LEDC peripheral configuration
    ledc_pwm_init();

    while (1) {
        for (uint32_t angle = 0; angle < (SERVO_MAX_DEGREE + 1); angle = angle + 5) {
            uint32_t led_duty = (8191 * angle) / 100;
            printf("Angle of rotation: %d,led_duty: %d\r\n", angle, led_duty);
            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_duty);
            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
            vTaskDelay(pdMS_TO_TICKS(200)); 
        }
        for (uint32_t angle = 100; angle > 0; angle = angle - 5) {
            uint32_t led_duty = (8191 * angle) / 100;
            printf("Angle of rotation: %d,led_duty: %d\r\n", angle, led_duty);
            ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_duty);
            ledc_update_duty(LEDC_MODE, LEDC_CHANNEL);
            vTaskDelay(pdMS_TO_TICKS(200));
        }
    }
}

调试现象
在这里插入图片描述

总结

本次主要是开发ESP32C3 LED PWM功能,实现呼吸灯。掌握PWM是机器控制的第一步,电机的调速离不开PWM。

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值