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

Прежде чем продолжить, убедитесь, что у вас установлена последняя версия VS Code и настроено расширение ESP-IDF:
- Установка ESP32 ESP-IDF на Windows и его интеграция с Visual Studio Code
- Установка ESP32 ESP-IDF на Linux Ubuntu
Дополнительно на нашем сайте вы можете прочитать статью про начало работы с 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:
|
1 |
#include "driver/uart.h" |
Настройка параметров связи
Первым шагом является настройка параметров связи по UART. К ним относятся следующие:
- Скорость передачи данных;
- Биты данных;
- Контроль четности;
- Количество стоп-битов;
- Аппаратный режим управления потоком;
- Режим связи.
Как правило, существует два способа настройки этих методов связи.
В первом, более распространенном методе, мы настраиваем все параметры за один шаг. Это делается путем создания структуры uart_config_t , содержащей все определения необходимых параметров. Затем вызывается функция uart_param_config() , которая принимает в качестве параметров порт UART и указанную выше структуру. Это позволит настроить параметры UART.
|
1 2 3 4 5 6 7 8 9 10 11 |
const uart_port_t uart_num = UART_NUM_2; uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS, .rx_flow_ctrl_thresh = 122, }; // Configure UART parameters ESP_ERROR_CHECK(uart_param_config(uart_num, &uart_config)); |
Второй метод предполагает вызов отдельных функций для настройки каждого из параметров. В таблице ниже показаны параметры и соответствующие им функции настройки.
| Скорость передачи данных | 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.
|
1 |
esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) |
В следующей функции мы устанавливаем GPIO4 в режим TX, GPIO5 в режим RX, GPIO18 в режим RTS и GPIO19 в режим CTS для UART2.
|
1 |
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, 4, 5, 18, 19)); |
Установка драйвера
Далее мы выделяем ресурсы ESP32 для драйвера UART. Этот этап знаменует завершение настройки UART. Для выделения необходимых внутренних ресурсов для драйвера UART мы используем функцию uart_driver_install() . Она принимает пять параметров. Первый параметр — номер порта UART. Остальные параметры перечислены ниже в порядке следования:
- rx_buffer_size (Размер кольцевого буфера приема).
- tx_buffer_size (Размер кольцевого буфера TX).
- queue_size (размер очереди событий UART).
- uart_queue (дескриптор очереди событий UART).
- intr_alloc_flags (Флаги для выделения прерывания).
|
1 |
esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_buffer_size, int queue_size, QueueHandle_t *uart_queue, int intr_alloc_flags) |
Сначала настроим буферизованный ввод-вывод UART с очередью событий следующим образом:
|
1 2 |
const int uart_buffer_size = (1024 * 2); QueueHandle_t uart_queue; |
Далее мы устанавливаем драйвер, используя очередь событий:
|
1 2 |
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, uart_buffer_size, \ uart_buffer_size, 10, &uart_queue, 0)); |
Отправка и получение данных
Этот этап обозначает начало работы UART. Контроллер UART имеет конечный автомат, обычно называемый FSM, который управляет связью UART. FSM отвечает за весь процесс, в рамках которого приложение просто считывает и записывает данные в определенный буфер. Рассмотрим каждый из этих шагов.
Передача данных
Для последовательной передачи данных сначала записывается информация в буфер TX FIFO. Затем конечный автомат сериализует эти данные и отправляет их. Для записи данных в кольцевой буфер TX используется функция uart_write_bytes() . Когда в буфере TX FIFO появляется свободное место, данные перемещаются из кольцевого буфера в буфер FIFO. Этот процесс происходит автоматически с помощью обработчика прерываний.
Функция uart_write_bytes() принимает три параметра. Первый параметр — номер UART-порта. Второй параметр — адрес буфера данных, а третий параметр — длина передаваемых данных.
|
1 |
int uart_write_bytes(uart_port_t uart_num, const void *src, size_t size) |
Ниже вы можете увидеть код, демонстрирующий использование этой функции для передачи сообщения «Добро пожаловать на esp32tutorials».
|
1 2 |
char* message = "Welcome to esp32tutorials\n"; uart_write_bytes(uart_num, (const char*)message, strlen(message)); |
Прием данных
Аналогично, для последовательного приема данных конечный автомат сначала обрабатывает входящие данные и распараллеливает их. Затем он записывает данные в буфер RX FIFO. Наконец, эти данные считываются из буфера RX FIFO. Для чтения данных, уже находящихся в буфере RX FIFO, используется функция uart_read_bytes() . Эта функция принимает четыре параметра. Первый параметр — номер порта UART. Второй параметр — указатель на буфер. Третий параметр — длина данных, а последний параметр — количество тактов RTOS.
|
1 |
int uart_read_bytes(uart_port_t uart_num, void *buf, uint32_t length, TickType_t ticks_to_wait) |
Пример эхо-сигнала 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’ («Выбрать шаблон»), чтобы продолжить.
В разделе Extension («Расширение») выберите опцию ESP-IDF:
На вкладке UART мы нажмем на «uart_echo». Затем нажмем ‘Create project using template uart_echo.’ («Создать проект, используя шаблон uart_echo»).
Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».
Это откроет созданный нами проект ESP_IDF_UART_ECHO во вкладке EXPLORER. Внутри папки проекта находится несколько папок. Это справедливо для всех проектов, которые вы будете создавать с помощью ESP-IDF Explorer.
Редактор конфигурации ESP-IDF SDK
Для начала перейдем в меню menuconfig. Щелкните значок, показанный ниже. Откроется редактор конфигурации ESP-IDF SDK.
Прокрутите вниз и откройте Echo Example Configuration (пример конфигурации эхо-контроллера) для нашего проекта. Здесь мы можем установить параметры конфигурации UART в соответствии с нашими потребностями. Это включает номер порта UART, скорость связи UART (бодовая скорость), контакты RX и TX UART, а также размер стека для задачи. Здесь вы можете увидеть, что по умолчанию ESP-IDF использует порт UART номер 2 (UART2), бодовую скорость 115200, контакт RX — GPIO5, контакт TX — GPIO4, а размер стека задачи — 2048. Вы можете изменить эти параметры, а затем нажать кнопку «Сохранить», расположенную вверху. Мы оставим настройки конфигурации по умолчанию.
Перейдём к файлу main.c. В папке main находится исходный код, поэтому файл main.c будет расположен именно там.
Теперь перейдите в файл main > uart_echo_example_main.c и откройте его.
Ниже приведён код, который демонстрирует работу функции эхо-ответа через UART. Он будет отправлять полученное сообщение через UART2 обратно отправителю.
Код ESP-IDF: ESP32 UART Echo
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
/* UART Echo Example This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/uart.h" #include "driver/gpio.h" #include "sdkconfig.h" /** * This is an example which echos any data it receives on configured UART back to the sender, * with hardware flow control turned off. It does not use UART driver event queue. * * - Port: configured UART * - Receive (Rx) buffer: on * - Transmit (Tx) buffer: off * - Flow control: off * - Event queue: off * - Pin assignment: see defines below (See Kconfig) */ #define ECHO_TEST_TXD (CONFIG_EXAMPLE_UART_TXD) #define ECHO_TEST_RXD (CONFIG_EXAMPLE_UART_RXD) #define ECHO_TEST_RTS (UART_PIN_NO_CHANGE) #define ECHO_TEST_CTS (UART_PIN_NO_CHANGE) #define ECHO_UART_PORT_NUM (CONFIG_EXAMPLE_UART_PORT_NUM) #define ECHO_UART_BAUD_RATE (CONFIG_EXAMPLE_UART_BAUD_RATE) #define ECHO_TASK_STACK_SIZE (CONFIG_EXAMPLE_TASK_STACK_SIZE) #define BUF_SIZE (1024) static void echo_task(void *arg) { /* Configure parameters of an UART driver, * communication pins and install the driver */ uart_config_t uart_config = { .baud_rate = ECHO_UART_BAUD_RATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .source_clk = UART_SCLK_APB, }; int intr_alloc_flags = 0; #if CONFIG_UART_ISR_IN_IRAM intr_alloc_flags = ESP_INTR_FLAG_IRAM; #endif ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config)); ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS)); // Configure a temporary buffer for the incoming data uint8_t *data = (uint8_t *) malloc(BUF_SIZE); while (1) { // Read data from the UART int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS); // Write data back to the UART uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len); } } void app_main(void) { xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL); } |
Как работает код?
Для начала мы подключим необходимые библиотеки, включая библиотеки FreeRTOS для генерации задержек и создания задач, driver/gpio.h, поскольку нам нужно назначить сигналы периферийного устройства UART на контакты GPIO ESP32, и driver/uart.h для связи по UART.
|
1 2 3 4 5 6 |
#include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/uart.h" #include "driver/gpio.h" #include "sdkconfig.h" |
Затем мы определили несколько переменных, включая контакты RX, TX, RTS и CTS, скорость передачи данных, номер порта UAT и размер стека задач. Эти переменные будут обращаться к значениям, которые мы задали ранее в menuconfig, поэтому значения уже определены.
|
1 2 3 4 5 6 7 8 |
#define ECHO_TEST_TXD (CONFIG_EXAMPLE_UART_TXD) #define ECHO_TEST_RXD (CONFIG_EXAMPLE_UART_RXD) #define ECHO_TEST_RTS (UART_PIN_NO_CHANGE) #define ECHO_TEST_CTS (UART_PIN_NO_CHANGE) #define ECHO_UART_PORT_NUM (CONFIG_EXAMPLE_UART_PORT_NUM) #define ECHO_UART_BAUD_RATE (CONFIG_EXAMPLE_UART_BAUD_RATE) #define ECHO_TASK_STACK_SIZE (CONFIG_EXAMPLE_TASK_STACK_SIZE) |
Кроме того, в этом коде мы определим размер буфера. Он составляет 1024 байта или приблизительно 1 килобайт.
|
1 |
#define BUF_SIZE (1024) |
echo_task()
Далее у нас есть функция echo_task(). Она состоит из структуры uart_config_t, содержащей все необходимые параметры для связи по UART. Позже она будет передана в качестве параметра в функцию uart_param_confg() при настройке параметров связи по UART. Используемая конфигурация: 8 бит данных, отсутствие бита четности и 1 стоповый бит (8-N-1) со скоростью передачи данных 115200 бод. Кроме того, тактовая частота источника UART установлена на APB.
|
1 2 3 4 5 6 7 8 9 10 |
static void echo_task(void *arg) { uart_config_t uart_config = { .baud_rate = ECHO_UART_BAUD_RATE, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .source_clk = UART_SCLK_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.
|
1 |
ESP_ERROR_CHECK(uart_driver_install(ECHO_UART_PORT_NUM, BUF_SIZE * 2, 0, 0, NULL, intr_alloc_flags)); |
Настройка параметров UART
Далее мы вызываем функцию uart_param_config() для установки параметров конфигурации UART. Она принимает два параметра. Первый параметр — это номер порта UART, а второй — параметры настройки UART, которые мы задали в функции echo_task().
|
1 |
ESP_ERROR_CHECK(uart_param_config(ECHO_UART_PORT_NUM, &uart_config)); |
Установка контактов для связи
Для установки контактов связи UART (TX, RX, RTS и CTS) мы будем использовать функцию uart_set_pin() и указывать в качестве параметров контакты GPIO. В нашем случае драйвер будет назначать сигналы TX, RX, RTS и CTS соответствующим контактам GPIO, которые мы установим.
|
1 |
ESP_ERROR_CHECK(uart_set_pin(ECHO_UART_PORT_NUM, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS)); |
Мы создадим временный буфер для поступающих данных, выделив динамическую память.
|
1 |
uint8_t *data = (uint8_t *) malloc(BUF_SIZE); |
Использование UART-связи
Внутри цикла while мы будем считывать данные из UART2, вызывая функцию uart_read_bytes(), и сохранять их в целочисленной переменной 'len'. Затем мы запишем эти данные (len) обратно в UART, используя функцию uart_write_bytes().
|
1 2 3 4 |
while (1) { int len = uart_read_bytes(ECHO_UART_PORT_NUM, data, BUF_SIZE, 20 / portTICK_RATE_MS); uart_write_bytes(ECHO_UART_PORT_NUM, (const char *) data, len); } |
app_main()
Внутри функции main() мы создадим задачу. Для создания задачи используйте функцию xTaskCreate(). Эта функция принимает несколько аргументов.
- Первый аргумент — это имя функции. В нашем случае мы установили его значение равным echo_task.
- Второй аргумент — это имя задачи для описательных целей. В нашем случае мы задали второй аргумент как «uart_echo_task».
- Третий аргумент задает размер стека задачи. Он указывает объем памяти, который мы хотим зарезервировать для конкретной задачи. Мы установили его значение равным '2048', что является значением по умолчанию.
- Четвертый аргумент — это параметр. Это значение, которое передается в качестве параметра создаваемой задаче. Его можно использовать для указания переменной, которая используется в основной функции и значение которой необходимо добавить в задачу. В нашем случае мы установим этот аргумент равным NULL, что означает, что мы не используем это свойство.
- Пятый аргумент — это приоритет задачи. Мы установили его равным «10».
- Последний аргумент — это дескриптор, используемый для изменения функции задачи, например, приостановки, удаления, возобновления, получения или установки конфигурации задачи. Он работает как указатель, поэтому с ним используется символ амперсанда. Он необязателен, поэтому мы также можем установить его в NULL. В нашем случае мы установили его в NULL.
|
1 2 3 4 |
void app_main(void) { xTaskCreate(echo_task, "uart_echo_task", ECHO_TASK_STACK_SIZE, NULL, 10, NULL); } |
Компиляция скетча
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.
|
1 |
idf.py -p COMX flash monitor |
После успешной прошивки подключите 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-порта и скорость передачи данных. Затем нажмите «Открыть».

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

Пример асинхронных задач приема/передачи 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’ («Выбрать шаблон»), чтобы продолжить.
В разделе Extension («Расширение») выберите опцию ESP-IDF:
На вкладке UART мы щелкнем по пункту «uart_async_rxtxtasks». Затем нажмем ‘Create project using template uart_async_rxtxtasks’ («Создать проект, используя шаблон uart_async_rxtxtasks»).
Вы получите уведомление о создании проекта. Чтобы открыть проект в новом окне, нажмите «Да».
Это откроет созданный нами проект ESP_IDF_UART_RxTxTasks во вкладке EXPLORER. Теперь перейдите в main > uart_async_rxtxtasks_main.c и откройте его.
Откроется следующий код, показанный ниже.
Код ESP-IDF: асинхронные задачи приема и передачи через UART на ESP32
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
/* UART asynchronous example, that uses separate RX and TX tasks This example code is in the Public Domain (or CC0 licensed, at your option.) Unless required by applicable law or agreed to in writing, this software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_log.h" #include "driver/uart.h" #include "string.h" #include "driver/gpio.h" static const int RX_BUF_SIZE = 1024; #define TXD_PIN (GPIO_NUM_4) #define RXD_PIN (GPIO_NUM_5) void init(void) { const uart_config_t uart_config = { .baud_rate = 115200, .data_bits = UART_DATA_8_BITS, .parity = UART_PARITY_DISABLE, .stop_bits = UART_STOP_BITS_1, .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, .source_clk = UART_SCLK_APB, }; // We won't use a buffer for sending data. uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0); uart_param_config(UART_NUM_1, &uart_config); uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE); } int sendData(const char* logName, const char* data) { const int len = strlen(data); const int txBytes = uart_write_bytes(UART_NUM_1, data, len); ESP_LOGI(logName, "Wrote %d bytes", txBytes); return txBytes; } static void tx_task(void *arg) { static const char *TX_TASK_TAG = "TX_TASK"; esp_log_level_set(TX_TASK_TAG, ESP_LOG_INFO); while (1) { sendData(TX_TASK_TAG, "Hello world"); vTaskDelay(2000 / portTICK_PERIOD_MS); } } static void rx_task(void *arg) { static const char *RX_TASK_TAG = "RX_TASK"; esp_log_level_set(RX_TASK_TAG, ESP_LOG_INFO); uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1); while (1) { const int rxBytes = uart_read_bytes(UART_NUM_1, data, RX_BUF_SIZE, 1000 / portTICK_RATE_MS); if (rxBytes > 0) { data[rxBytes] = 0; ESP_LOGI(RX_TASK_TAG, "Read %d bytes: '%s'", rxBytes, data); ESP_LOG_BUFFER_HEXDUMP(RX_TASK_TAG, data, rxBytes, ESP_LOG_INFO); } } free(data); } void app_main(void) { init(); xTaskCreate(rx_task, "uart_rx_task", 1024*2, NULL, configMAX_PRIORITIES, NULL); xTaskCreate(tx_task, "uart_tx_task", 1024*2, NULL, configMAX_PRIORITIES-1, NULL); } |
Компиляция скетча
Для прошивки микросхемы введите следующую команду в последовательном терминале. Не забудьте заменить COM-порт на тот, через который подключена ваша плата.
|
1 |
idf.py -p COMX flash monitor |
После успешной прошивки подключите 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 бод, а затем нажмите «Открыть».
Терминал ESP-IDF постоянно выводит сообщение 'TX_TASK: Wrote 11 bytes', что указывает на то, что ESP32 отправляет сообщение через UART каждые 2 секунды. Терминал COM14, к которому подключен USB-TTL преобразователь, получает сообщение 'Hello world' каждые 2 секунды.
Теперь давайте отправим сообщение с компьютера на ESP32. В данном случае мы отправляем сообщение «Отправка данных на ESP32» с этого терминала на ESP32.
ESP32 получает сообщение и записывает его в терминал ESP-IDF, как показано ниже:
6 просмотров

















