UART jest sprzętowym nadajnikiem i odbiornikiem asynchronicznych ramek szeregowych. W UAV łączy flight controller z odbiornikiem RC, GNSS, modemem telemetrycznym, komputerem pokładowym, ESC lub konsolą diagnostyczną. Sam UART nie określa napięć RS-232, terminacji RS-485 ani znaczenia bajtów MAVLink, NMEA, SBUS czy CRSF. Rozdzielenie peryferium, warstwy elektrycznej i protokołu aplikacyjnego jest podstawą poprawnego projektu.

Spis treści#

Trzy osobne warstwy#

Peryferium UART zamienia bajty na bity i odwrotnie. Konfiguracja obejmuje baud rate, liczbę bitów danych, parzystość i bity stopu. Nie definiuje złącza, dopuszczalnej długości kabla ani odporności wspólnej.

Warstwa elektryczna może być:

  • CMOS/TTL o poziomach zgodnych z MCU, zwykle 3,3 V;
  • RS-232 z napięciami dodatnimi i ujemnymi oraz odwróconą logiką;
  • RS-485/RS-422 z nadajnikiem różnicowym;
  • specjalnym, odwróconym lub jednoliniowym interfejsem odbiornika RC.

Warstwa aplikacyjna określa strukturę wiadomości: NMEA/UBX dla GNSS, MAVLink dla telemetrii, CRSF/SBUS dla RC, protokół AT modemu albo własne ramki. Napis „UART 115200” nie gwarantuje interoperacyjności, jeśli pozostałe dwie warstwy się różnią.

Ramka asynchroniczna#

W typowej konfiguracji 8N1 linia jest w spoczynku wysoka. Nadajnik wysyła:

idle=1 | start=0 | d0 d1 d2 d3 d4 d5 d6 d7 | stop=1 | idle

Bit najmłodszy jest zwykle pierwszy. Nie ma osobnego zegara. Zbocze startu synchronizuje odbiornik, który następnie próbuje bity według własnego zegara. Parzystość może wykryć część pojedynczych błędów, ale nie zastępuje CRC ramki aplikacyjnej.

Konfiguracje 7E1, 8E1, 8O1, 8N2 i inne są legalne. Obie strony muszą mieć identyczne ustawienia. Niektóre MCU liczą bit parzystości do programowanej długości słowa, co prowadzi do nieintuicyjnej konfiguracji rejestrów.

Break to utrzymywanie linii w stanie aktywnym dłużej niż pełna ramka. Może być legalnym sygnałem protokołu albo skutkiem zwarcia. Sterownik powinien raportować go oddzielnie.

Baud rate i przepustowość#

Baud oznacza liczbę symboli na sekundę. Dla binarnego UART jeden symbol przenosi jeden bit, dlatego liczbowo baud i bit/s są równe na przewodzie. Dane użytkowe są mniejsze przez narzut.

Dla 8N1 każdy bajt wymaga 10 bitów: start, osiem danych i stop. Maksymalna idealna przepustowość wynosi:

payload_B/s = baud / 10

Przy 115200 baud jest to 11520 B/s przed nagłówkiem, CRC i przerwami. 8E1 wymaga 11 bitów, więc efektywność spada z 80% do około 72,7% względem surowej liczby bitów.

Wymagany baud rate oblicza się z najgorszego strumienia, nie średniej. GNSS może wysłać kilka komunikatów w krótkim burst, a telemetria — retransmitować parametry. Bufor musi pomieścić burst powstały podczas najdłuższego okresu, w którym CPU nie opróżnia RX.

Próbkowanie i tolerancja zegara#

Odbiornik wykrywa zbocze startu i zwykle nadpróbkowuje linię, na przykład 16 lub 8 razy na bit. Próbka ma przypadać blisko środka bitu. Błąd częstotliwości nadajnika i odbiornika kumuluje się przez całą ramkę, dlatego na końcu długiego słowa punkt próbkowania przesuwa się najbardziej.

Budżet obejmuje błąd oscylatora obu stron, kwantyzację dzielnika baud, jitter, asymetrię zboczy i zakłócenia. „115200” ustawione w kodzie nie oznacza dokładnie 115200 na pinie. Reference manual MCU podaje wzór dzielnika i dopuszczalny błąd dla danego oversamplingu.

Oscylator RC może być wystarczający przy temperaturze pokojowej, lecz po zmianie temperatury i napięcia przekroczyć budżet. Dla wymagającego linku zewnętrzny rezonator albo kalibracja daje większy margines.

Długi stan niski wskutek zakłócenia może zostać rozpoznany jako fałszywy start. Filtry wejściowe, Schmitt trigger i CRC protokołu pomagają, lecz ważniejsza jest właściwa warstwa fizyczna.

Błędy sprzętowe#

UART typowo raportuje:

  • framing error — bit stopu nie był wysoki w oczekiwanej chwili;
  • parity error — nie zgadza się bit parzystości;
  • noise error — próbki bitu były niespójne;
  • overrun — kolejny bajt nadszedł, zanim poprzedni został odebrany z rejestru/FIFO;
  • break — linia była aktywna przez zbyt długi czas.

Overrun jest błędem architektury czasu rzeczywistego. Samo wyczyszczenie flagi bez policzenia utraconych bajtów powoduje, że parser może zaakceptować fragment od środka jako nową wiadomość. Po utracie danych parser wraca do poszukiwania znacznika początku i weryfikuje długość oraz CRC.

Framing error często wskazuje zły baud, inwersję, poziomy napięć lub zakłócenie. Seria 0x00/0xFF może wynikać z linii zwartej albo niepodłączonej. Kody błędów i stan pinów powinny trafić do diagnostyki, nie tylko do debugowego printf.

Połączenie logic-level UART#

W pełnym dupleksie TX urządzenia A łączy się z RX urządzenia B, a RX A z TX B. Potrzebna jest wspólna referencja masy. TX–TX tworzy konflikt dwóch wyjść; RX–RX nie przesyła danych.

Poziom „TTL” jest nazwą nieprecyzyjną. Moduł 5 V może wystawiać 5 V na RX mikrokontrolera 3,3 V. Trzeba sprawdzić V_IH, V_IL, maksymalne napięcie wejścia i tolerancję pinu w danym trybie. Dzielnik rezystorowy działa tylko w jednym kierunku i z obciążeniem pojemnościowym ogranicza szybkość zbocza.

Linia niepodłączona nie może pływać. Słaby pull-up utrzymuje idle, ale jego wartość nie może nadmiernie obciążać nadajnika ani tworzyć zbyt wolnego zbocza. Po resecie MCU piny bywają wejściami, więc zewnętrzny moduł może już wysyłać dane zanim uruchomi się sterownik.

RS-232 i RS-485#

RS-232 nie jest bezpośrednio zgodny z GPIO. Klasyczny nadajnik używa napięć dodatnich i ujemnych oraz odwróconego znaczenia logicznego. Potrzebny jest transceiver, na przykład z pompą ładunkową. Podłączenie wyjścia RS-232 do pinu MCU może przekroczyć absolutne maksimum.

RS-485 przenosi sygnał różnicowo, zwykle po skrętce. Jest odporniejszy na różnicę potencjałów i EMI, dlatego lepiej nadaje się do dłuższego przewodu. Sam standard nie określa formatu pakietu ani arbitrażu wielu nadajników.

W half-duplex RS-485 sterownik kontroluje DE/RE. DE trzeba włączyć przed pierwszym bitem i wyłączyć dopiero po rzeczywistym zakończeniu bitu stopu. Flaga „bufor TX pusty” oznacza często tylko możliwość przyjęcia kolejnego bajtu, nie pustą linię. Za wczesne wyłączenie ucina koniec ramki; za późne blokuje odpowiedź drugiej strony.

Magistralę RS-485 terminujemy zgodnie z impedancją przewodu na jej końcach, nie przy każdym węźle. Rezystory bias ustalają idle, gdy nikt nie nadaje. Terminacja, topologia, dopuszczalny common-mode i ochrona ESD pochodzą z projektu warstwy fizycznej.

Inwersja i half-duplex#

Niektóre protokoły RC wykorzystują odwróconą logikę, nietypową liczbę bitów lub jedną linię w obu kierunkach. SBUS jest częstym źródłem nieporozumienia: właściwy baud i format nie wystarczą, jeśli sygnał wymaga inwersji.

Wybrane STM32 potrafią odwrócić RX/TX sprzętowo, inne wymagają zewnętrznego inwertera albo użycia innego peryferium. Funkcja zależy od konkretnej instancji i mapowania pinów.

W half-duplex na jednej linii nadajnik musi przejść w high-Z przed odpowiedzią urządzenia. Należy uwzględnić turnaround time. Echo własnych bajtów może być dostępne lub blokowane przez transceiver; parser nie powinien przypadkowo uznać go za odpowiedź.

FIFO, przerwania i DMA#

Odbiór bajt-po-bajcie przerwaniem jest prosty, ale przy wielu szybkich portach zwiększa obciążenie i jitter. Sprzętowe FIFO pozwala obsłużyć kilka bajtów naraz, lecz próg FIFO dodaje latency. DMA przenosi bloki bez udziału CPU, ale wymaga rozwiązania granicy wiadomości.

Dla ciągłego RX często używa się DMA w trybie kołowym oraz przerwania half-transfer/transfer-complete lub detekcji idle-line. Program odczytuje bieżący licznik DMA, wyznacza nowy zakres i przesuwa dane do parsera bez zatrzymywania odbioru.

Wyścigi pojawiają się, gdy DMA owija bufor w chwili odczytu wskaźnika. Algorytm musi jednoznacznie określić producenta i konsumenta, barierę pamięci oraz zachowanie przy pełnym buforze. Na MCU z data cache region DMA powinien być niecache'owany lub utrzymywany instrukcjami clean/invalidate według kierunku.

TX może korzystać z kolejki deskryptorów. Bufor musi pozostać ważny do zakończenia transmisji; wskaźnik do zmiennej lokalnej jest błędem lifetime. Callback DMA nie zawsze oznacza, że ostatni bit stopu opuścił pin.

Bufor pierścieniowy#

Ring buffer ma indeks zapisu producenta i odczytu konsumenta. Dla rozmiaru będącego potęgą dwóch można użyć maski:

next = (head + 1u) & (RX_SIZE - 1u);
if (next == tail) {
    rx_overflow++;
} else {
    rx[head] = byte;
    head = next;
}

Trzeba jawnie wybrać politykę pełnego bufora: odrzucić nowy bajt, nadpisać najstarszy pakiet albo zatrzymać nadawcę przez flow control. Dla protokołu ramkowego zwykle lepiej odrzucić uszkodzoną całość i zsynchronizować parser niż cicho mieszać fragmenty.

Indeksy współdzielone między ISR i zadaniem wymagają atomowości odpowiedniej dla MCU. volatile nie tworzy pełnej synchronizacji pamięci i nie rozwiązuje operacji wielobajtowej na 8-bitowym procesorze.

Bufor liczy się z równania burstu:

B_min > R_rx · t_max_block + największa_ramka + margines

gdzie t_max_block jest najdłuższym potwierdzonym czasem bez obsługi konsumenta, nie typową wartością z pustego systemu.

Granice ramek#

UART nie przekazuje informacji „to koniec pakietu”. Granice ustala protokół przez:

  • stałą długość;
  • pole długości po nagłówku;
  • specjalny delimiter z escapingiem;
  • przerwę czasową;
  • połączenie nagłówka, długości i CRC.

Idle-line jest użyteczne dla protokołów, które gwarantują przerwę między wiadomościami, ale nie jest uniwersalnym końcem pakietu. Scheduler nadawcy lub USB-UART może skleić ramki bez przerwy albo wstawić przerwę wewnątrz jednej wiadomości.

Parser tekstowego NMEA kończy linię CR/LF, a binarny MAVLink korzysta ze znacznika początku, nagłówka z długością i checksum. Protokół własny powinien określić maksymalną długość przed rezerwacją bufora.

Parser odporny na błędy#

Parser strumieniowy nie zakłada, że jedno wywołanie dostarcza całą ramkę. Otrzymuje dowolne fragmenty i utrzymuje stan: SEARCH_MAGIC, HEADER, PAYLOAD, CRC. Każde pole długości jest sprawdzane przed użyciem.

if długość > MAX_PAYLOAD:
    odrzuć kandydat
    wróć do wyszukiwania magic

if CRC niepoprawne:
    zwiększ licznik
    przesuń okno o co najmniej jeden bajt
    szukaj kolejnej ramki

Resynchronizacja ma graniczny koszt CPU. Atak lub szum nie może zmusić parsera do wielokrotnego kopiowania wielkiego bufora. Stosuje się indeksy, ograniczoną pracę na iterację i deadline.

Walidacja obejmuje identyfikator wiadomości, długość właściwą dla typu, CRC, numer sekwencyjny, dopuszczalny nadawca i zakres pól. Poprawne CRC nie oznacza, że komenda jest autoryzowana — protokół i system potrzebują osobnej polityki zaufania.

Kontrola przepływu#

RTS/CTS pozwala sprzętowo zatrzymać nadajnik, zanim odbiorca przepełni FIFO. Nazewnictwo i aktywny poziom należy sprawdzić po obu stronach. Nie każdy moduł respektuje CTS natychmiast; dokumentacja może podawać liczbę bajtów wysyłanych po deaktywacji.

XON/XOFF umieszcza kontrolę w danych i wymaga escaping albo protokołu tekstowego, który rezerwuje znaki. Jest podatne na utratę znaku sterującego.

Jeżeli nadajnika nie można zatrzymać, odbiornik musi zagwarantować pojemność i czas obsługi albo zaakceptować kontrolowaną utratę. Telemetria o niskim priorytecie może być odrzucana; ramki sterowania i failsafe wymagają osobnego budżetu.

Latency i czas rzeczywisty#

Czas serializacji jednego bajtu 8N1 to 10/baud. Przy 9600 baud trwa około 1,04 ms; wiadomość 100-bajtowa zajmuje ponad 104 ms bez żadnego opóźnienia programu. Zwiększenie baud zmniejsza serializację, ale nie naprawia kolejek i parsera.

Latency od próbki GNSS do EKF obejmuje wygenerowanie komunikatu przez odbiornik, transmisję, oczekiwanie w DMA, parsowanie i harmonogram zadania. Timestamp callbacku UART nie jest czasem pomiaru. Jeżeli protokół przekazuje time-of-week albo moduł ma impuls PPS, należy je skojarzyć.

Priorytet przerwania UART nie powinien wypierać krytycznego data-ready IMU przez długi parser. ISR przesuwa dane i znaczniki, a parsowanie wykonuje ograniczone czasowo zadanie. Z drugiej strony zbyt niska obsługa RX powoduje overrun — potrzebny jest pomiar worst-case latency.

GNSS, RC i telemetria#

GNSS często udostępnia tekstowe NMEA i binarny protokół producenta na tym samym porcie. Włączenie zbyt wielu komunikatów może przekroczyć baud. Konfigurację należy odczytać zwrotnie, a parser zachować odporność na mieszany strumień.

Odbiorniki RC mogą używać UART-u sprzętowo, ale protokoły różnią się inwersją, half-duplexem, formatem i latency. Failsafe nie może opierać się wyłącznie na braku bajtów; uwzględnia flagi protokołu, wiek ostatniej poprawnej ramki i wiarygodność kanałów.

MAVLink jest protokołem wiadomości działającym m.in. nad UART. Może współdzielić link z parametrami, logami i komendami, więc scheduler strumieni powinien ograniczać duże transfery. Nasycenie TX logami nie może opóźnić heartbeat ani krytycznej odpowiedzi.

Modem LTE lub radiomodem może mieć port AT i osobny kanał danych albo jeden multipleksowany strumień. Sterownik musi rozróżniać echo komend, odpowiedzi asynchroniczne i dane; prosty read until OK jest podatny na wyścigi.

Bootloader i port serwisowy#

Wiele MCU ma systemowy bootloader aktywowany kombinacją pinów i nasłuchujący UART. ST AN3155 opisuje protokół bootloadera STM32, lecz dostępne porty i komendy zależą od konkretnego układu.

Projekt FC powinien uniemożliwiać przypadkowe wejście w bootloader przez stan pływającego BOOT i przypadkowe bajty urządzenia zewnętrznego. Linie strapujące otrzymują określone rezystory, a sekwencja resetu jest testowana z podłączonym GNSS/modemem.

Port konsoli nie powinien bezwarunkowo drukować binarnych sekretów, parametrów ani zalewać czasu rzeczywistego. Produkcyjny firmware rozdziela log diagnostyczny od protokołu sterującego lub stosuje jawne multipleksowanie.

Aktualizacja firmware przez UART wymaga walidacji obrazu, odporności na utratę zasilania i kontrolowanego dostępu. Sam fakt posiadania CRC transportowego nie potwierdza pochodzenia firmware.

Okablowanie i EMI#

Single-ended UART na GPIO nadaje się przede wszystkim do krótkich połączeń wewnątrz urządzenia. Przewód przy ESC i fazach silnika zbiera szybkie zakłócenia, a różnica mas między modułami przesuwa progi.

Praktyki projektowe:

  • krótka trasa i ciągła referencja masy;
  • unikanie równoległego prowadzenia z fazami silnika i wejściem baterii;
  • mały rezystor szeregowy przy nadajniku, dobrany pomiarowo do ograniczenia ringing;
  • ochrona ESD przy zewnętrznym złączu o małej pojemności;
  • złącze z masą obok sygnałów;
  • RS-485/RS-422 lub CAN, gdy długość i środowisko przekraczają rozsądny zakres GPIO UART;
  • izolacja, jeżeli domeny masy tego wymagają.

Ekran przewodu i sposób jego zakończenia zależą od konstrukcji EMC. Nie zastępują przewodu powrotnego. Pętla masy przez ekran, zasilanie i ramę może być gorsza od braku ekranu.

Diagnostyka#

Najpierw sprawdza się warstwę fizyczną, potem format UART, na końcu protokół. Oscyloskop pokaże idle, amplitudę, inwersję, czas bitu i ringing. Analizator logiczny z poprawną konfiguracją zdekoduje bajty, ale może „poprawnie” dekodować przypadkowe dane przy niewłaściwym progu.

Procedura:

  1. zmierz poziom idle i upewnij się, że TX/RX są skrzyżowane;
  2. zmierz czas pojedynczego bitu zamiast ufać konfiguracji;
  3. zacznij od znanego wzorca 0x55, który daje regularne zbocza;
  4. potwierdź 8N1/parzystość/stop i ewentualną inwersję;
  5. uruchom sprzętowy loopback i potem urządzenie rzeczywiste;
  6. licz framing, parity, noise, overrun i break osobno;
  7. nasyć CPU, DMA i inne porty, mierząc maksymalną przerwę obsługi;
  8. testuj pełny burst oraz przepełnienie z kontrolowaną polityką;
  9. wstrzykuj ucięte ramki, zły CRC i absurdalne długości;
  10. testuj reset jednej strony w trakcie transmisji i resynchronizację.

Logiczny brak ramek nie powinien prowadzić od razu do resetu całego FC. Sterownik najpierw klasyfikuje brak sygnału, trwałe zwarcie, overrun i błąd protokołu, a następnie degraduje konkretną funkcję.

Lista uruchomieniowa#

  • Peryferium, poziomy elektryczne i protokół są opisane oddzielnie.
  • TX/RX, masa, napięcia i inwersja zostały zmierzone.
  • Rzeczywisty baud mieści się w budżecie obu zegarów.
  • Przepustowość uwzględnia bity start/stop i burst.
  • RX nie przepełnia się przy najgorszym czasie blokady CPU.
  • DMA ma bezpieczny bufor, cache maintenance i obsługę wrap.
  • Parser ogranicza długość, czas pracy i zawsze sprawdza CRC.
  • Utrata bajtu prowadzi do kontrolowanej resynchronizacji.
  • Flagi UART są liczone osobno i dostępne w logu.
  • RS-485 wyłącza DE dopiero po końcu bitu stopu.
  • Timestamp pomiaru nie jest utożsamiony z callbackiem RX.
  • Boot i aktualizacja są odporne na przypadkowe dane z portu.

Powiązane tematy#

Przypisy#

  1. STMicroelectronics, Getting started with UART — ramka, baud rate i konfiguracja UART w STM32.
  2. STMicroelectronics, AN3155: USART protocol used in the STM32 bootloader — przykład protokołu bootloadera nad USART.
  3. MAVLink, Packet serialization — przykład ramkowania, długości, sekwencji i checksum nad łączem szeregowym.

Utworzono: 15 sierpnia 2026. Ostatnia aktualizacja: 15 sierpnia 2026. Źródła zweryfikowano: 15 sierpnia 2026.

Źródła z centralnego rejestru

  1. STMicroelectronics: Getting started with UART [dokumentacja producenta]
  2. ST AN3155: USART protocol used in the STM32 bootloader [nota aplikacyjna producenta]
  3. MAVLink Packet Serialization [specyfikacja]
  4. u-blox NEO-F9P Integration Manual [dokumentacja]