ESP32: ожидание окончания передачи UART
В одном из проектов мне понадобилось притягивать к питанию один из GPIO на момент передачи данных по UART. Решение «в лоб» было простое. Включать подтяжку перед отправкой данных и снимать её сразу же следующей строкой кода:
HardwareSerial MySerial(1); // Создаём экземпляр UART на порту 1 #define RX_PIN 20 // Пин RX #define TX_PIN 21 // Пин TX void setup() { MySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Инициализируем UART на пинах RX и TX pinMode(10, OUTPUT); } void loop() { digitalWrite(10, HIGH); MySerial.println("abc"); digitalWrite(10, LOW); delay(30); }
Однако этот код работает не так как ожидалось. digitalWrite(10, LOW); срабатывает сразу же, а не после окончания передачи символов. Это прекрасно видно на осциллограмме:
Проблема заключается в том, что метод MySerial.println() работает неблокирующе (асинхронно).
Когда вы его вызываете, он не отправляет символы физически по проводу один за другим, ожидая каждого бита. Вместо этого он просто копирует строку во внутренний буфер передачи (TX buffer) и моментально возвращает управление следующей строчке кода. Сама физическая отправка битов в линию происходит в фоне с помощью аппаратных прерываний (или фоновых задач FreeRTOS на ESP32).
Из-за этого digitalWrite(10, LOW); выполняется практически мгновенно (спустя микросекунды), как только данные попали в буфер, а не когда они фактически ушли по проводам.
Решение
Чтобы принудительно дождаться окончания физической передачи всех символов из буфера, нужно вызвать метод `flush()`. Он приостанавливает выполнение программы (блокирует поток) до тех пор, пока передающий буфер не опустеет и последний бит не будет отправлен.
HardwareSerial MySerial(1); // Создаём экземпляр UART на порту 1 #define RX_PIN 20 // Пин RX #define TX_PIN 21 // Пин TX void setup() { MySerial.begin(9600, SERIAL_8N1, RX_PIN, TX_PIN); // Инициализируем UART pinMode(10, OUTPUT); } void loop() { digitalWrite(10, HIGH); MySerial.println("abc"); MySerial.flush(); // <-- Ждём, пока все символы физически уйдут по UART digitalWrite(10, LOW); delay(30); }

