Опубликован: 19.01.2025 | Доступ: свободный | Студентов: 0 / 0 | Длительность: 05:57:00
Лекция 15:

Лабораторная работа №14. Работа с LED PWM контроллером

< Лекция 14 || Лекция 15 || Лекция 16 >

14.1 Цель и задачи

Цель работы: изучить порядок настройки и использования встроенного контроллера LED PWM. Задачи:

  1. Получить навыки управления светодиодами с использованием широтно-импульсно модулированных (ШИМ) сигналов.
  2. Разработать программу для управления и индикации через светодиоды платы.

Презентация к блоку "Микроконтроллеры RISC-V"

14.2 Краткие теоретические сведения

Контроллер LED PWM - это периферийное устройство, предназначенное для генерации ШИМ сигналов для управления светодиодами, однако выходные ШИМ сигналы контроллера могут использоваться и для других целей.

Контроллер LED PWM включает в себя четыре независимых таймера (Time0 - Timer3) с поддержкой деления на доли, мультиплексор и шесть независимых ШИМ-генераторов (PWM0 - PWM5) с разрешением 14 бит (рис. 14.1).

Архитектура LED PWM контроллера

Рис. 14.1. Архитектура LED PWM контроллера

Контроллер может реализовывать затухание рабочего цикла (т.е. постепенное увеличение/уменьшение рабочего цикла ШИМ без вмешательства процессора) с генерацией прерывания по завершении затухания, позволяет регулировать фазу выходного ШИМ-сигнала, допускает перевод вывода ШИМ-сигнала в режим пониженного энергопотребления.

На рисунке 14.2 показаны настраиваемые элементы контроллера.

Каждый таймер в контроллере LED PWM реализует счет времени на основе тактового сигнала ref_pulseX. Все таймеры используют один и тот же источник тактового сигнала LEDC_CLKX, который затем пропускается через делитель тактового сигнала, чтобы сформировать ref_pulseX для счетчика.

Настройка элементов PWM контроллера

Рис. 14.2. Настройка элементов PWM контроллера

Настройка канала для генерации ШИМ-сигнала проводится в три последовательных этапа:

  1. Инициализация таймера;
  2. Инициализация канала (подключение к нему таймера и GPIO);
  3. Задание значения на выходе 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 внешним контактам.

  1. Реализовать плавное уменьшение яркости светодиода до полного его выключения в течение 10 секунд после запуска программы.
  2. Реализовать плавное увеличение яркости светодиода до его максимальной яркости в течение 10 секунд после запуска программы.
  3. Реализовать циклическое плавное уменьшение с последующим увеличением яркости. Длительность цикла - 10 секунд.

14.3.1 Описание последовательности выполнения работы

Для выполнения работы необходимо иметь беспаечную макетную плату для многократного макетирования; одножильные провода-перемычки с контактами, допускающими коммутацию с установленными на макетной плате элементами; светодиоды.

  1. Открыть шаблон проекта командой Open Folder. В качестве шаблона для первого проекта можно использовать проект Sample_project, находящийся в каталоге esp\ esp-idf\examples\get-started\
  2. Подготовить текст основной программы в соответствии с заданием, используя шаблон, реализующий формирование ШИМ сигнала с использованием контроллера и приведенный в п. 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 Вопросы для контроля

  1. Поясните правила управления яркостью светодиода с использованием ШИМ сигнала.
  2. Какие действия необходимо выполнить для настройки LED PWM контроллера?
  3. Как осуществляется настройка таймера? Какую функцию выполняет предварительный делитель?
< Лекция 14 || Лекция 15 || Лекция 16 >