Связь по UART на ESP32 с использованием ESP-IDF


В данной статье мы рассмотрим коммуникационные порты UART платы ESP32. Сначала мы обсудим некоторые важные библиотеки драйверов UART, предоставляемые в ESP-IDF, а затем продемонстрируем примеры проектов для передачи и приема данных через UART. На примере проекта мы научимся настраивать параметры UART и устанавливать драйвер UART для чтения/записи с использованием интерфейса UART. Последовательный порт (UART) также используется для отладки и программирования ESP32 с помощью USB-порта.

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

Связь по UART на ESP32 с использованием ESP-IDF

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

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

Введение в UART

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

В состав ESP32 входят три порта UART, обычно обозначаемые как UART0, UART1 и UART2. Эти три последовательных интерфейса поддерживаются аппаратно и работают на уровне TTL 3,3 В. Каждый из них имеет 4 контакта: RX, TX, RTS и CTS.

API ESP32 для связи по UART с помощью ESP-IDF

Теперь давайте обсудим библиотеку драйверов UART и ее функции, предоставляемые ESP-IDF для установления связи между устройствами UART, такими как ESP32, и преобразователем USB-TTL.

ESP-IDF предоставляет библиотеку driver/uart.h, необходимую для связи по UART. Давайте рассмотрим шаги по успешной настройке связи по UART с использованием API, предоставляемого этой библиотекой.

Это заголовочный файл, необходимый для включения драйвера UART:

Настройка параметров связи

Первым шагом является настройка параметров связи по UART. К ним относятся следующие:

  • Скорость передачи данных;
  • Биты данных;
  • Контроль четности;
  • Количество стоп-битов;
  • Аппаратный режим управления потоком;
  • Режим связи.

Как правило, существует два способа настройки этих методов связи.

В первом, более распространенном методе, мы настраиваем все параметры за один шаг. Это делается путем создания структуры uart_config_t , содержащей все определения необходимых параметров. Затем вызывается функция uart_param_config() , которая принимает в качестве параметров порт UART и указанную выше структуру. Это позволит настроить параметры UART.

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

Скорость передачи данных uart_set_baudrate()
Количество переданных битов Функция uart_set_word_length() выбрала значение из массива uart_word_length_t
Контроль четности Функция uart_set_parity() выбрала значение из uart_parity_t
Количество стоп-битов Функция uart_set_stop_bits() выбрала значение из uart_stop_bits_t
Аппаратный режим управления потоком Функция uart_set_hw_flow_ctrl() выбрала из набора данных uart_hw_flowcontrol_t
Режим связи Функция uart_set_mode() выбрала значение из uart_mode_t

Как видим, диапазон настроек параметров связи по UART достаточно широк

Конфигурирование контактов для связи по UART

На этом этапе мы назначаем физические контакты, которые позволят установить UART-связь между двумя устройствами путем их соединения.

Функция uart_set_pin() вызывается для установки контактов TX, RX, RTS и CTS, которые мы передаем в качестве параметров. Эта функция принимает пять параметров. Первый параметр — номер порта UART. Второй параметр — контакт GPIO, который мы хотим установить в качестве контакта TX. Третий параметр — контакт GPIO, который мы хотим установить в качестве контакта RX. Аналогично, четвертый параметр — контакт GPIO, который мы хотим установить в качестве контакта RTS. Наконец, последний параметр — контакт GPIO, который мы хотим установить в качестве контакта CTS. Драйвер направит указанные нами контакты GPIO на соответствующие сигналы TX, RX, RTS и CTS.

В следующей функции мы устанавливаем GPIO4 в режим TX, GPIO5 в режим RX, GPIO18 в режим RTS и GPIO19 в режим CTS для UART2.

Установка драйвера

Далее мы выделяем ресурсы ESP32 для драйвера UART. Этот этап знаменует завершение настройки UART. Для выделения необходимых внутренних ресурсов для драйвера UART мы используем функцию uart_driver_install() . Она принимает пять параметров. Первый параметр — номер порта UART. Остальные параметры перечислены ниже в порядке следования:

  1. rx_buffer_size (Размер кольцевого буфера приема).
  2. tx_buffer_size (Размер кольцевого буфера TX).
  3. queue_size (размер очереди событий UART).
  4. uart_queue (дескриптор очереди событий UART).
  5. intr_alloc_flags (Флаги для выделения прерывания).

Сначала настроим буферизованный ввод-вывод UART с очередью событий следующим образом:

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

Отправка и получение данных

Этот этап обозначает начало работы UART. Контроллер UART имеет конечный автомат, обычно называемый FSM, который управляет связью UART. FSM отвечает за весь процесс, в рамках которого приложение просто считывает и записывает данные в определенный буфер. Рассмотрим каждый из этих шагов.

Передача данных

Для последовательной передачи данных сначала записывается информация в буфер TX FIFO. Затем конечный автомат сериализует эти данные и отправляет их. Для записи данных в кольцевой буфер TX используется функция uart_write_bytes() . Когда в буфере TX FIFO появляется свободное место, данные перемещаются из кольцевого буфера в буфер FIFO. Этот процесс происходит автоматически с помощью обработчика прерываний.

Функция uart_write_bytes() принимает три параметра. Первый параметр — номер UART-порта. Второй параметр — адрес буфера данных, а третий параметр — длина передаваемых данных.

Ниже вы можете увидеть код, демонстрирующий использование этой функции для передачи сообщения «Добро пожаловать на esp32tutorials».

Прием данных

Аналогично, для последовательного приема данных конечный автомат сначала обрабатывает входящие данные и распараллеливает их. Затем он записывает данные в буфер RX FIFO. Наконец, эти данные считываются из буфера RX FIFO. Для чтения данных, уже находящихся в буфере RX FIFO, используется функция uart_read_bytes() . Эта функция принимает четыре параметра. Первый параметр — номер порта UART. Второй параметр — указатель на буфер. Третий параметр — длина данных, а последний параметр — количество тактов RTOS.

Пример эхо-сигнала UART с помощью ESP-IDF 

В этом разделе мы создадим и протестируем проект, используя драйвер UART, описанный ранее. Мы будем использовать пример UART Echo, предоставленный ESP-IDF. На примере мы покажем, как использовать интерфейсы UART. Для демонстрации данные, полученные на настроенном UART, будут отправлены обратно отправителю.

Создание примера проекта

Откройте VS Code и перейдите в менюView > Command Palette. Введите в строке поиска ESP-IDF: New Project и нажмите Enter.

Укажите название проекта и каталог. Мы назвали наш проект «ESP_IDF_UART_ECHO». Для платы ESP-IDF мы выбрали опцию custom board («Пользовательская плата»). В качестве целевой платформы ESP-IDF мы выбрали модуль ESP32. Нажмите кнопку ‘Choose Template’ («Выбрать шаблон»), чтобы продолжить.

Создание нового проекта в ESP-IDF

В разделе Extension («Расширение») выберите опцию ESP-IDF:

Выбор опции ESP-IDF в разделе Extension («Расширение»)

На вкладке UART мы нажмем на «uart_echo». Затем нажмем ‘Create project using template uart_echo.’ («Создать проект, используя шаблон uart_echo»).

Создание проекта с использованием шаблона uart_echo

Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».

Это откроет созданный нами проект ESP_IDF_UART_ECHO во вкладке EXPLORER. Внутри папки проекта находится несколько папок. Это справедливо для всех проектов, которые вы будете создавать с помощью ESP-IDF Explorer.

Редактор конфигурации ESP-IDF SDK

Для начала перейдем в меню menuconfig. Щелкните значок, показанный ниже. Откроется редактор конфигурации ESP-IDF SDK.

Кнопка для открытия редактора конфигурации ESP-IDF SDK

Прокрутите вниз и откройте Echo Example Configuration (пример конфигурации эхо-контроллера) для нашего проекта. Здесь мы можем установить параметры конфигурации UART в соответствии с нашими потребностями. Это включает номер порта UART, скорость связи UART (бодовая скорость), контакты RX и TX UART, а также размер стека для задачи. Здесь вы можете увидеть, что по умолчанию ESP-IDF использует порт UART номер 2 (UART2), бодовую скорость 115200, контакт RX — GPIO5, контакт TX — GPIO4, а размер стека задачи — 2048. Вы можете изменить эти параметры, а затем нажать кнопку «Сохранить», расположенную вверху. Мы оставим настройки конфигурации по умолчанию.

Конфигурация параметров связи UART для нашего примера

Перейдём к файлу main.c. В папке main находится исходный код, поэтому файл main.c будет расположен именно там.

Теперь перейдите в файл main > uart_echo_example_main.c и откройте его.

Открытие файла uart_echo_example_main.c

Ниже приведён код, который демонстрирует работу функции эхо-ответа через UART. Он будет отправлять полученное сообщение через UART2 обратно отправителю.

Код ESP-IDF: ESP32 UART Echo

Как работает код?

Для начала мы подключим необходимые библиотеки, включая библиотеки FreeRTOS для генерации задержек и создания задач, driver/gpio.h, поскольку нам нужно назначить сигналы периферийного устройства UART на контакты GPIO ESP32, и driver/uart.h для связи по UART.

Затем мы определили несколько переменных, включая контакты RX, TX, RTS и CTS, скорость передачи данных, номер порта UAT и размер стека задач. Эти переменные будут обращаться к значениям, которые мы задали ранее в menuconfig, поэтому значения уже определены.

Кроме того, в этом коде мы определим размер буфера. Он составляет 1024 байта или приблизительно 1 килобайт.

echo_task()

Далее у нас есть функция echo_task(). Она состоит из структуры uart_config_t, содержащей все необходимые параметры для связи по UART. Позже она будет передана в качестве параметра в функцию uart_param_confg() при настройке параметров связи по UART. Используемая конфигурация: 8 бит данных, отсутствие бита четности и 1 стоповый бит (8-N-1) со скоростью передачи данных 115200 бод. Кроме того, тактовая частота источника UART установлена ​​на APB.

Установка драйвера

Далее мы вызываем функцию uart_driver_install() для установки драйвера UART. Она принимает шесть параметров, как описано ниже:

  • uart_port_t: Это номер порта UART, который мы задали в menuconfig. Мы используем настройки по умолчанию, поэтому в нашем случае это UART2.
  • int rx_buffer_size: Это размер буфера, который мы определили как 1024 байта, умноженные на 2.
  • int tx_buffer_size: Это размер буфера TX, который в нашем случае равен 0. Это означает, что пока все данные не будут отправлены, драйвер не будет использовать этот буфер.
  • int queue_size: Это размер очереди событий UART, который устанавливается равным 0, поскольку очереди не используются.
  • QueueHandle_t *uart_queue: Это дескриптор очереди событий UART, который в нашем случае равен NULL, поскольку в этом примере очередей нет.
  • int intr_alloc_flags: Это флаг, присваиваемый прерыванию. Поскольку в этом примере мы не используем прерывание, он устанавливается в значение NULL.

Настройка параметров UART

Далее мы вызываем функцию uart_param_config() для установки параметров конфигурации UART. Она принимает два параметра. Первый параметр — это номер порта UART, а второй — параметры настройки UART, которые мы задали в функции echo_task().

Установка контактов для связи

Для установки контактов связи UART (TX, RX, RTS и CTS) мы будем использовать функцию uart_set_pin() и указывать в качестве параметров контакты GPIO. В нашем случае драйвер будет назначать сигналы TX, RX, RTS и CTS соответствующим контактам GPIO, которые мы установим.

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

Использование UART-связи

Внутри цикла while мы будем считывать данные из UART2, вызывая функцию uart_read_bytes(), и сохранять их в целочисленной переменной 'len'. Затем мы запишем эти данные (len) обратно в UART, используя функцию uart_write_bytes().

app_main()

Внутри функции main() мы создадим задачу. Для создания задачи используйте функцию  xTaskCreate(). Эта функция принимает несколько аргументов.

  • Первый аргумент — это имя функции. В нашем случае мы установили его значение равным echo_task.
  • Второй аргумент — это имя задачи для описательных целей. В нашем случае мы задали второй аргумент как «uart_echo_task».
  • Третий аргумент задает размер стека задачи. Он указывает объем памяти, который мы хотим зарезервировать для конкретной задачи. Мы установили его значение равным '2048', что является значением по умолчанию.
  • Четвертый аргумент — это параметр. Это значение, которое передается в качестве параметра создаваемой задаче. Его можно использовать для указания переменной, которая используется в основной функции и значение которой необходимо добавить в задачу. В нашем случае мы установим этот аргумент равным NULL, что означает, что мы не используем это свойство.
  • Пятый аргумент — это приоритет задачи. Мы установили его равным «10».
  • Последний аргумент — это дескриптор, используемый для изменения функции задачи, например, приостановки, удаления, возобновления, получения или установки конфигурации задачи. Он работает как указатель, поэтому с ним используется символ амперсанда. Он необязателен, поэтому мы также можем установить его в NULL. В нашем случае мы установили его в NULL.

Компиляция скетча

Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.

Компиляция скетча в VS Code

После успешной прошивки подключите ESP32 с помощью преобразователя USB в TTL. Используйте следующие соединения для подключения обоих устройств.

USB-TTL преобразователь ESP32
3,3 В 3,3 В
GND GND
RX GPIO4 (настроен как TX)
TX GPIO5 (настроен как RX)

После соединения двух устройств подключите преобразователь USB в TTL к вашей системе. Теперь откройте Диспетчер устройств > Порты и проверьте COM-порт, к которому он подключен. Обратите внимание, что это будет другой COM-порт, отличный от того, к которому в данный момент подключена плата ESP32. В нашем случае ESP32 подключен к COM5, а преобразователь USB в TTL — к COM14.

После определения порта вам потребуется открыть последовательный терминал. Мы используем Putty. Установите тип подключения как последовательный, укажите номер COM-порта и скорость передачи данных. Затем нажмите «Открыть».

Настройка Putty для связи по UART

Откроется последовательный терминал для COM14. Теперь введите любой символ с клавиатуры, и вы сможете увидеть его в терминале. Если вы отключите контакты TX или RX, символы перестанут выводиться. Это говорит о том, что эхо исходит от платы ESP32. Здесь мы отправили сообщение «UART Echo Testing».

Тестирование работы нашего примера с помощью Putty

Пример асинхронных задач приема/передачи UART с помощью ESP-IDF 

В этом разделе мы создадим и протестируем еще один пример проекта uart_async_rxtxtasks, предоставленный ESP-IDF для UART. На примере мы продемонстрируем две асинхронные задачи, использующие один и тот же интерфейс UART для обмена данными. В этом примере создаются две FreeRTOS, где первая задача отправляет сообщение «Hello world» на компьютер через UART каждые 2 секунды, а вторая задача считывает полученные данные из UART и выводит их на экран.

Создание примера проекта

Откройте VS Code и перейдите в меню View > Command Palette. Введите в строке поиска ESP-IDF: New Project и нажмите Enter.

Укажите название проекта и каталог. Мы назвали наш проект «ESP_IDF_UART_RxTxTasks». Для платы ESP-IDF мы выбрали опцию custom board («Пользовательская плата»). В качестве целевой платформы для ESP-IDF мы выбрали модуль ESP32. Нажмите кнопку ‘Choose Template’ («Выбрать шаблон»), чтобы продолжить.

Создание примера проекта в ESP-IDF

В разделе Extension («Расширение») выберите опцию ESP-IDF:

Выбор опции ESP-IDF в разделе Extension («Расширение»)

На вкладке UART мы щелкнем по пункту «uart_async_rxtxtasks». Затем нажмем ‘Create project using template uart_async_rxtxtasks’ («Создать проект, используя шаблон uart_async_rxtxtasks»).

Создание проекта с использованием шаблона uart_async_rxtxtasks

Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».

Это откроет созданный нами проект ESP_IDF_UART_RxTxTasks во вкладке EXPLORER. Теперь перейдите в main > uart_async_rxtxtasks_main.c и откройте его.

Открытие файла uart_async_rxtxtasks_main.c

Откроется следующий код, показанный ниже.

Код ESP-IDF: асинхронные задачи приема и передачи через UART на ESP32

Компиляция скетча

Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.

После успешной прошивки подключите ESP32 с помощью преобразователя USB в TTL. Используйте следующие соединения для подключения обоих устройств.

USB-TTL преобразователь ESP32
3,3 В 3,3 В
GND GND
RX GPIO4 (настроен как TX)
TX GPIO5 (настроен как RX)

После соединения двух устройств подключите преобразователь USB в TTL к вашей системе. Теперь откройте Диспетчер устройств > Порты и проверьте COM-порт, к которому он подключен. Обратите внимание, что это будет другой COM-порт, отличный от того, к которому в данный момент подключена плата ESP32. В нашем случае ESP32 подключен к COM5, а преобразователь USB в TTL — к COM14.

После определения порта вам потребуется открыть последовательный терминал. Мы используем RealTerm: последовательный/TCP-терминал. Вы можете скачать эту программу по этой ссылке ( https://sourceforge.net/projects/realterm/ ).

Откройте COM14, установите скорость передачи данных на 115200 бод, а затем нажмите «Открыть».

Настройка параметров программы RealTerm для тестирования работы нашего проекта

Терминал ESP-IDF постоянно выводит сообщение 'TX_TASK: Wrote 11 bytes', что указывает на то, что ESP32 отправляет сообщение через UART каждые 2 секунды. Терминал COM14, к которому подключен USB-TTL преобразователь, получает сообщение 'Hello world' каждые 2 секунды.

Тестирование работы нашего проекта с помощью программы RealTerm

Теперь давайте отправим сообщение с компьютера на ESP32. В данном случае мы отправляем сообщение «Отправка данных на ESP32» с этого терминала на ESP32.

Тестирование отправки сообщения с компьютера на ESP32

ESP32 получает сообщение и записывает его в терминал ESP-IDF, как показано ниже:

Пример получения сообщения ESP32 по UART и записи его в терминал

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

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

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