Лабораторная работа №14. Работа с LED PWM контроллером
14.1 Цель и задачи
Цель работы: изучить порядок настройки и использования встроенного контроллера LED PWM. Задачи:
- Получить навыки управления светодиодами с использованием широтно-импульсно модулированных (ШИМ) сигналов.
- Разработать программу для управления и индикации через светодиоды платы.
Презентация к блоку "Микроконтроллеры RISC-V"
14.2 Краткие теоретические сведения
Контроллер LED PWM - это периферийное устройство, предназначенное для генерации ШИМ сигналов для управления светодиодами, однако выходные ШИМ сигналы контроллера могут использоваться и для других целей.
Контроллер LED PWM включает в себя четыре независимых таймера (Time0 - Timer3) с поддержкой деления на доли, мультиплексор и шесть независимых ШИМ-генераторов (PWM0 - PWM5) с разрешением 14 бит (рис. 14.1).
Контроллер может реализовывать затухание рабочего цикла (т.е. постепенное увеличение/уменьшение рабочего цикла ШИМ без вмешательства процессора) с генерацией прерывания по завершении затухания, позволяет регулировать фазу выходного ШИМ-сигнала, допускает перевод вывода ШИМ-сигнала в режим пониженного энергопотребления.
На рисунке 14.2 показаны настраиваемые элементы контроллера.
Каждый таймер в контроллере LED PWM реализует счет времени на основе тактового сигнала ref_pulseX. Все таймеры используют один и тот же источник тактового сигнала LEDC_CLKX, который затем пропускается через делитель тактового сигнала, чтобы сформировать ref_pulseX для счетчика.
Настройка канала для генерации ШИМ-сигнала проводится в три последовательных этапа:
- Инициализация таймера;
- Инициализация канала (подключение к нему таймера и GPIO);
- Задание значения на выходе GPIO.
Для выполнения этих действий можно использовать следующие API функции и структуры.
Для настройки таймера в функцию ledc_timer_config нужно передать заполненную структуру ledc_timer_config_t, которая состоит из следующих элементов:
struct ledc_timer_config_t { ledc_timer_bit_t duty_resolution, uint32_t freq_hz, ledc_mode_t speed_mode, ledc_timer_t timer_num, ledc_clk_cfg_t clk_cfg }
- timer_num - номер таймера, число от 0 до 3.
- clk_cfg. Для автоматического выбора параметра можно установить его в значение LEDC_AUTO_CLK.
- speed_mode. Для ESP32-C3 этот параметр может быть установлен только в значение LEDC_LOW_SPEED_MODE.
- duty_resolution - разрешение канала, количество бит. Например, при значении duty_resolution 10, можно устанавливать интенсивность сигнала (duty) в значения от 0 до (2**10-1).
- freq_hz - частота таймера. Значения частоты таймера и разрешения канала (duty_resolution) зависят друг от друга: при увеличении частоты необходимо понизить разрешение. Например, при частоте 40 мегагерц допустимое разрешение составляет только 1 бит, а при 5 килогерц - 13 бит.
Далее нужно настроить канал.
ledc_channel_config_t { ledc_channel_t channel, uint32_t duty, int gpio_num, ledc_mode_t speed_mode, int hpoint, ledc_timer_t timer_sel }
- channel - номер канала от 0 до 5.
- duty - интенсивность сигнала, от 0 до (2**duty_resolution-1).
- gpio_num - номер пина.
- timer_sel - номер выбранного таймера, аналогичный номеру timer_num в структуре ledc_timer_config_t.
- speed_mode - режим, аналогичный выбранному в структуре ledc_timer_config_t.
Чтобы эти изменения установились, как и в случае с таймером структура передается в специальную функцию ledc_timer_config. Сразу после этого на выбранном пине начинает генерироваться заданный сигнал.
Для изменения параметра duty последовательно используются функции ledc_set_duty(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t duty) и ledc_update_duty(ledc_mode_t speed_mode, ledc_channel_t channel) .
14.3 Задание к лабораторной работе
Подготовить программу, обеспечивающую управление светодиодами с использованием LED PWM контроллера, в соответствии с заданным вариантом. С использованием беспаечной макетной платы собрать схему, подключив светодиоды к настроенным на связь с выходами LED PWM внешним контактам.
- Реализовать плавное уменьшение яркости светодиода до полного его выключения в течение 10 секунд после запуска программы.
- Реализовать плавное увеличение яркости светодиода до его максимальной яркости в течение 10 секунд после запуска программы.
- Реализовать циклическое плавное уменьшение с последующим увеличением яркости. Длительность цикла - 10 секунд.
14.3.1 Описание последовательности выполнения работы
Для выполнения работы необходимо иметь беспаечную макетную плату для многократного макетирования; одножильные провода-перемычки с контактами, допускающими коммутацию с установленными на макетной плате элементами; светодиоды.
- Открыть шаблон проекта командой Open Folder. В качестве шаблона для первого проекта можно использовать проект Sample_project, находящийся в каталоге esp\ esp-idf\examples\get-started\
- Подготовить текст основной программы в соответствии с заданием, используя шаблон, реализующий формирование ШИМ сигнала с использованием контроллера и приведенный в п. 14.3.2.
14.3.2 Пример выполнения задания на защиту
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/ledc.h" #include "esp_err.h" //Для подключения таймера #define LEDC_LS_TIMER LEDC_TIMER_1 #define LEDC_LS_MODE LEDC_LOW_SPEED_MODE //Для подключения первого светодиода #define LEDC_LS_CH0_GPIO (8) #define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0 //Для подключения второго светодиода #define LEDC_LS_CH1_GPIO (5) #define LEDC_LS_CH1_CHANNEL LEDC_CHANNEL_3 #define LEDC_TEST_CH_NUM (2) //число светодиодов #define LEDC_TEST_DUTY (8191)//максимальная интенсивность void app_main(void) { int ch; /*Конфигурация таймера*/ ledc_timer_config_t ledc_timer = { .duty_resolution = LEDC_TIMER_13_BIT, .freq_hz = 5000, .speed_mode = LEDC_LS_MODE, .timer_num = LEDC_LS_TIMER, .clk_cfg = LEDC_AUTO_CLK, }; ledc_timer_config(&ledc_timer); /*Конфигурация двух ШИМ-каналов*/ ledc_channel_config_t ledc_channel[LEDC_TEST_CH_NUM] = { { .channel = LEDC_LS_CH0_CHANNEL, .duty = 0, .gpio_num = LEDC_LS_CH0_GPIO, .speed_mode = LEDC_LS_MODE, .hpoint = 0, .timer_sel = LEDC_LS_TIMER, .flags.output_invert = 0 }, { .channel = LEDC_LS_CH1_CHANNEL, .duty = 0, .gpio_num = LEDC_LS_CH1_GPIO, .speed_mode = LEDC_LS_MODE, .hpoint = 0, .timer_sel = LEDC_LS_TIMER, .flags.output_invert = 1 /*1 - сигнал на выходе инвертируется*/ }, }; for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { ledc_channel_config(&ledc_channel[ch]); } while (1) { /*Установка и обновление интенсивности для каждого канала*/ printf(" LEDC set duty from %d to 0 without autofade\n", LEDC_TEST_DUTY); for(int i = 0; i<LEDC_TEST_DUTY; i+= 40){ for (ch = 0; ch < LEDC_TEST_CH_NUM; ch++) { ledc_set_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel, LEDC_TEST_DUTY-i); ledc_update_duty(ledc_channel[ch].speed_mode, ledc_channel[ch].channel); } vTaskDelay(10 / portTICK_PERIOD_MS); } vTaskDelay(100 / portTICK_PERIOD_MS); } }
14.4 Вопросы для контроля
- Поясните правила управления яркостью светодиода с использованием ШИМ сигнала.
- Какие действия необходимо выполнить для настройки LED PWM контроллера?
- Как осуществляется настройка таймера? Какую функцию выполняет предварительный делитель?