Таймеры и задержки в FreeRTOS на ESP32 с помощью ESP-IDF


В данной статье мы рассмотрим как использовать таймеры и задержки в FreeRTOS с помощью ESP32 и ESP-IDF. Также в статье приведено сравнение функции vTaskDelay(), предоставляемой FreeRTOS, с различными значениями задержки в миллисекундах.

Таймер высокого разрешения (ESP Timer), предоставляемый FreeRTOS, использует 64-битный аппаратный таймер. FreeRTOS также предоставляет программные таймеры, которые более удобны в использовании, однако они имеют некоторые недостатки. Для обратных вызовов таймера назначается задача с низким приоритетом, а максимальное разрешение устанавливается равным периоду такта RTOS. С помощью esp_timer генерируются периодические таймеры с разрешением в микросекунды и диапазоном в 64 бита. Более того, обратные вызовы таймера инициируются из задачи esp_timer с высоким приоритетом.

Таймеры и задержки в FreeRTOS на ESP32 с помощью ESP-IDF

Прежде чем продолжить, убедитесь, что у вас установлена ​​последняя версия VS Code и настроено расширение ESP-IDF:

Также на нашем сайте вы можете прочитать статью про начало работы с ESP32 с использованием ESP-IDF.

Таймеры FreeRTOS для ESP32

Поскольку ESP-IDF основан на операционной системе FreeRTOS, мы начнем с подключения общей библиотеки FreeRTOS. Для использования функциональности таймера мы подключим заголовочный файл «freertos/timers.h».

Чтобы получить время с момента загрузки в микросекундах, мы используем функцию esp_timer_get_time(). Эта функция возвращает количество микросекунд с момента инициализации esp_timer, которая запускается до вызова функции app_main().

Код для получения времени таймера (время в микросекундах с момента загрузки)

Это полный код, который мы используем для вывода времени таймера в последовательный монитор. Функция esp_timer_get_time() вернет нам время в микросекундах с момента запуска приложения.

Результаты показывают, что с момента запуска приложения прошло 169219 микросекунд.

Демонстрация использования таймера в ESP32

Получение интервала времени между прерываниями (portTick_PERIOD_MS / portTICK_RATE_MS)

В операционной системе FreeRTOS используются различные расписания тактов. Это время между прерываниями. Некоторые из них предопределены, например, интервалы тактов между прерываниями. В FreeRTOS это определяется как portTick_PERIOD_MS. В более старой версии это определялось как portTICK_RATE_MS .

Это полный код, который мы будем использовать для вывода значений portTick_PERIOD_MS и portTICK_RATE_MS в последовательный терминал.

В выходных данных указано, что параметры portTick_PERIOD_MS и portTICK_RATE_MS заданы как 10 миллисекунд. Это подходит для частоты 100 МГц, установленной в процессоре.

Демонстрация получения интервала времени между прерываниями в ESP32

Задержка в тиках FreeRTOS

Далее мы покажем, как добавлять задержки с помощью FreeRTOS. Для генерации задержки мы будем использовать функцию «vTaskDelay». Она принимает параметр типа integer (uint32), который представляет собой константу TickType, определяющую количество тактов, которые нужно задержать. Это число соответствует такту, то есть частоте микросхемы. В функции vTaskDelay() получаемая задержка соответствует задержке конкретной задачи в количестве тактов.

В следующей программе мы измерим время работы таймера до и после задержки в 1 такт. Таким образом, мы сможем найти минимальную разницу для задержки выполнения задачи.

В выходных данных мы видим два значения таймера (время в микросекундах с момента загрузки), полученные после задержки в 1 такт. Разница между ними составляет 5383 микросекунды. Как мы уже упоминали, период такта задан как 10 миллисекунд. Однако на выполнение потребовалось меньше 10 миллисекунд.

Демонстрация задержки в тиках FreeRTOS

Задержка FreeRTOS в миллисекундах

В предыдущем примере мы рассмотрели функцию vTaskDelay() и измерили задержку в тактах. Однако чаще всего мы используем эту функцию для генерации задержек в миллисекундах.

Чтобы перевести такты в миллисекунды, мы разделим количество миллисекунд на portTICK_PERIOD_MS или portTICK_RATE_MS. Параметр portTICK_PERIOD_MS является частью директивы #defines. Он настраивается при компиляции скетча и по умолчанию устанавливается равным скорости работы микросхемы. Таким образом, деление 1 на количество тактов, в течение которых работает микросхема, даст нам миллисекунды.

В качестве альтернативы, мы также можем указать аргумент функции vTaskDelay() как pdMS_TO_TICKS() и указать количество миллисекунд в скобках.

Все три команды должны обеспечить задержку в 1 миллисекунду. Однако функция vTaskDelay() не очень точна для очень малых значений задержки. Давайте это проверим.

В приведенном ниже коде мы получаем значения таймера с задержкой в ​​1 миллисекунду.

Как видно из выходных данных, разница между двумя значениями таймера превышает 1 миллисекунду, поскольку задержка была слишком мала для идеальной работы. Нам удалось создать задержку приблизительно в 1,64 миллисекунды.

Демонстрация задержки FreeRTOS в миллисекундах

Давайте попробуем увеличить задержку до 1000 миллисекунд. Мы создадим задержку в 1000 миллисекунд, используя следующую строку кода:

Вот полный код, который мы используем:

Как видно из выходных данных, задержка между двумя значениями таймера теперь очень близка к 1000 миллисекундам. Следовательно, функция vTaskDelay() работает точнее при немного больших задержках.

Демонстрация длительной задержки FreeRTOS в миллисекундах

Сравнение значений vTaskDelay() в миллисекундах

Теперь сравним задержки для 1, 10, 100 и 1000 миллисекунд, используя функцию vTaskDelay(). В приведенном ниже коде мы использовали программу, аналогичную предыдущему примеру. Однако теперь мы увеличили количество выводимых значений таймера с увеличением задержки. Таким образом, мы будем выводить значения таймера каждые 1 миллисекунду, 10 миллисекунд, 100 миллисекунд и 1000 миллисекунд. Эти значения будут использоваться для сравнения точности генерации задержки.

Вот полный код, который мы будем использовать:

Как видно из результатов, увеличение задержки дает более точный результат по сравнению с меньшими значениями задержки. Это также было доказано в предыдущем примере.

Сравнение значений vTaskDelay() в миллисекундах

(Проголосуй первым!)
Загрузка...
54 просмотров

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *