侧边栏壁纸
  • 累计撰写 125 篇文章
  • 累计创建 16 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录
ESP32   

ESP32-LED Control

概述

LED控制器(LEDC)主要用于控制LED的亮度,当然它也可以用于生成其他目的的PWM信号。它具有16个通道,可以生成独立的波形,这些波形可以用于驱动RGB LED器件。

LEDC的一半通道在高速模式下运行。此模式在硬件中实现,并提供PWM占空比的自动且无干扰的更改。通道的另一半在低速模式下运行,更改的时刻取决于应用软件。每组通道也可以使用不同的时钟源,但是LEDC驱动程序尚不支持此功能。

并且PWM控制器可以自动逐渐增加或减少占空比,使得允许衰减不会受到任何处理器干扰。

简单而言,这一功能就是PWM波的产生、控制器。

架构

LED_PWM 内部有 8 个高速通道以及 8 个低速通道。高速通道有 4个高速时钟模块,可以从中任选一个 h_timerx。低速通道有 4 个低速时钟模块,可以从中任选一个 l_timerx。

高速定时器的时钟源采用了 REF_TICKAPB_CLK,低速定时器采用了 REF_TICKSLOW_CLOCK

流程框图分析


这是其中某个高速通道的框图,表示一个 PWM 通道和它选取的分频器;在该情况下,一个高速通道配有一个高速分频器。在前面的定时器学习中已经讲过有关分频器的相关参数与用法了,这里不再赘述。

也就是该框图的左侧为定时器,通过分频器(Divder)与计数器(Counter)的设置,计数器中的数值不断的累计,达到最大值后重置,继续重新累加。而这个不断重复累加的计数器的值,就是PWM波产生的关键。

产生PWM波

上图中,左侧我们知道是定时器,右侧则是PWM产生通道,有两个比较器,即high_level_comparator 以及 low_level_comparator

high_level_comparator的比较值是 hpoint,当计数器的值达到 hpoint 时,输出信号翻转为高电平。

low_level_comparator 的比较值是 lpoint,当计数器的值等于 lpoint 时,输出信号翻转为低电平。

所以 hpointlpoint 共同决定了PWM波的占空比,我们可以通过控制这两个数值的差,控制LEDC的亮度。

Arduino层编程

好了,前面不管你理没理解和编程基本没有几毛钱关系,不影响~

只要有以下的大致参数设置思路即可:

  1. 开启定时器,设置定时器的分频系数(这里也不用你算,直接填频率)和计数器值位数(这里理解为精度)。
  2. 将PWM通道绑定到具体的一个引脚上。
  3. 设置占空比

且在输出过程中也可以随时改变占空比、频率等系数。

初始化( ledcSetup)

// channel(通道):0-15 	freq (频率) resolution_bits(计数器精度): 1-20
double  ledcSetup(uint8_t channel, double freq, uint8_t resolution_bits);

绑定引脚(ledcAttachPin)

void   ledcAttachPin(uint8_t pin, uint8_t channel); // 绑定引脚
void   ledcDetachPin(uint8_t pin); // 解绑引脚

设置占空比(ledcWrite)

resolution_bits的输入为X,duty的值是:小于2x-1
且值越大,占空比越小。占空比:(2x-1-duty)/2x-1

void   ledcWrite(uint8_t channel, uint32_t duty);

改频率

程序中可以修改频率

double  ledcWriteTone(uint8_t channel, double freq);

这里是预制的音乐频率,可以直接修改,驱动扬声器

double  ledcWriteNote(uint8_t channel, note_t note, uint8_t octave);

参数读取

读取当前设置的duty值与频率

uint32_t    ledcRead(uint8_t channel);
double      ledcReadFreq(uint8_t channel);

例子(LED小灯)

#include <Arduino.h>
// 使用0号通道
#define LEDC_CHANNEL_0     0

// 定时器精度为15位
#define LEDC_TIMER_13_BIT  15

// 频率
#define LEDC_BASE_FREQ     5000

// 输出引脚
#define LED_PIN            18

int brightness = 0;    // LED亮度
int fadeAmount = 5;    // 衰减值

// 将值映射到0-255之间,注意32766是2^15-1
void ledcAnalogWrite(uint8_t channel, uint32_t value, uint32_t valueMax = 255) {
  // calculate duty, 8191 from 2 ^ 13 - 1
  uint32_t duty = (32766/ valueMax) * min(value, valueMax);

  // 设置占空比
  ledcWrite(channel, duty);
}

void setup() {
  // Setup timer and attach timer to a led pin
  ledcSetup(LEDC_CHANNEL_0, LEDC_BASE_FREQ, LEDC_TIMER_13_BIT);
  ledcAttachPin(LED_PIN, LEDC_CHANNEL_0);
}

void loop() {
  ledcAnalogWrite(LEDC_CHANNEL_0, brightness);

  brightness = brightness + fadeAmount;

  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  
  delay(30);
}

0

评论区