Периферийное устройство контроллера LED (LEDC) было разработано для основной цели управления яркостью светодиодов LED, хотя его можно также использовать для генерации ШИМ-сигналов (PWM), предназначенных для других целей. Имеется 16 каналов, которые могут генерировать независимые формы сигналов, что может использоваться, к примеру, для управления светодиодными лентами RGB или генерации звука.
Каналы LEDC делятся на 2 группы по 8 каналов в каждой. Одна группа каналов LEDC работает в высокоскоростном режиме (high speed mode). Этот режим реализован аппаратно, и предоставляет автоматическое, без выбросов изменение скважности PWM. Другая группа каналов работает в низкоскоростном режиме (low speed mode), в этом режиме скважность PWM должна меняться программным драйвером. Каждая группа каналов также может также может использовать разные источники тактов.
Контроллер PWM может автоматически и постепенно увеличивать или уменьшать скважность PWM, что позволяет управлять освещением без программного вмешательства процессора.
Настройка канала LEDC в высокоскоростном или низкоскоростном режиме делается тремя шагами:
1. Конфигурируется таймер путем указания частоты сигнала PWM и разрешающей способности изменения его скважности. 2. Конфигурируется канал путем связывания его с таймером и ножкой GPIO для вывода сигнала PWM. 3. Изменение сигнала PWM, который управляет выходом, чтобы менять интенсивность свечения LED. Это может осуществляться либо по полным управлением со стороны программы, либо аппаратным фейдингом.
Как опциональный шаг также можно настроить прерывание по окончанию фейдинга.
Рис. 1. Ключевые настройки контроллера LED PWM с помощью API-функций.
[Конфигурация таймера]
Настройка таймера осуществляется вызовом функции ledc_timer_config(), с передачей ей структуры данных ledc_timer_config_t, которая содержит следующие настройки конфигурации:
• ledc_mode_t: режим скорости. • ledc_timer_t: номер таймера. • Частота сигнала PWM. • Разрешающая способность (разрядность) изменения скважности PWM. • ledc_clk_cfg_t: частота источника тактов.
Частота и разрешающая способность взаимосвязаны. Чем выше частота PWM, тем меньшая разрешающая способность доступна, и наоборот. Эта взаимосвязь может быть важной, если Вы планируете использовать это API не для простого управления яркостью LED. Для дополнительной информации см. далее раздел "Поддерживаемые диапазоны частоты и разрешающей способности скважности".
Частота тактирования также ограничивает частоту PWM. Чем выше частота тактов, тем более высокая частота PWM может быть сконфигурирована.
Таблица 1. Характеристики источников тактирования ESP32 LEDC.
Мнемоника |
Частота тактов |
Режим скорости |
Возможности тактирования |
APB_CLK |
80 МГц |
High / Low |
|
REF_TICK |
1 МГц |
Совместимо с динамическим масштабированием частоты (Dynamic Frequency Scaling). |
RTC8M_CLK |
~8 МГц |
Low |
Совместимо с Dynamic Frequency Scaling и режимом пониженного энергопотребления Light Sleep. |
Примечание: на ESP32, если в качестве источника тактов LEDC выбран RTCxM_CLK, то для получения точной частоты тактов выполняется внутренняя калибровка. Это гарантирует точную частоту выходного сигнала PWM.
Конфигурация канала. Когда настраивается таймер, конфигурируется желаемый канал (один из ledc_channel_t). Это делается функцией ledc_channel_config().
Подобно конфигурации таймера, функции настройки канала должна быть передана структура ledc_channel_config_t, которая содержит параметры конфигурации канала.
В этом месте канал должен начать работать, генерируя сигнал PWM на выбранной ножке GPIO, как это было сконфигурировано в ledc_channel_config_t, на частоте, указанной в настройках таймера, и с заданной скважностью. Работа канала (генерация сигнала) может быть приостановлена в любой момент вызовом функции ledc_stop().
[Изменение сигнала PWM]
Как только канал начнет работать и генерировать сигнал PWM с постоянной скважностью, есть несколько способов поменять этот сигнал. Когда осуществляется управление LED, меняется главным образом яркость свечения.
В следующих двух секциях описывается, как менять скважность с помощью аппаратного и программного фейдинга. Если необходимо, также можно поменять частоту сигнала, это рассматривается в секции "Изменение частоты PWM".
Изменение скважности программно. Для установки скважности периода PWM используйте специальную функцию ledc_set_duty(). После этого вызовите ledc_update_duty() для активации изменений. Для проверки текущего установленного значения скважности используйте соответствующую функцию ledc_get_duty().
Другой способ установки скважности, как и некоторых других параметров, это вызов ledc_channel_config(), см. выше секцию "Конфигурация канала".
Диапазон передаваемых значений для изменения скважности зависит от выбранной разрешающей способности (duty_resolution), и значение должно быть от 0 до (2duty_resolution) - 1. Например, если выбранная разрешающая способность 10 (duty_resolution=10), то скважность может быть в диапазоне от 0 до 1023. Это дает точность установки уровня примерно 0.1%.
Изменение скважности аппаратно. Аппаратура LEDC обеспечивает способ плавного изменения скважности от одного значения к другому. Для использования этой возможности разрешите фейдинг функцией ledc_fade_func_install(), и затем сконфигурируйте её вызовом одной из следующих доступных функций фейдинга:
ledc_set_fade_with_time() ledc_set_fade_with_step() ledc_set_fade()
Фейдинг начинается вызовом ledc_fade_start(). Фейдинг может работать в режиме блокирования или без блокирования, см. ledc_fade_mode_t для двух различных отличающихся режимов фейдинга. Обратите внимание, что в любом из этих двух режимов следующий фейдинг или обновление на фиксированную скважность не даст эффект, пока не завершится последний процесс фейдинга. Из-за аппаратных ограничений нет способа остановить фейдинг до момента достижения им целевой скважности.
Для получения оповещения о завершении операции фейдинга может быть зарегистрирована соответствующая callback-функция путем вызова ledc_cb_register() после того, как была установлена служба фейдинга.
Если больше не требуется фейдинг и связанное с ним прерывание, то фейдинг может быть запрещен вызовом ledc_fade_func_uninstall().
Изменение частоты PWM. LEDC API предоставляет несколько способов поменять частоту PWM "на лету":
• Установка частоты вызовом ledc_set_freq(). Имеется комплементарная функция ledc_get_freq() для проверки текущей частоты. • Изменение частоты и разрешающей способности для скважности вызовом ledc_bind_channel_timer(), чтобы привязать к каналу какой-нибудь другой таймер. • Изменение таймера канала вызовом ledc_channel_config().
Дополнительное управление функцией PWM. Существует несколько функций таймера, реализующих управление на более низком уровне, которые можно использовать для изменения настроек PWM:
ledc_timer_set() ledc_timer_rst() ledc_timer_pause() ledc_timer_resume()
Две первые из них вызываются "закулисно" функцией ledc_channel_config(), чтобы обеспечить запуск таймера после того, как он сконфигурирован.
Использование прерываний. Когда конфигурируется канал LEDC, одним из параметров ledc_channel_config_t является ledc_intr_type_t. Это обработчик прерывания, который запускается, когда завершается фейдинг PWM.
Для регистрации обработчика этого прерывания вызовите ledc_isr_register().
Высокоскоростной и низкоскоростной режимы. Высокоскоростной режим LEDC позволяет реализовать переключение настроек таймера без выбросов и сбоев. Это означает, что если настройки таймера были изменены, то они вступят в действие автоматически на следующем прерывании переполнения таймера. Если сравнить с низкоскоростным режимом, когда применяется низкоскоростной таймер, изменение настроек должно быть явно инициировано программой. Драйвер LEDC осуществляет это в фоновом режиме, т. е. когда вызывается ledc_timer_config() или ledc_timer_set().
Дополнительную информацию по скоростным режимам см. документацию ESP32 Technical Reference Manual -> LED PWM Controller (LEDC) [PDF].
[Поддерживаемые диапазоны частоты и разрешающей способности скважности]
Контроллер LED PWM (LEDC) изначально был разработан для управления светодиодами (LED). Он предоставляет для этого большую гибкость для настройки периода и скважности PWM. Например, при частоте PWM 5 кГц можно получить максимальную разрешающую способность скважности 13 бит. Это значит, что скважность можно менять в диапазоне от 0 до 100% шагами по ~0.012% (2 ^ 13 = 8192 дискретных уровней интенсивности свечения LED). Однако следует заметить, что эти параметры зависят от частоты тактов таймера, вырабатывающего такты для контроллера LED PWM, который в свою очередь тактирует канал (см. описание конфигурации таймера в документе ESP32 Technical Reference Manual -> LED PWM Controller (LEDC) [PDF]).
LEDC может использоваться для генерации сигналов и с намного большей частотой, достаточной для тактирования других устройств, например модуля цифровой камеры. В этом случае максимально возможная частота составит 40 МГц при разрешающей способности 1 бит. это значит, что скважность может быть в этом случае только фиксированной на 50%, и не может быть изменена.
Разработанное LEDC API сообщает об ошибке, когда делается попытка установить частоту и скважность, превышающие возможный диапазон аппаратуры LEDC. Например, попытка установить частоту 20 МГц и разрешающую способность 3 бита приведут к следующей ошибке, о которой сообщит serial monitor:
E (196) ledc: requested frequency and duty resolution cannot be achieved, try reducing freq_hz
or duty_resolution. div_param=128
В такой ситуации нужно уменьшить либо разрядность (т. е. разрешающую способность) скважности, либо уменьшить частоту PWM. Например, установка разрешающей способности изменения скважности 2 устранит эту проблему, и скважность периода ШИМ можно будет менять 4 градациями, с шагом 25%.
Драйвер LEDC будет также перехватывать попытки конфигурирования комбинаций частота / разрядность, которые ниже поддерживаемого минимума, и сообщать о таких попытках, например:
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 бит. Если нужна меньшая разрешающая способность (1 .. 10 бит), введите напрямую нужное числовое значение.
Пример приложения, где осуществляется управление скважностью с функцией фейдинга, см. в каталоге peripherals/ledc/ledc_fade среди примеров среды разработки ESP-IDF [2]. Базовый пример LEDC см. в peripherals/ledc/ledc_basic.
[Справочник по API LEDC]
Заголовочный файл для API-функций драйвера LEDC: components/driver/include/driver/ledc.h. Используемые драйвером типы данных описаны в заголовке components/hal/include/hal/ledc_types.h.
Функция |
Описание |
ledc_channel_config |
Конфигурирует канал LEDC для определенного канала, ножки выхода GPIO, прерывания, таймера, частоты PWM в Гц и разрешающей способности скважности. |
ledc_timer_config |
Конфигурирует таймер LEDC с указанием частоты PWM в Гц и разрешающей способности скважности. |
ledc_update_duty |
Обновляет параметры канала таймера, вызовите эту функцию, чтобы активировать обновленные параметры LEDC. После вызова ledc_set_duty, нам нужно вызвать эту функцию, чтобы вступили в действие измененные настройки. И новые параметры LEDC не вступят в силу до момента следующего цикла PWM(1). |
ledc_set_pin |
Установит ножку выхода GPIO. Эта функция только направляет сигнал LEDC на ножку GPIO через матрицу, другие инициализации ресурсов LEDC не производятся. Вместо этой функции используйте ledc_channel_config() для выполнения полной конфигурации канала LEDC. |
ledc_stop |
Останавливает LEDC. Выход LEDC запрещается, и устанавливается в уровень ожидания (idle level). |
ledc_set_freq |
Установит частоту PWM канала LEDC в Гц. |
ledc_get_freq |
Считывает текущую установленную частоту PWM канала LEDC в Гц. |
ledc_set_duty_with_hpoint |
Установит скважность и верхнее значение изменения скважности (hpoint) LEDC. Скважность обновится только после вызова ledc_update_duty(1, 2). |
ledc_get_hpoint |
Считывает значение hpoint, значение счетчика, когда выход устанавливается в уровень лог. 1. |
ledc_set_duty |
Установка скважности канала LEDC. Эта функция не поменяет значение hpoint для этого канала. Если это необходимо, то вызовите ledc_set_duty_with_hpoint. Скважность обновится только после вызова ledc_update_duty(1, 2). |
ledc_get_duty |
Вернет скважность канала LED на текущем периоде PWM. Не следует ожидать, что функция вернет новую скважность на том же цикле, когда произошел вызов ledc_update_duty, потому что обновление скважности произойдет на следующем периоде PWM. |
ledc_set_fade |
Установит градиент канала LEDC (т. е. скорость, направление и другие параметры автоматического фейдинга). Настройки этой функции вступят в силу после вызова ledc_update_duty(2). |
ledc_isr_register |
Регистрирует обработчик прерывания (ISR) для LEDC. Этот обработчик будет подключен к тому же ядру CPU, на котором выполнялась эта функция. |
ledc_timer_set |
Конфигурирует настройки таймера LEDC. |
ledc_timer_rst |
Сбросит таймер LEDC. |
ledc_timer_pause |
Приостановит таймер LEDC. |
ledc_timer_resume |
Возобновит работу таймера LEDC. |
ledc_bind_channel_timer |
Привязывает канал LEDC к выбранному таймеру. |
ledc_set_fade_with_step |
Установит функцию фейдинга LEDC. Перед вызовом этой функции вызовите один раз ledc_fade_func_install(). После этого для запуска фейдинга вызовите ledc_fade_start()(1, 2). |
ledc_set_fade_with_time |
Установит на ограниченное время функцию фейдинга LEDC. Перед вызовом этой функции вызовите один раз ledc_fade_func_install(). После этого для запуска фейдинга вызовите ledc_fade_start()(1, 2). |
ledc_fade_func_install |
Инсталлирует функцию фейдинга LEDC. Эта функция займет прерывание модуля LEDC. |
ledc_fade_func_uninstall |
Деинсталлирует функцию фейдинга LEDC. |
ledc_fade_start |
Запустит фейдинг LEDC(2). Перед вызовом этой функции вызовите один раз ledc_fade_func_install(). Перед запуском фейдинга вызовите ledc_fade_start сразу после вызова ledc_set_fade_with_time или ledc_set_fade_with_step. Запуск операции фейдинга не будет потокобезопасным, поэтому используйте ledc_fade_start с осторожностью. |
ledc_set_duty_and_update |
Потокобезопасная API-функция для установки скважности канала LEDC и возврата, когда скважность была обновлена(2). |
ledc_set_fade_time_and_start |
Потокобезопасная API-функция для установки и старта фейдинга, с ограниченным временем(2). Перед вызовом этой функции требуется однократный вызов ledc_fade_func_install(). |
ledc_set_fade_step_and_start |
Потокобезопасная API-функция для установки и старта фейдинга (2). Перед вызовом этой функции требуется однократный вызов ledc_fade_func_install(). |
ledc_cb_register |
Регистрирует функцию обратного вызова (callback) LEDC. Callback-функция вызывается из ISR, она не должна никогда пытаться делать блокировку, и все вызываемые из неё API-функции FreeRTOS должны быть ISR-версиями. |
Примечания:
(1) Функции ledc_set_duty, ledc_set_duty_with_hpoint и ledc_update_duty не являются потокобезопасными (not thread-safe), поэтому не вызывайте эти функции для управления одним и тем же каналом LEDC одновременно из разных задач RTOS. Потокобезопасная версия это ledc_set_duty_and_update. (2) Для ESP32 аппаратура не поддерживает любое изменение скважности, пока происходит операция фейдинга (процесс автоматического изменения скважности) на этом канале. Другие операции по управлению скважности должны подождать момента завершения операции фейдинга.
Подробное описание функций, перечислений, типов данных, определений драйвера LEDC см. в документации [1].
[Ссылки]
1. ESP32 LED Control (LEDC) site:docs.espressif.com. 2. Установка среды разработки ESP-IDF для ESP32. 3. ESP32 High Resolution Timer. |