提示:本博客作为学习笔记,有错误的地方希望指正
一、ESP32LEDC介绍
1.1、概述
参考资料:ESP IDF编程手册V4.4
LED 控制器 (LEDC) 主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。 该控制器有 16 路通道,可以产生独立的波形来驱动 RGB LED 等设备。
LEDC 通道共有两组,分别为 8 路高速通道和 8 路低速通道。高速通道模式在硬件中实现,可以自动且无干扰地改变 PWM 占空比。低速通道模式下,PWM 占空比需要由软件中的驱动器改变。每组通道都可以使用不同的时钟源。
LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实现亮度和颜色渐变。
1.2、功能概览
设置 LEDC 通道在 高速模式或低速模式 下运行,需要进行如下配置:
- 定时器配置 指定 PWM 信号的频率和占空比分辨率。
- 通道配置 绑定定时器和输出 PWM 信号的 GPIO。
- 改变 PWM 信号 输出 PWM 信号来驱动 LED。可通过软件控制或使用硬件渐变功能来改变 LED 的亮度。
另一个可选步骤是可以在渐变终端设置一个中断。
1.2.1、LEDC定时器配置
要设置定时器,可调用函数 ledc_timer_config(),并将包括如下配置参数的数据结构 ledc_timer_config_t 传递给该函数:
定时器配置结构题如下所示:
//ledc_timer_config功能的LEDC Timer配置参数
typedef struct {
ledc_mode_t speed_mode; /* !< LEDC高速模式或低速模式*/
union {
ledc_timer_bit_t duty_resolution; /* !< LEDC通道分辨率*/
ledc_timer_bit_t bit_num __attribute__((deprecated));/* !ESP-IDF 3.0弃用。这是'duty_resolution'的别名,用于向后兼容ESP-IDF 2.1 */
};
ledc_timer_t timer_num; /* !<通道的定时器源(0 - 3)*/
uint32_t freq_hz; /* !< LEDC定时器频率(Hz) */
ledc_clk_cfg_t clk_cfg; /* !<配置LEDC源时钟。
对于低速通道和高速通道,可以通过LEDC_USE_REF_TICK、LEDC_USE_APB_CLK或LEDC_AUTO_CLK指定源时钟。
对于低速通道,您也可以使用LEDC_USE_RTC8M_CLK指定源时钟,在这种情况下,所有低速通道的源时钟必须是RTC8M_CLK*/
} ledc_timer_config_t;
频率和占空比分辨率相互关联。PWM 频率越高,占空比分辨率越低,反之亦然。如果 API 不是用来改变 LED 亮度,而是用于其它目的,这种相互关系可能会很重要。
时钟源同样可以限制PWM频率。选择的时钟源频率越高,可以配置的PWM频率上限就越高。
LEDC可以有3个定时器可以选择。
L
E
D
C
时
钟
源
特
性
LEDC 时钟源特性
LEDC时钟源特性
时钟名称 | 时钟频率 | 速度模式 | 时钟功能 |
---|---|---|---|
APB_CLK | 80 MHz | 高速 / 低速 | / |
REF_TICK | 1 MHz | 高速 / 低速 | 支持动态调频(DFS)功能 |
RTC8M_CLK | ~8 MHz | 低速 | 支持动态调频(DFS)功能,支持Light-sleep模式 |
注解:如果 ESP32 的定时器选用了RTCxM_CLK作为其时钟源,驱动会通过内部校准来得知这个时钟源的实际频率。这样确保了输出PWM信号频率的精准性。
1.2.2、LEDC通道配置
定时器设置好后,请配置所需的通道(ledc_channel_t )。配置通道需调用函数 ledc_channel_config()。
通道的配置与定时器设置类似,需向通道配置函数传递包括通道配置参数的结构体 ledc_channel_config_t 。
此时,通道会按照 ledc_channel_config_t 的配置开始运作,并在选定的 GPIO 上生成由定时器设置指定的频率和占空比的 PWM 信号。在通道运作过程中,可以随时通过调用函数 ledc_stop() 将其暂停。
LEDC通道配置参数结构体
//配置ledc_channel_config功能的LEDC通道参数
typedef struct {
int gpio_num; /* !< LEDC输出gpio_num,如果要使用gpio16, gpio_num = 16 */
ledc_mode_t speed_mode; /* !< LEDC speed speed_mode,高速模式或低速模式*/
ledc_channel_t channel; /* !< LEDC通道(0 - 7)*/
ledc_intr_type_t intr_type; /* !< 配置中断,淡出中断启用或淡出中断禁用*/
ledc_timer_t timer_sel; /* !< 选择通道的定时器源(0 - 3)*/
uint32_t duty; /* !< LEDC通道负载,负载设定范围为[0,(2**duty_resolution)] */
int hpoint; /* !< LEDC通道hpoint值,最大值为0xfffff */
struct {
unsigned int output_invert: 1; /*!< 使能(1)或失能(0)gpio输出反转 */
} flags; /*!< LEDC标志 */
} ledc_channel_config_t;
1.3、LEDC改变 PWM 信号
通道开始运行、生成具有恒定占空比和频率的 PWM 信号之后,有几种方式可以改变该信号。驱动 LED 时,主要通过改变占空比来变化光线亮度。
以下介绍如何使用软件和硬件改变占空比。如有需要,PWM 信号的频率也可更改。
1.3.1、使用软件改变 PWM 占空比
调用函数 ledc_set_duty() 可以设置新的占空比。之后,调用函数 ledc_update_duty() 使新配置生效。可使用ledc_get_duty()查看当前设置的占空比。
另外一种设置占空比和其他通道参数的方式是调用 通道配置 一节提到的函数 ledc_channel_config()。
传递给函数的占空比数值范围取决于选定的 duty_resolution,应为 0 至 (2 ** duty_resolution) - 1。例如,如选定的占空比分辨率为 10,则占空比的数值范围为 0 至 1023。此时分辨率为 ~0.1%。
1.3.2、使用硬件改变 PWM 占空比
LED PWM 控制器硬件可逐渐改变占空比的数值。要使用此功能,需用函数 ledc_fade_func_install() 使能渐变,之后用下列可用渐变函数之一配置:
- ledc_set_fade_with_time()
- ledc_set_fade_with_step()
- ledc_set_fade()
最后需要调用 ledc_fade_start() 开启渐变。渐变可以在阻塞或非阻塞模式下运行,具体区别请查看 ledc_fade_mode_t。需要特别注意的是,不管在哪种模式下,下一次渐变或单次占空比配置的指令生效都必须等到前一次渐变结束。由于 ESP32 的硬件限制,在渐变达到原先预期的占空比前想要中止本次渐变是不被支持的。
此外,在使能渐变后,每个通道都可以额外通过调用 ledc_cb_register() 注册一个回调函数用以获得渐变完成的事件通知。
如不需要渐变和渐变中断,可用函数 ledc_fade_func_uninstall() 关闭。
1.4、改变 PWM 频率
LED PWM 控制器 API 有多种方式即时改变 PWM 频率:
- 通过调用函数 ledc_set_freq() 设置频率。可用函数 ledc_get_freq() 查看当前频率。
- 通过调用函数 ledc_bind_channel_timer() 将其他定时器绑定到该通道来改变频率和占空比分辨率。
- 通过调用函数 ledc_channel_config() 改变通道的定时器。
1.5、控制 PWM 的更多方式
有一些较底层的定时器特定函数可用于更改 PWM 设置:
- ledc_timer_set()
- ledc_timer_rst()
- ledc_timer_pause()
- ledc_timer_resume()
前两个功能可通过函数 ledc_channel_config() 在后台运行,在定时器配置后启动。
1.6、使用中断
配置 LED PWM 控制器通道时,可在 ledc_channel_config_t 中选取参数 ledc_intr_type_t ,在渐变完成时触发中断。
要注册处理程序来处理中断,可调用函数 ledc_isr_register()。
1.7、LED PWM 控制器高速和低速模式
高速模式的优点是可平稳地改变定时器设置。也就是说,高速模式下如定时器设置改变,此变更会自动应用于定时器的下一次溢出中断。而更新低速定时器时,设置变更应由软件显式触发。LED PWM 驱动的设置将在硬件层面被修改,比如在调用函数 ledc_timer_config() 或 ledc_timer_set() 时。
1.8、频率和占空比分辨率支持范围
LED PWM 控制器主要用于驱动 LED。该控制器 PWM 占空比设置的分辨率范围较广。比如,PWM 频率为 5 kHz 时,占空比分辨率最大可为 13 位。这意味着占空比可为 0 至 100% 之间的任意值,分辨率为~0.012%(2 ** 13 = 8192 LED 亮度的离散电平)。然而,这些参数取决于为 LED PWM 控制器定时器计时的时钟信号,LED PWM 控制器为通道提供时钟。
LED PWM 控制器可用于生成频率较高的信号,足以为数码相机模组等其他设备提供时钟。此时,最大频率可为 40 MHz,占空比分辨率为 1 位。也就是说,占空比固定为 50%,无法调整。
LED PWM 控制器 API 会在设定的频率和占空比分辨率超过 LED PWM 控制器硬件范围时报错。例如,试图将频率设置为 20 MHz、占空比分辨率设置为 3 位时,串行端口监视器上会报告如下错误:
E (196) ledc: requested frequency and duty resolution cannot be achieved, try reducing freq_hz or duty_resolution. div_param=128
此时,占空比分辨率或频率必须降低。比如,将占空比分辨率设置为 2 会解决这一问题,让占空比设置为 25% 的倍数,即 25%、50% 或 75%。
如设置的频率和占空比分辨率低于所支持的最低值,LED PWM 驱动器也会反映并报告,如:
E (196) ledc: requested frequency and duty resolution cannot be achieved, try increasing freq_hz or duty_resolution. div_param=128000000
占空比分辨率通常用 ledc_timer_bit_t 设置,范围是 10 至 15 位。如需较低的占空比分辨率(上至 10,下至 1),可直接输入相应数值。
二、硬件设计
任何ESP32开发版即可支持。
三、实现代码
3.1、实现LEDC基本控制-1
实现功能,实现LED或者电机以及其他可以支持pwm信号控制器件的控制。
初始化流程:
#include <stdio.h>
#include "driver/ledc.h"
#include "esp_err.h"
#define LEDC_TIMER LEDC_TIMER_0 //LEDC定时器
#define LEDC_MODE LEDC_LOW_SPEED_MODE //LEDC的速度模式
#define LEDC_OUTPUT_IO (5) //LEDC绑定引脚
#define LEDC_CHANNEL LEDC_CHANNEL_0 //LEDC通道
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT //LEDC占空比分辨率
#define LEDC_DUTY (4095) //LEDC占空比
#define LEDC_FREQUENCY (5000) //LEDC频率 5 kHz
static void example_ledc_init(void)
{
//LEDC定时器配置
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_MODE, //设置定时器低速模式
.timer_num = LEDC_TIMER, //设置定时器0
.duty_resolution = LEDC_DUTY_RES, //设置定时器分辨率 13位
.freq_hz = LEDC_FREQUENCY, //设置定时器频率 5kHz
.clk_cfg = LEDC_AUTO_CLK //设置定时器时钟选择
};
ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); //设置定时器配置
//配置LEDC通道
ledc_channel_config_t ledc_channel = {
.speed_mode = LEDC_MODE, //设置通道模式低速模式
.channel = LEDC_CHANNEL, //设置LEDC通道0
.timer_sel = LEDC_TIMER, //设置LEDC定时器
.intr_type = LEDC_INTR_DISABLE, //设置LEDC中断类型
.gpio_num = LEDC_OUTPUT_IO, //设置LEDCGPIO引脚
.duty = 0, // Set duty to 0% //设置占空比
.hpoint = 0 //LEDC通道hpoint值
};
ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));//配置LEDC通道参数
}
void app_main(void)
{
// 配置LEDC外设
example_ledc_init();
// 设置占空比 50% 2^13 = 8192 4096即占一半,占空比50%
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, LEDC_DUTY));
// 更新占空比
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
}
3.2、实现LEDC硬件控制PWM输出
实现功能,实现LED或者电机以及其他可以支持pwm信号控制器件的控制。在这个示例中主要有使用硬件控制PWM的输出,但是ESP32不能像STM32一样的打断硬件输出PWM的设置成当前输入的PWM的值,因此只能等待硬件PWM输出时间结束才可以执行下一次设置pwm的值,可以使用硬件pwm输出多长时间,时间到达的时候就会产生一个ledc fade中断事件,这里使用信号量的方式,等待esp32硬件pwm
设置好时间后,到达规定的时间会产生中断,然后在中断中发送信号量,在循环中接收到型号量的时候就继续执行当前的程序,没有接收到信号量的话就一直等待信号量的到来。
这个历程有两种方法实现pwm的控制输出,一个是使用硬件的方式,一个是使用软件的方式实现的。
初始化流程:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/ledc.h"
#include "esp_err.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
/*
* 1. 从初始化 LEDC 模块开始:
* 一种。 首先设置 LEDC 的定时器,这决定了频率和 PWM 的分辨率。b。
* 然后设置你要使用的LEDC通道,并与其中一个计时器绑定。
* 2.你需要先安装一个默认的淡入淡出功能,然后你可以使用淡入淡出 API。
* 3.您也可以直接设置目标值班而不褪色。
* 4. 本例使用 GPIO18/19/4/5 作为 LEDC 输出,并且会反复改变职责。
* 5. GPIO18/19 来自高速通道组。GPIO4/5 来自低速通道组。
*/
#if CONFIG_IDF_TARGET_ESP32
#define LEDC_HS_TIMER LEDC_TIMER_0
#define LEDC_HS_MODE LEDC_HIGH_SPEED_MODE
#define LEDC_HS_CH0_GPIO (18)
#define LEDC_HS_CH0_CHANNEL LEDC_CHANNEL_0
#define LEDC_HS_CH1_GPIO (19)
#define LEDC_HS_CH1_CHANNEL LEDC_CHANNEL_1
#endif
#define LEDC_LS_TIMER LEDC_TIMER_1
#define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
#if !CONFIG_IDF_TARGET_ESP32
#define LEDC_LS_CH0_GPIO (18)
#define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
#define LEDC_LS_CH1_GPIO (19)
#define LEDC_LS_CH1_CHANNEL LEDC_CHANNEL_1
#endif
#define LEDC_LS_CH2_GPIO (4)
#define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2
#define LEDC_LS_CH3_GPIO (5)
#define LEDC_LS_CH3_CHANNEL LEDC_CHANNEL_3
#define LEDC_TEST_CH_NUM (4)
#define LEDC_TEST_DUTY (4000)
#define LEDC_TEST_FADE_TIME (3000)
/*
* 当淡入淡出操作结束时会调用这个回调函数
* 仅当您知道它在 ISR 中被调用时才使用回调
* 否则,您可以使用信号量来解除阻塞任务
*/
static bool cb_ledc_fade_end_event(const ledc_cb_param_t *param, void *user_arg)
{
portBASE_TYPE taskAwoken = pdFALSE;
if (param->event == LEDC_FADE_END_EVT) {
SemaphoreHandle_t counting_sem = (SemaphoreHandle_t) user_arg;
xSemaphoreGiveFromISR(counting_sem, &taskAwoken);
}
return (taskAwoken == pdTRUE);
}
void app_main(void)
{
int ch;
//准备和设置定时器的配置将由 LED 控制器使用
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_TIMER_13_BIT, // PWM占空比的分辨率
.freq_hz = 5000, // PWM信号频率
.speed_mode = LEDC_LS_MODE, // 定时器模式
.timer_num = LEDC_LS_TIMER, // 定时器索引
.clk_cfg = LEDC_AUTO_CLK, // 自动选择源时钟
};
//为高速通道设置 timer0 的配置
ledc_timer_config(&ledc_timer);
#ifdef CONFIG_IDF_TARGET_ESP32
//为低速通道准备和设置 timer1 的配置
ledc_timer.speed_mode = LEDC_HS_MODE;
ledc_timer.timer_num = LEDC_HS_TIMER;
ledc_timer_config(&ledc_timer);
#endif
/*
* 准备个人配置用于 LED 控制器的每个通道通过选择:
* - 控制器的通道号
* - 输出占空比,初始设置为 0
* - LED 连接到的 GPIO 编号
* - 速度模式,高或低
* - 定时器服务选定的频道
* 注意:如果不同频道使用一个定时器,然后是这些频道的频率和 bit_num将是相同的
*/
ledc_channel_config_t ledc_channel[LEDC_TEST_CH_NUM] = {
#if CONFIG_IDF_TARGET_ESP32
{
.channel = LEDC_HS_CH0_CHANNEL, //LEDC高速通道0
.duty = 0, //占空比
.gpio_num = LEDC_HS_CH0_GPIO, //绑定gpio位号
.speed_mode = LEDC_HS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_HS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 0 //使能(1)或失能(0)gpio输出反转
},
{
.channel = LEDC_HS_CH1_CHANNEL, //LEDC高速通道1
.duty = 0, //占空比
.gpio_num = LEDC_HS_CH1_GPIO, //绑定gpio位号
.speed_mode = LEDC_HS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_HS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 0 //使能(1)或失能(0)gpio输出反转
},
#else
{
.channel = LEDC_LS_CH0_CHANNEL, //LEDC低速通道0
.duty = 0, //占空比
.gpio_num = LEDC_LS_CH0_GPIO, //绑定gpio位号
.speed_mode = LEDC_LS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_LS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 0 //使能(1)或失能(0)gpio输出反转
},
{
.channel = LEDC_LS_CH1_CHANNEL, //LEDC低速通道1
.duty = 0, //占空比
.gpio_num = LEDC_LS_CH1_GPIO, //绑定gpio位号
.speed_mode = LEDC_LS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_LS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 0 //使能(1)或失能(0)gpio输出反转
},
#endif
{
.channel = LEDC_LS_CH2_CHANNEL, //LEDC低速通道2
.duty = 0, //占空比
.gpio_num = LEDC_LS_CH2_GPIO, //绑定gpio位号
.speed_mode = LEDC_LS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_LS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 1 //使能(1)或失能(0)gpio输出反转
},
{
.channel = LEDC_LS_CH3_CHANNEL, //LEDC低速通道3
.duty = 0, //占空比
.gpio_num = LEDC_LS_CH3_GPIO, //绑定gpio位号
.speed_mode = LEDC_LS_MODE, //高速模式
.hpoint = 0, //LEDC通道hpoint值
.timer_sel = LEDC_LS_TIMER, //选择通道的定时器源(0 - 3)
.flags.output_invert = 1 //使能(1)或失能(0)gpio输出反转
},
};
// Set LED Controller with previously prepared configuration
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_channel_config(&ledc_channel[ch]); //配置通道
}
// Initialize fade service.
ledc_fade_func_install(0); //安装LEDC淡出功能。此功能将占用LEDC模块的中断。
ledc_cbs_t callbacks = {
.fade_cb = cb_ledc_fade_end_event //设置中断回调函数
};
//创建互斥信号量
SemaphoreHandle_t counting_sem = xSemaphoreCreateCounting(LEDC_TEST_CH_NUM, 0);
//LEDC回调注册功能
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
ledc_cb_register(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, &callbacks, (void *) counting_sem);
}
while (1) {
printf("1. LEDC fade up to duty = %d\n", LEDC_TEST_DUTY);
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
//设定LEDC淡出功能,具有有限的时间
ledc_set_fade_with_time(ledc_channel[ch].speed_mode,ledc_channel[ch].channel, LEDC_TEST_DUTY, LEDC_TEST_FADE_TIME);
//启动LEDC衰落
ledc_fade_start(ledc_channel[ch].speed_mode,ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
}
//获取信号量,信号量无效的话则无限堵塞
for (int i = 0; i < LEDC_TEST_CH_NUM; i++) {
xSemaphoreTake(counting_sem, portMAX_DELAY);
}
printf("2. LEDC fade down to duty = 0\n");
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
//设定LEDC淡出功能,具有有限的时间
ledc_set_fade_with_time(ledc_channel[ch].speed_mode,ledc_channel[ch].channel, 0, LEDC_TEST_FADE_TIME);
//设定LEDC淡出功能,具有有限的时间
ledc_fade_start(ledc_channel[ch].speed_mode,ledc_channel[ch].channel, LEDC_FADE_NO_WAIT);
}
//获取信号量,信号量无效的话则无限堵塞
for (int i = 0; i < LEDC_TEST_CH_NUM; i++) {
xSemaphoreTake(counting_sem, portMAX_DELAY);
}
printf("3. LEDC set duty = %d without fade\n", LEDC_TEST_DUTY);
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
//设置占空比
ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, LEDC_TEST_DUTY);
//更新占空比
ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
printf("4. LEDC set duty = 0 without fade\n");
for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) {
//设置占空比
ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, 0);
//更新占空比
ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel);
}
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
四、LEDC实验演示结果
这里的话可以根据不同的硬件实现不同的效果,LED的亮度调节,或者电机速度调节。
五、ESP32 LEDC中的API
5.1、ledc_types.h文件中的内容的API
uart_types.h文件中的内容基本上实现的是一些LEDC的速度模式、中断、时钟源、定时器选择、LEDC通道、占空比分辨率、淡出时候的状态、通道配置结构体、定时器配置结构体。
typedef enum {
#if SOC_LEDC_SUPPORT_HS_MODE
Ledc_high_speed_mode = 0, /*!< LEDC高速模式*/
# endif
LEDC_LOW_SPEED_MODE , /*!< LEDC低速模式 */
LEDC_SPEED_MODE_MAX , /*!< LEDC限速*/
} ledc_mode_t;
typedef enum {
LEDC_INTR_DISABLE = 0, /*!<禁用LEDC中断*/
LEDC_INTR_FADE_END , /*!<使能LEDC中断*/
LEDC_INTR_MAX,
} ledc_intr_type_t;
typedef enum {
LEDC_DUTY_DIR_REDUCE = 0, /*!< LEDC负载降低方向*/
LEDC_DUTY_DIR_INCREASE = 1, /*!< LEDC增税方向*/
LEDC_DUTY_DIR_MAX,
} ledc_duty_direction_t;
typedef enum {
LEDC_SLOW_CLK_RTC8M = 0, /*!< LEDC低速定时器时钟源为8MHz RTC时钟*/
LEDC_SLOW_CLK_APB, /*!< LEDC低速定时器时钟源为80MHz APB时钟*/
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
LEDC_SLOW_CLK_XTAL, /*!< LEDC低速定时器时钟源XTAL时钟*/
# endif
} ledc_slow_clk_sel_t;
typedef enum {
LEDC_AUTO_CLK = 0, /*!< 驱动程序在初始化定时器时根据给定的分辨率和值班参数自动选择源时钟(REF_TICK或APB) */
LEDC_USE_REF_TICK, /*!< LEDC timer select REF_TICK clock作为源时钟*/
LEDC_USE_APB_CLK, /*!< LEDC timer选择APB时钟作为源时钟*/
LEDC_USE_RTC8M_CLK, /*!< LEDC timer select RTC8M_CLK作为源时钟。仅对低速通道有效,所有低速通道需保持一致*/
#if SOC_LEDC_SUPPORT_XTAL_CLOCK
LEDC_USE_XTAL_CLK, /* !< LEDC timer选择XTAL时钟作为源时钟*/
# endif
} ledc_clk_cfg_t;
/*
* 注意:设置数值匹配ledc_clk_cfg_t的值是一种避免冲突的hack
* 驱动程序中的LEDC_AUTO_CLK,因为这些枚举有非常相似的名称,
* 、用户可以通过这是一个错误。
*/
typedef enum {
LEDC_REF_TICK = LEDC_USE_REF_TICK, /*!< LEDC定时器时钟从参考滴答(1Mhz)分割*/
LEDC_APB_CLK = LEDC_USE_APB_CLK, /*!< LEDC定时器时钟与APB时钟分开(80Mhz) */
} ledc_clk_src_t;
typedef enum {
LEDC_TIMER_0 = 0, /* !< LEDC 定时器0 */
LEDC_TIMER_1, /* !< LEDC 定时器1 */
LEDC_TIMER_2, /* !< LEDC 定时器2 */
LEDC_TIMER_3, /* !< LEDC 定时器3 */
LEDC_TIMER_MAX,
} ledc_timer_t;
typedef enum {
LEDC_CHANNEL_0 = 0, /* !< LEDC 通道0 */
LEDC_CHANNEL_1, /* !< LEDC 通道1 */
LEDC_CHANNEL_2, /* !< LEDC 通道2 */
LEDC_CHANNEL_3, /* !< LEDC 通道3 */
LEDC_CHANNEL_4, /* !< LEDC 通道4 */
LEDC_CHANNEL_5, /* !< LEDC 通道5 */
#if SOC_LEDC_CHANNEL_NUM >
LEDC_CHANNEL_6, /* !< LEDC 频道6 */
LEDC_CHANNEL_7, /* !< LEDC 频道7 */
# endif
LEDC_CHANNEL_MAX,
} ledc_channel_t;
typedef enum {
LEDC_TIMER_2_BIT = 1, /*!< 1位的LEDC PWM占空比分辨率*/
LEDC_TIMER_2_BIT , /*!< 2位的LEDC PWM占空比分辨率*/
LEDC_TIMER_3_BIT , /*!< 3位的LEDC PWM占空比分辨率*/
LEDC_TIMER_4_BIT , /*!< 4位的LEDC PWM占空比分辨率*/
LEDC_TIMER_5_BIT , /*!< 5位的LEDC PWM占空比分辨率*/
LEDC_TIMER_6_BIT , /*!< 6位的LEDC PWM占空比分辨率*/
LEDC_TIMER_7_BIT , /*!< 7位的LEDC PWM占空比分辨率*/
LEDC_TIMER_8_BIT , /*!< 8位的LEDC PWM占空比分辨率*/
LEDC_TIMER_9_BIT , /*!< 9位的LEDC PWM占空比分辨率*/
LEDC_TIMER_10_BIT , /*!< 10位的LEDC PWM占空比分辨率*/
LEDC_TIMER_11_BIT , /*!< 11位的LEDC PWM占空比分辨率*/
LEDC_TIMER_12_BIT , /*!< 12位的LEDC PWM占空比分辨率*/
LEDC_TIMER_13_BIT , /*!< 13位的LEDC PWM占空比分辨率*/
LEDC_TIMER_14_BIT , /*!< 14位的LEDC PWM占空比分辨率*/
#if SOC_LEDC_TIMER_BIT_WIDE_NUM
LEDC_TIMER_15_BIT , /*!< 15位的LEDC PWM占空比分辨率*/
LEDC_TIMER_16_BIT , /*!< 16位的LEDC PWM占空比分辨率*/
LEDC_TIMER_17_BIT , /*!< 17位的LEDC PWM占空比分辨率*/
LEDC_TIMER_18_BIT , /*!< 18位的LEDC PWM占空比分辨率*/
LEDC_TIMER_19_BIT , /*!< 19位的LEDC PWM占空比分辨率*/
LEDC_TIMER_20_BIT , /*!< 20位的LEDC PWM占空比分辨率*/
# endif
LEDC_TIMER_BIT_MAX,
} ledc_timer_bit_t;
typedef enum {
LEDC_FADE_NO_WAIT = 0, /*!< LEDC淡出函数将立即返回*/
LEDC_FADE_WAIT_DONE, /*!< LEDC淡出功能将阻塞,直到淡出到目标任务*/
LEDC_FADE_MAX,
} ledc_fade_mode_t;
//配置ledc_channel_config功能的LEDC通道参数
typedef struct {
int gpio_num; /* !< LEDC输出gpio_num,如果要使用gpio16, gpio_num = 16 */
ledc_mode_t speed_mode; /* !< LEDC speed speed_mode,高速模式或低速模式*/
ledc_channel_t channel; /* !< LEDC通道(0 - 7)*/
ledc_intr_type_t intr_type; /* !< 配置中断,淡出中断启用或淡出中断禁用*/
ledc_timer_t timer_sel; /* !< 选择通道的定时器源(0 - 3)*/
uint32_t duty; /* !< LEDC通道负载,负载设定范围为[0,(2**duty_resolution)] */
int hpoint; /* !< LEDC通道hpoint值,最大值为0xfffff */
struct {
unsigned int output_invert: 1; /*!< 使能(1)或失能(0)gpio输出反转 */
} flags; /*!< LEDC标志 */
} ledc_channel_config_t;
//ledc_timer_config功能的LEDC Timer配置参数
typedef struct {
ledc_mode_t speed_mode; /* !< LEDC speed speed_mode,高速模式或低速模式*/
union {
ledc_timer_bit_t duty_resolution; /* !< LEDC通道负载分辨率*/
ledc_timer_bit_t bit_num __attribute__((deprecated));/* !ESP-IDF 3.0弃用。这是'duty_resolution'的别名,用于向后兼容ESP-IDF 2.1 */
};
ledc_timer_t timer_num; /* !<通道的定时器源(0 - 3)*/
uint32_t freq_hz; /* !< LEDC定时器频率(Hz) */
ledc_clk_cfg_t clk_cfg; /* !<配置LEDC源时钟。
对于低速通道和高速通道,可以通过LEDC_USE_REF_TICK、LEDC_USE_APB_CLK或LEDC_AUTO_CLK指定源时钟。
对于低速通道,您也可以使用LEDC_USE_RTC8M_CLK指定源时钟,在这种情况下,所有低速通道的源时钟必须是RTC8M_CLK*/
} ledc_timer_config_t;
5.2、在ledc.h文件中的内容的API
在LEDC中不带参数解释的API
//LEDC回调事件类型
typedef enum {
LEDC_FADE_END_EVT /**< LEDC渐变结束事件*/
} ledc_cb_event_t;
//LEDC回调参数
typedef struct {
ledc_cb_event_t event; /**<事件名称*/
uint32_t speed_mode; /**< LEDC通道组的速率模式*/
uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
uint32_t duty; /**<通道的LEDC电流负载,负载范围为[0,(2**duty_resolution) - 1] */
} ledc_cb_param_t;
//LEDC事件回调类型
typedef bool (* ledc_cb_t)(const ledc_cb_param_t *param, void *user_arg);
/**
* @brief支持的LEDC回调组
* @note回调都是在ISR环境下运行的
*/
typedef struct {
ledc_cb_t fade_cb; /**< LEDC fade_end回调函数*/
} ledc_cbs_t;
//LEDC通道配置使用给定的通道/输出gpio_num/中断/源定时器/频率(Hz)/LEDC负载分辨率配置LEDC通道
esp_err_t ledc_channel_config(const ledc_channel_config * ledc_conf);
//LEDC定时器配置配置LEDC定时器与给定的源定时器/频率(Hz)/duty_resolution
esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
//LEDC更新通道参数,调用此函数激活LEDC更新的参数。在ledc_set_duty之后,我们需要调用这个函数来更新设置。
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
//设置LEDC输出gpio。这个函数是多余的,请使用ledc_channel_config来设置gpio引脚。
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel)
__attribute__((deprecated("use ledc_channel_config instead")));
//LEDC停止。关闭LEDC输出,设置空闲电平
esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level);
//LEDC设置频道频率(Hz)注意,并非所有目标都支持高速模式。
esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz);
//LEDC获得频道频率(Hz)注意,并非所有目标都支持高速模式。
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
/**
* @brief LEDC设置占空比和hpoint值,只有在调用ledc_update_duty之后,duty才会更新。
* @note ledc_set_duty, ledc_set_duty_with_hpoint和ledc_update_duty不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。一个线程安全的API版本是ledc_set_duty_and_update
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
//LEDC获得hpoint值,当输出设置为高电平时计数器的值。
int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC设定占空比
* 这个函数不会改变这个通道的hpoint值。如果需要,请调用ledc_set_duty_with_hpoint。
* 只有在调用ledc_update_duty之后,占空比才会更新。
* @note ledc_set_duty, ledc_set_duty_with_hpoint和ledc_update_duty不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_duty_and_update。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);
//LEDC得到占空比
uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC设置梯度
* 设置LEDC梯度,该函数调用ledc_update_duty函数后生效。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction,uint32_t step_num, uint32_t duty_cycle_num, uint32_t duty_scale);
//注册LEDC中断处理程序,该处理程序是一个ISR。处理程序将被附加到该函数运行的同一个CPU核心上。
esp_err_t ledc_isr_register(void (*fn)(void*), void* arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
//配置LEDC设置
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src);
//复位LEDC定时器
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
//暂停LEDC定时器计数器
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
//恢复LEDC定时器
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
//将LEDC通道与所选定时器绑定
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel);
/**
* @brief设置LEDC渐变功能。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 调用ledc_fade_start()之后开始渐变。
* @note ledc_set_fade_with_step, ledc_set_fade_with_time和ledc_fade_start不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_fade_step_and_start
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num);
/**
* @brief设定LEDC渐变功能,具有有限的时间。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 调用ledc_fade_start()之后开始渐变。
* @note ledc_set_fade_with_step, ledc_set_fade_with_time和ledc_fade_start不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_fade_step_and_start
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
//安装LEDC渐变功能。此功能将占用LEDC模块的中断。
esp_err_t ledc_fade_func_install (int intr_alloc_flags);
//卸载LEDC渐变功能。
void ledc_fade_func_uninstall(void);
/**
* @brief启动LEDC渐变。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 在开始渐变之前,在ledc_set_fade_with_time或ledc_set_fade_with_step之后调用此API。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode);
/**
* 一个线程安全的API,用于设置LEDC通道的占空比,并在占空比更新时返回。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/**
* 一个线程安全的API来设置和启动LEDC渐变功能,有一个有限的时间。
* 在调用这个函数之前,调用ledc_fade_func_install()一次。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode);
/**
* 一个线程安全的API来设置和启动LEDC渐变功能。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
*/
esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode);
# ifdef __cplusplus
}
# endif
/**
* @brief LEDC回调注册功能
* @注意回调是由ISR调用的,它永远不能试图阻塞,并且任何被调用的FreeRTOS API必须是ISR支持的。
*/
esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg);
在LEDC中带参数解释的API
//LEDC回调事件类型
typedef enum {
LEDC_FADE_END_EVT /**< LEDC渐变结束事件*/
} ledc_cb_event_t;
//LEDC回调参数
typedef struct {
ledc_cb_event_t event; /**<事件名称*/
uint32_t speed_mode; /**< LEDC通道组的速率模式*/
uint32_t channel; /**< LEDC channel (0 - LEDC_CHANNEL_MAX-1) */
uint32_t duty; /**<通道的LEDC电流负载,负载范围为[0,(2**duty_resolution) - 1] */
} ledc_cb_param_t;
/**
* @brief LEDC事件回调类型
* @param param LEDC回调参数
* @param user_arg用户注册数据
*/
typedef bool (* ledc_cb_t)(const ledc_cb_param_t *param, void *user_arg);
/**
* @brief支持的LEDC回调组
* @note回调都是在ISR环境下运行的
*/
typedef struct {
ledc_cb_t fade_cb;/**< LEDC fade_end回调函数*/
} ledc_cbs_t;
/**
* @brief LEDC通道配置
* 使用给定的通道/输出gpio_num/中断/源定时器/频率(Hz)/LEDC负载分辨率配置LEDC通道
* @param ledc_conf LEDC通道配置结构的指针
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_channel_config(const ledc_channel_config * ledc_conf);
/**
* @brief LEDC定时器配置
* 配置LEDC定时器与给定的源定时器/频率(Hz)/duty_resolution
* @param timer_conf LEDC定时器配置结构的指针
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_FAIL不能找到一个适当的预除数基于给定的频率和当前的duty_resolution。
*/
esp_err_t ledc_timer_config(const ledc_timer_config_t* timer_conf);
/**
* @brief LEDC更新通道参数
* @note调用此函数激活LEDC更新的参数。
* 在ledc_set_duty之后,我们需要调用这个函数来更新设置。
* @note ledc_set_duty, ledc_set_duty_with_hpoint和ledc_update_duty不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_duty_and_update
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* 设置LEDC输出gpio。
* 这个函数是多余的,请使用ledc_channel_config来设置gpio引脚。
* @param gpio_num LEDC输出gpio
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param ledc_channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc_channel)
__attribute__((deprecated("use ledc_channel_config instead")));
/**
* @brief LEDC停止。
* 关闭LEDC输出,设置空闲电平
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param idle_level设置LEDC停止后的输出空闲级别。
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_stop(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t idle_level);
/**
* @brief LEDC设置频道频率(Hz)
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_num LEDC定时器索引(0-3),select from ledc_timer_t
* @param freq_hz设置LEDC频率
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_FAIL不能找到一个适当的预除数基于给定的频率和当前的duty_resolution。
*/
esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t freq_hz);
/**
* @brief LEDC获得频道频率(Hz)
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_num LEDC定时器索引(0-3),select from ledc_timer_t
* @return
* - 0错误
* -其他当前LEDC频率
*/
uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num);
/**
* @brief LEDC设置占空比和hpoint值
* 只有在调用ledc_update_duty之后,duty才会更新。
* @note ledc_set_duty, ledc_set_duty_with_hpoint和ledc_update_duty不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_duty_and_update
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty设置LEDC duty, duty设置范围为[0,(2**duty_resolution) - 1]
* 设置LEDC的hpoint值(max: 0xfffff)
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_set_duty_with_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/**
* @brief LEDC获得hpoint值,当输出设置为高电平时计数器的值。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @return
* - LEDC_ERR_VAL如果参数错误
* -其他LEDC渠道当前hpoint值
*/
int ledc_get_hpoint(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC设定占空比
* 这个函数不会改变这个通道的hpoint值。如果需要,请调用ledc_set_duty_with_hpoint。
* 只有在调用ledc_update_duty之后,占空比才会更新。
* @note ledc_set_duty, ledc_set_duty_with_hpoint和ledc_update_duty不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_duty_and_update。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty设置LEDC duty, duty设置范围为[0,(2**duty_resolution) - 1]
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty);
/**
@brief LEDC得到占空比
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @return
* - LEDC_ERR_DUTY如果参数错误
* -其他目前的LEDC占空比
*/
uint32_t ledc_get_duty(ledc_mode_t speed_mode, ledc_channel_t channel);
/**
* @brief LEDC设置梯度
* 设置LEDC梯度,该函数调用ledc_update_duty函数后生效。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty设置梯度负载的开始,负载设置的范围为[0,(2**duty_resolution) - 1]
* 设置渐变的方向
* @param step_num设置渐变的数量
* @param duty_cycle_num设置多少LEDC滴答每次梯度持续
* 设置梯度变化幅度
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_ARG参数错误
*/
esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, ledc_duty_direction_t fade_direction,
uint32_t step_num, uint32_t duty_cycle_num, uint32_t duty_scale);
/**
* 注册LEDC中断处理程序,该处理程序是一个ISR。
* 处理程序将被附加到该函数运行的同一个CPU核心上。
* @param fn中断处理函数。
* @param arg用户提供的参数传递给处理函数。
* @param intr_alloc_flags用于分配中断的标志。一个或多个(ORred)
* ESP_INTR_FLAG_ *值。更多信息参见esp_intr_alloc.h。
* @param handle返回句柄的指针。如果非null,则中断句柄将
* 在这里返回。
* @return
* - ESP_OK成功
* ESP_ERR_INVALID_ARG函数指针错误。
*/
esp_err_t ledc_isr_register(void (*fn)(void*), void* arg, int intr_alloc_flags, ledc_isr_handle_t *handle);
/**
* 配置LEDC设置
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_sel定时器索引(0-3),在LEDC模块中有4个定时器
* @param clock_divider定时器的时钟分割值,该定时器的时钟与所选的时钟源分开
* @param duty_resolution以位数表示的占空比设置分辨率。值域值范围为[0,(2**duty_resolution)]
* @param clk_src选择LEDC源时钟。
* @return
* -(-1)参数错误
* -其他电流LEDC占空比
*/
esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_t clock_divider, uint32_t duty_resolution, ledc_clk_src_t clk_src);
/**
* @brief复位LEDC定时器
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_sel LEDC定时器索引(0-3),select from ledc_timer_t
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
*/
esp_err_t ledc_timer_rst(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* @brief 暂停LEDC定时器计数器
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_sel LEDC定时器索引(0-3),select from ledc_timer_t
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
*/
esp_err_t ledc_timer_pause(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* @brief恢复LEDC定时器
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param timer_sel LEDC定时器索引(0-3),select from ledc_timer_t
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
*/
esp_err_t ledc_timer_resume(ledc_mode_t speed_mode, ledc_timer_t timer_sel);
/**
* 将LEDC通道与所选定时器绑定
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param timer_sel LEDC定时器索引(0-3),select from ledc_timer_t
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
*/
esp_err_t ledc_bind_channel_timer(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_timer_t timer_sel);
/**
* @brief设置LEDC渐变功能。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 调用ledc_fade_start()之后开始渐变。
* @note ledc_set_fade_with_step, ledc_set_fade_with_time和ledc_fade_start不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_fade_step_and_start
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。,
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty渐变的目标占空比[0,(2**duty_resolution) - 1]
* @param缩放控制增加或减少步长缩放。
* @param cycle_num每个周期增加或减少负载
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_FAIL渐变函数初始化错误
*/
esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num);
/**
* @brief设定LEDC渐变功能,具有有限的时间。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 调用ledc_fade_start()之后开始渐变。
* @note ledc_set_fade_with_step, ledc_set_fade_with_time和ledc_fade_start不是线程安全的,不要调用这些函数
* 同时在不同的任务中控制一个LEDC通道。
* 一个线程安全的API版本是ledc_set_fade_step_and_start
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。,
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty渐变的目标占空比[0,(2**duty_resolution) - 1]
* @param max_fade_time_ms最大渐变时间(ms)。
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_FAIL渐变函数初始化错误
*/
esp_err_t ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, int max_fade_time_ms);
/**
* @brief安装LEDC渐变功能。此功能将占用LEDC模块的中断。
* @param intr_alloc_flags用于分配中断的标志。一个或多个(ORred)
* ESP_INTR_FLAG_ *值。更多信息参见esp_intr_alloc.h。
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能已经安装。
*/
esp_err_t ledc_fade_func_install (int intr_alloc_flags);
/**
* @brief卸载LEDC渐变功能。
*/
void ledc_fade_func_uninstall(void);
/**
* @brief启动LEDC渐变。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 在开始渐变之前,在ledc_set_fade_with_time或ledc_set_fade_with_step之后调用此API。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param频道LEDC频道号
* @param fade_mode是否阻塞直到淡入完成。
* @return
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_ERR_INVALID_ARG参数错误。
*/
esp_err_t ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_fade_mode_t fade_mode);
/**
* 一个线程安全的API,用于设置LEDC通道的占空比,并在占空比更新时返回。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param duty设置LEDC duty, duty设置范围为[0,(2**duty_resolution) - 1]
* 设置LEDC的hpoint值(max: 0xfffff)
*/
esp_err_t ledc_set_duty_and_update(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty, uint32_t hpoint);
/**
* 一个线程安全的API来设置和启动LEDC渐变功能,有一个有限的时间。
* 在调用这个函数之前,调用ledc_fade_func_install()一次。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty渐变的目标占空比[0,(2**duty_resolution) - 1]
* @param max_fade_time_ms最大渐变时间(ms)。
* @param fade_mode选择阻塞或非阻塞模式
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_FAIL渐变函数初始化错误
*/
esp_err_t ledc_set_fade_time_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t max_fade_time_ms, ledc_fade_mode_t fade_mode);
/**
* 一个线程安全的API来设置和启动LEDC渐变功能。
* @note在调用这个函数之前调用ledc_fade_func_install()一次。
* 注意:如果一个渐隐操作正在那个通道上运行,驱动程序将不允许它停止。
* 其他值班操作必须等到褪色操作结束。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param target_duty渐变的目标占空比[0,(2**duty_resolution) - 1]
* @param缩放控制增加或减少步长缩放。
* @param cycle_num每个周期增加或减少负载
* @param fade_mode选择阻塞或非阻塞模式
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_FAIL渐变函数初始化错误
*/
esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t target_duty, uint32_t scale, uint32_t cycle_num, ledc_fade_mode_t fade_mode);
# ifdef __cplusplus
}
# endif
/**
* @brief LEDC回调注册功能
* @注意回调是由ISR调用的,它永远不能试图阻塞,并且任何被调用的FreeRTOS API必须是ISR支持的。
* @param speed_mode选择指定速率模式的LEDC通道组。注意,并非所有目标都支持高速模式。
* @param channel LEDC channel index (0 - LEDC_CHANNEL_MAX-1), select from ledc_channel_t
* @param cbs LEDC回调函数组
@param user_arg用户注册回调函数的数据
* @return
* - ESP_ERR_INVALID_ARG参数错误
* - ESP_OK成功
* - ESP_ERR_INVALID_STATE渐变功能未安装。
* - ESP_FAIL渐变函数初始化错误
*/
esp_err_t ledc_cb_register(ledc_mode_t speed_mode, ledc_channel_t channel, ledc_cbs_t *cbs, void *user_arg);