ledc: Update LEDC programming guide

Add source clock in timer config
Add fade end callback and ledc_fade_stop usage
Explain ledc_fade_mode_t difference and limitation
This commit is contained in:
songruojing 2021-08-06 12:23:26 +08:00
parent c2b8535205
commit 31f9a69454
3 changed files with 179 additions and 17 deletions

View File

@ -445,7 +445,6 @@ TEST_CASE("LEDC fade stop test", "[ledc]")
const ledc_mode_t test_speed_mode = TEST_SPEED_MODE;
fade_setup();
// Overwrite the last fade with new fade
int64_t fade_start, fade_stop;
int time_ms = 0;
fade_start = esp_timer_get_time();
@ -453,14 +452,19 @@ TEST_CASE("LEDC fade stop test", "[ledc]")
TEST_ESP_OK(ledc_fade_start(test_speed_mode, LEDC_CHANNEL_0, LEDC_FADE_NO_WAIT));
// Add some delay before stopping the fade
vTaskDelay(127 / portTICK_RATE_MS);
uint32_t duty_at_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
// Get duty value right before stopping the fade
uint32_t duty_before_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
TEST_ESP_OK(ledc_fade_stop(test_speed_mode, LEDC_CHANNEL_0));
fade_stop = esp_timer_get_time();
time_ms = (fade_stop - fade_start) / 1000;
TEST_ASSERT_TRUE(fabs(time_ms - 127) < 20);
// Get duty value after fade_stop returns (give at least one cycle for the duty set in fade_stop to take effective)
uint32_t duty_after_stop = ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0);
TEST_ASSERT_INT32_WITHIN(4, duty_before_stop, duty_after_stop); // 4 is the scale for one step in the last fade
vTaskDelay(300 / portTICK_RATE_MS);
TEST_ASSERT_EQUAL_INT32(duty_at_stop, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ASSERT_NOT_EQUAL(4000, duty_at_stop);
// Duty should not change any more after ledc_fade_stop returns
TEST_ASSERT_EQUAL_INT32(duty_after_stop, ledc_get_duty(test_speed_mode, LEDC_CHANNEL_0));
TEST_ASSERT_NOT_EQUAL(4000, duty_after_stop);
//deinitialize fade service
ledc_fade_func_uninstall();

View File

@ -1,6 +1,6 @@
LED Control (LEDC)
==================
{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6"}
{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6", esp32s3="8"}
:link_to_translation:`zh_CN:[中文]`
@ -57,9 +57,80 @@ Setting the timer is done by calling the function :cpp:func:`ledc_timer_config`
- Timer number :cpp:type:`ledc_timer_t`
- PWM signal frequency
- Resolution of PWM duty
- Source clock :cpp:type:`ledc_clk_cfg_t`
The frequency and the duty resolution are interdependent. The higher the PWM frequency, the lower the duty resolution which is available, and vice versa. This relationship might be important if you are planning to use this API for purposes other than changing the intensity of LEDs. For more details, see Section :ref:`ledc-api-supported-range-frequency-duty-resolution`.
The source clock can also limit the PWM frequency. The higher the source clock frequency, the higher the maximum PWM frequency can be configured.
.. only:: esp32
.. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
:widths: 5 5 5 20
:header-rows: 1
* - Clock name
- Clock freq
- Speed mode
- Clock capabilities
* - APB_CLK
- 80 MHz
- High / Low
- /
* - REF_TICK
- 1 MHz
- High / Low
- Dynamic Frequency Scaling compatible
* - RTC8M_CLK
- ~8 MHz
- Low
- Dynamic Frequency Scaling compatible, Light sleep compatible
.. only:: esp32s2
.. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
:widths: 15 15 30
:header-rows: 1
* - Clock name
- Clock freq
- Clock capabilities
* - APB_CLK
- 80 MHz
- /
* - REF_TICK
- 1 MHz
- Dynamic Frequency Scaling compatible
* - RTC8M_CLK
- ~8 MHz
- Dynamic Frequency Scaling compatible, Light sleep compatible
* - XTAL_CLK
- 40 MHz
- Dynamic Frequency Scaling compatible
.. only:: esp32s3 or esp32c3
.. list-table:: Characteristics of {IDF_TARGET_NAME} LEDC source clocks
:widths: 15 15 30
:header-rows: 1
* - Clock name
- Clock freq
- Clock capabilities
* - APB_CLK
- 80 MHz
- /
* - RTC20M_CLK
- ~20 MHz
- Dynamic Frequency Scaling compatible, Light sleep compatible
* - XTAL_CLK
- 40 MHz
- Dynamic Frequency Scaling compatible
.. note::
For {IDF_TARGET_NAME}, all timers share one clock source. In other words, it is impossible to use different clock sources for different timers.
.. _ledc-api-configure-channel:
@ -82,7 +153,7 @@ Once the channel starts operating and generating the PWM signal with the constan
The following two sections describe how to change the duty cycle using software and hardware fading. If required, the signal's frequency can also be changed; it is covered in Section :ref:`ledc-api-change-pwm-frequency`.
.. only:: esp32s2 or esp32c3
.. only:: not esp32
.. note::
@ -108,7 +179,15 @@ The LEDC hardware provides the means to gradually transition from one duty cycle
* :cpp:func:`ledc_set_fade_with_step`
* :cpp:func:`ledc_set_fade`
Finally start fading with :cpp:func:`ledc_fade_start`.
.. only:: esp32
Start fading with :cpp:func:`ledc_fade_start`. A fade can be operated in blocking or non-blocking mode, please check :cpp:enum:`ledc_fade_mode_t` for the difference between the two available fade modes. Note that with either fade mode, the next fade or fixed-duty update will not take effect until the last fade finishes. Due to hardware limitations, there is no way to stop a fade before it reaches its target duty.
.. only:: not esp32
Start fading with :cpp:func:`ledc_fade_start`. A fade can be operated in blocking or non-blocking mode, please check :cpp:enum:`ledc_fade_mode_t` for the difference between the two available fade modes. Note that with either fade mode, the next fade or fixed-duty update will not take effect until the last fade finishes or is stopped. :cpp:func:`ledc_fade_stop` has to be called to stop a fade that is in progress.
To get a notification about the completion of a fade operation, a fade end callback function can be registered for each channel by calling :cpp:func:`ledc_cb_register` after the fade service being installed.
If not required anymore, fading and an associated interrupt can be disabled with :cpp:func:`ledc_fade_func_uninstall`.
@ -155,7 +234,7 @@ For registration of a handler to address this interrupt, call :cpp:func:`ledc_is
High speed mode enables a glitch-free changeover of timer settings. This means that if the timer settings are modified, the changes will be applied automatically on the next overflow interrupt of the timer. In contrast, when updating the low-speed timer, the change of settings should be explicitly triggered by software. The LEDC driver handles it in the background, e.g., when :cpp:func:`ledc_timer_config` or :cpp:func:`ledc_timer_set` is called.
For additional details regarding speed modes, see *{IDF_TARGET_NAME} Technical Reference Manual* > *LED PWM Controller (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__]. Please note that the support for ``SLOW_CLOCK`` mentioned in this manual is not yet supported in the LEDC driver.
For additional details regarding speed modes, see *{IDF_TARGET_NAME} Technical Reference Manual* > *LED PWM Controller (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__].
.. _ledc-api-supported-range-frequency-duty-resolution:

View File

@ -1,6 +1,6 @@
LED PWM 控制器
==============
{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6"}
{IDF_TARGET_LEDC_CHAN_NUM:default="8", esp32="16", esp32s2="8", esp32c3="6", esp32s3="8"}
:link_to_translation:`en:[English]`
@ -57,9 +57,80 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实
- 定时器索引 :cpp:type:`ledc_timer_t`
- PWM 信号频率
- PWM 占空比分辨率
- 时钟源 :cpp:type:`ledc_clk_cfg_t`
频率和占空比分辨率相互关联。PWM 频率越高,占空比分辨率越低,反之亦然。如果 API 不是用来改变 LED 亮度,而是用于其它目的,这种相互关系可能会很重要。更多信息详见 :ref:`ledc-api-supported-range-frequency-duty-resolution` 一节。
时钟源同样可以限制PWM频率。选择的时钟源频率越高可以配置的PWM频率上限就越高。
.. only:: esp32
.. list-table:: {IDF_TARGET_NAME} LEDC 时钟源特性
:widths: 5 5 8 20
:header-rows: 1
* - 时钟名称
- 时钟频率
- 速度模式
- 时钟功能
* - APB_CLK
- 80 MHz
- 高速 / 低速
- /
* - REF_TICK
- 1 MHz
- 高速 / 低速
- 支持动态调频DFS功能
* - RTC8M_CLK
- ~8 MHz
- 低速
- 支持动态调频DFS功能支持Light-sleep模式
.. only:: esp32s2
.. list-table:: {IDF_TARGET_NAME} LEDC 时钟源特性
:widths: 10 10 30
:header-rows: 1
* - 时钟名称
- 时钟频率
- 时钟功能
* - APB_CLK
- 80 MHz
- /
* - REF_TICK
- 1 MHz
- 支持动态调频DFS功能
* - RTC8M_CLK
- ~8 MHz
- 支持动态调频DFS功能支持Light-sleep模式
* - XTAL_CLK
- 40 MHz
- 支持动态调频DFS功能
.. only:: esp32s3 or esp32c3
.. list-table:: {IDF_TARGET_NAME} LEDC 时钟源特性
:widths: 10 10 30
:header-rows: 1
* - 时钟名称
- 时钟频率
- 时钟功能
* - APB_CLK
- 80 MHz
- /
* - RTC20M_CLK
- ~20 MHz
- 支持动态调频DFS功能支持Light-sleep模式
* - XTAL_CLK
- 40 MHz
- 支持动态调频DFS功能
.. note::
{IDF_TARGET_NAME}的所有定时器共用一个时钟源。因此{IDF_TARGET_NAME}不支持给不同的定时器配置不同的时钟源。
.. _ledc-api-configure-channel:
@ -82,7 +153,7 @@ LED PWM 控制器可在无需 CPU 干预的情况下自动改变占空比,实
以下两节介绍了如何使用软件和硬件改变占空比。如有需要PWM 信号的频率也可更改,详见 :ref:`ledc-api-change-pwm-frequency` 一节。
.. only:: esp32s2 or esp32c3
.. only:: not esp32
.. note::
@ -108,7 +179,15 @@ LED PWM 控制器硬件可逐渐改变占空比的数值。要使用此功能,
* :cpp:func:`ledc_set_fade_with_step`
* :cpp:func:`ledc_set_fade`
最后用 :cpp:func:`ledc_fade_start` 开启渐变。
.. only:: esp32
最后需要调用 :cpp:func:`ledc_fade_start` 开启渐变。渐变可以在阻塞或非阻塞模式下运行,具体区别请查看 :cpp:enum:`ledc_fade_mode_t`。需要特别注意的是,不管在哪种模式下,下一次渐变或单次占空比配置的指令生效都必须等到前一次渐变结束。由于 {IDF_TARGET_NAME} 的硬件限制,在渐变达到原先预期的占空比前想要中止本次渐变是不被支持的。
.. only:: not esp32
最后需要调用 :cpp:func:`ledc_fade_start` 开启渐变。渐变可以在阻塞或非阻塞模式下运行,具体区别请查看 :cpp:enum:`ledc_fade_mode_t`。需要特别注意的是,不管在哪种模式下,下一次渐变或是单次占空比配置的指令生效都必须等到前一次渐变完成或被中止。中止一个正在运行中的渐变需要调用函数 :cpp:func:`ledc_fade_stop`
此外,在使能渐变后,每个通道都可以额外通过调用 :cpp:func:`ledc_cb_register` 注册一个回调函数用以获得渐变完成的事件通知。
如不需要渐变和渐变中断,可用函数 :cpp:func:`ledc_fade_func_uninstall` 关闭。
@ -155,7 +234,7 @@ LED PWM 控制器 API 有多种方式即时改变 PWM 频率:
高速模式的优点是可平稳地改变定时器设置。也就是说高速模式下如定时器设置改变此变更会自动应用于定时器的下一次溢出中断。而更新低速定时器时设置变更应由软件显式触发。LED PWM 驱动的设置将在硬件层面被修改,比如在调用函数 :cpp:func:`ledc_timer_config`:cpp:func:`ledc_timer_set` 时。
更多关于速度模式的详细信息请参阅 *{IDF_TARGET_NAME} 技术参考手册* > *LED PWM 控制器 (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__]。注意,该手册中提到的支持 ``SLOW_CLOCK`` 暂不适用于 LED PWM 驱动。
更多关于速度模式的详细信息请参阅 *{IDF_TARGET_NAME} 技术参考手册* > *LED PWM 控制器 (LEDC)* [`PDF <{IDF_TARGET_TRM_EN_URL}#ledpwm>`__]。
.. _ledc-api-supported-range-frequency-duty-resolution: