Pytanie:
Co powoduje błędy UART?
user791953
2013-09-25 18:37:46 UTC
view on stackexchange narkive permalink

Chciałbym wiedzieć, dlaczego pojawiają się błędy UART i kiedy należy je sprawdzić. Jest tutaj post, który pyta o obsługę poszczególnych błędów, takich jak przepełnienie, parzystość itp. Jasno wiem, dlaczego dochodzi do przepełnienia danych, dlaczego występuje błąd parzystości, ale chciałbym wiedzieć, jaka jest główna przyczyna. Moje pytanie jest bardziej skoncentrowane na tym, dlaczego te błędy mogą wystąpić (przyczyny fizyczne) i kiedy należy zrobić sprawdzanie błędów jako czynnika dla ich aplikacji.

Jak dotąd mój program wydaje się działać świetnie (bez sprawdzania błędów ), ale wiem, że hałas może wszystko zepsuć. Jak mogę zasymulować warunki, które mogą spowodować awarię portów UART Rx / Tx?

Pięć odpowiedzi:
Scott Winder
2013-09-25 19:33:58 UTC
view on stackexchange narkive permalink

Istnieje kilka potencjalnych źródeł szumu w każdym obwodzie. Niektóre z najczęstszych to:

  • Źle regulowane zasilacze;
  • Przełączanie zasilaczy;
  • Niewystarczające odsprzężenie pojemnościowe szyn zasilających w pobliżu MCU;
  • Sprzężenie indukcyjne pobliskich źródeł elektromagnetycznych (w tym 50 lub 60 Hz z sieci zasilającej; nawet jeśli obwód jest zasilany z baterii, wystąpi to zakłócenia, gdy są dostatecznie blisko źródła zasilania);
  • Źródła RF w pobliżu częstotliwości rezonansowej śladu na płytce drukowanej lub jednej z jej harmonicznych;
  • Trasowanie ścieżek wysokoprądowych na płytce drukowanej w pobliżu linii sygnałowych;
  • Itd.

Ponadto (jak wspomniał @jippie), odchylenie zegara jest bardzo częstą przyczyną błędów w każdym typie komunikacja szeregowa wykorzystująca z góry określoną szybkość transmisji danych. Jeśli używasz zewnętrznego kryształu i łączysz się z innym systemem, co do którego można rozsądnie oczekiwać, że będzie dokładny, jest mniej prawdopodobne, że spowoduje problemy. Jednak wewnętrzne oscylatory mogą mieć tolerancje, które są o kilka rzędów wielkości gorsze niż kryształy i mają tendencję do większych zmian w zakresie temperatur.

Istnieje kilka podstawowych testów, które można przeprowadzić na działającym systemie, aby określić podstawową odporność interfejsu na zakłócenia (i zniekształcenia), w tym:

  • Zawieszenie (ochłodzenie obwód do minimalnej oceny jego komponentów);
  • Pieczenie (podgrzać do maksymalnej wartości);
  • Ekspozycja na EMI:
    • Umieść płytkę na przewodzie zasilającym działającego grzejnika;
    • Ustaw radio CB w pobliżu tablicy;
    • Umieść płytkę obok routera bezprzewodowego;
    • Użyj długiego przewodu połączeniowego (zamiast prawidłowo skonstruowanego kabla szeregowego) do połączenia UART.

Jest wiele innych - w rzeczywistości istnieją duże laboratoria testowe zajmujące się kwalifikacją EMC.

Ogólnie rzecz biorąc, jeśli jakiś minimalny poziom utraty danych nie jest akceptowalny, zawsze rozsądnie jest uwzględnić jakiś rodzaj sprawdzania błędów w kodzie komunikacyjnym. Nawet prosta suma kontrolna jest lepsza niż nic.

jippie
2013-09-25 18:44:07 UTC
view on stackexchange narkive permalink

Jednym z częstych źródeł błędów na UART, poza jakością sygnału (szum, czasy narastania / opadania), jest przesunięcie zegara. Jeśli zegar nadajnika i zegar odbiornika nie pochodzą z tego samego źródła (co ma miejsce w większości przypadków), to jeden z nich będzie działał szybciej niż drugi. Gdy błąd synchronizacji jest zbyt duży, czasami możesz odczytać nieprawidłowy fragment.

Co spowodowałoby przesunięcie zegara, gdyby mikrokontroler został sam w czarnej skrzynce, w środku nie wiadomo gdzie?
Darmowe zegary lokalne. Każdy oscylator ma swoją własną dokładność. Zegar MCU można podzielić na użyteczną częstotliwość dla UART, ale czasami jest on odchylony o niewielki procent. Jest to z kolei spowodowane faktem, że dzielnik jest liczbą całkowitą.
Na przykład. Zegar MCU = 16 MHz, prędkość transmisji UART = 9600Bd. Wtedy UART jest zwykle taktowany częstotliwością 153600 Hz. Ale 16000000/153600 nie jest liczbą całkowitą, więc szybkość transmisji będzie wyłączona.
Tak, to da mały procent błędu. Chyba miałem to szczęście, że nie napotkałem żadnych błędów, ale jeśli są to dane krytyczne, zawsze należy je sprawdzać.
Niższa szybkość transmisji, wyższa częstotliwość zegara (zwiększa rozdzielczość próbkowania i dokładność taktowania).
supercat
2013-09-25 21:16:45 UTC
view on stackexchange narkive permalink

Większość błędów ma trzy przyczyny: (1) sygnał generowany przez przetwornik nie reprezentuje prawidłowych danych; (2) sygnał nadajnika nie został odebrany w takiej postaci, w jakiej został wygenerowany lub (3) odbiornik nie był gotowy do obsługi danych w momencie ich odebrania. Najczęstszą przyczyną problemu nr 1, jaki widziałem, jest nadajnik, który jest ponownie konfigurowany lub wyłączany podczas przesyłania danych. Problem nr 2 może łatwo wystąpić w przypadku sygnałów przechodzących przez „świat zewnętrzny” w wyniku zakłóceń radiowych (telefony komórkowe mogą być zaskakująco nieprzyjemne!), Ale generalnie nie powinien występować w przypadku sygnałów ograniczonych do jednej płytki. Problem nr 3 może wystąpić, ponieważ zbyt wiele bajtów przybywa szybciej, niż można je przetworzyć, lub ponieważ odbiornik jest rekonfigurowany, zamykany lub uruchamiany podczas transmisji.

W wielu przypadkach trudno jest całkowicie wyeliminować wszystkie te problemy; celem powinno być zapewnienie, że całkowita „szkoda” wyrządzona przez nich (prawdopodobieństwo wystąpienia, iloczyn szkód przypadających na wystąpienie) jest akceptowalnie niska. Najłatwiej można to zrobić, wybierając pesymistyczną ocenę niezawodności, a następnie projektując protokół tak, aby wpływ na wydajność systemu nawet najgorszych awarii, które były zgodne z szacunkami, mieścił się w akceptowalnych granicach.

Andy aka
2013-09-25 18:53:47 UTC
view on stackexchange narkive permalink

Błędy w ramkach mogą być spowodowane tym, o czym wspomina @jippie - odbiornik wykrył bit startu i tam, gdzie oczekuje bitu stopu, dane są odwracane. Może to być również spowodowane uszkodzeniem danych spowodowanym zakłóceniami linii wpływającymi na bit stopu. Zawsze musisz to sprawdzić dla każdego odebranego bajtu.

Błędy parzystości występują, gdy parzystość jest zaimplementowana w łączu danych i występuje uszkodzenie, które powoduje niezgodność parzystości w odebranych danych. Zawsze musisz to sprawdzić dla każdego odebranego bajtu.

Przerwa w odbiorze jest również traktowana jako błąd, chociaż w rzeczywistości oznacza, że ​​przychodzące dane spadły do ​​logicznego zera na dłużej niż 1 bajt danych. Zwykle logiczne 1 to stan „otoczenia” pomiędzy kolejnymi bajtami danych i taki pozostaje. Myślę, że to powrót do starych systemów telegraficznych. Nie zawracałbym sobie głowy sprawdzaniem tego, chyba że używasz tej "funkcji" do wskazania (powiedzmy) polecenia resetowania odbiornikowi.

Błąd przepełnienia występuje, gdy nowy bajt jest odebrany przed odczytaniem poprzedniego bajtu przez procesor. Nieco inaczej, gdy w grę wchodzi FIFO, ale prowadzi do tego samego - prawidłowe odebrane dane są tracone z powodu spowolnienia procesora. Zawsze sprawdzaj to przed odczytaniem bajtu, a jeśli bajt jest częścią dłuższej wiadomości (lub polecenia), wyrzuć całą wiadomość / polecenie i w jakiś sposób zażądaj od nadajnika ponownego wysłania całej wiadomości / polecenia.

Under run nie jest tak naprawdę błędem, ale wskazuje wysyłającemu UART, że jego bufor transmisji jest pusty, tj. żąda nowego bajtu do transmisji. Nie musisz tego sprawdzać.

Rozumiem, czym są te błędy i dlaczego się pojawiają, moje pytanie dotyczy raczej tego, kiedy należy je sprawdzać.
AilifisopiCMT - gotowe
BTW, underrun nie jest problemem w przypadku większości protokołów, ale niektóre protokoły używają bezczynnej linii do wskazania końca pakietu. W takich przypadkach niedopełnienie po stronie nadawczej może spowodować, że odbiornik będzie błędnie sądził, że pakiet kończy się, zanim powinien.
Andyz Smith
2013-09-25 20:51:28 UTC
view on stackexchange narkive permalink

Aby poradzić sobie z tymi błędami, należy zaimplementować protokół logiczny wyższego poziomu. coś podobnego do TCP lub poszukaj pomysłów w stosie OSI.

Zasadniczo dwie ważne części, od których należy zacząć, to sumy kontrolne i limity czasu. użyj algorytmu do obliczenia nadmiarowej wartości, która reprezentuje, w mniejszej formie, zawartość każdej wiadomości. następnie sprawdź to w otrzymanej wiadomości. jeśli sumy się nie zgadzają, prawdopodobnie wystąpił błąd ramek, szum bitowy itp., I będziesz musiał odrzucić wiadomość i spróbować odzyskać, ponownie wysłać, sygnał NACK (nie potwierdzony) itp.

również upewnij się, że zaimplementowałeś limity czasu w protokole wyższego poziomu. jeśli wystąpi jakiś błąd w ramce, UART może nigdy nie odzyskać sprawności i ponownie rozpocząć przetwarzanie. może czekać na bit stopu w ramce, która według UART nadawcy została już wysłana, ale została uszkodzona przez szum, przesunięcie zegara itp. spowoduje to wysłanie dowolnego kodu wejściowego do nieskończonej pętli. upewnij się, że masz rozsądne ograniczenie co do tego, jak długo czytanie danych wejściowych powinno czekać do podjęcia decyzji o porzuceniu tej wiadomości i ponownie spróbuj, NACK, porzuć itp.

Limity czasu muszą być zaimplementowane po co najmniej jednej stronie dowolnego protokołu wyższego poziomu; w wielu przypadkach najlepiej jest wdrożyć je dokładnie po jednej stronie. Posiadanie jednej strony wiecznego czekania na dane, które nigdy nie dotrą, jest problemem tylko wtedy, gdy zamiast tego mogłaby zrobić coś innego pożytecznego. Jeśli X prosi Y o jakieś dane, X będzie musiał być przygotowany do ponownego wysłania swojego żądania na wypadek, gdyby Y go nie otrzymał. Y nie musi jednak martwić się, czy X otrzyma odpowiedź. Jeśli X nie otrzyma tego, X ponownie zapyta o dane. Fakt, że X nie pyta ponownie o dane, oznacza, że ​​Y nie musi ich ponownie wysyłać.
@supercat racja, to jest dobry wzorzec, ale ja dążę bardziej do kodowania niskiego poziomu linia po linii. zawsze będziesz mieć pętlę odczytującą dane i próbującą dowiedzieć się, czy pełna wiadomość jest gotowa, jeśli kompletnej wiadomości nigdy nie ma, może zawiesić podsystem wejściowy, niezależnie od tego, czy nie ma nic innego, jak tylko czekanie Gotowe. w tym przypadku podsystem wejściowy musi przynajmniej zdać sobie sprawę, że wystąpiła awaria, opróżnić wszystkie dane gabage i zresetować je dla kolejnej próby.
Jeśli każdy pakiet zaczyna się od sekwencji bajtów, która jest zawsze możliwa do zidentyfikowania w dowolnym kontekście, i jeśli odbiorca nie ma nic pożytecznego, co może zrobić, dopóki nie otrzyma całego pakietu, po co miałoby obchodzić, czy upłynie kilka godzin po odebraniu częściowego pakietu? Następnym razem, gdy ktoś spróbuje wysłać prawdziwy pakiet, odbiorca zobaczy znacznik początku pakietu i porzuci częściowy pakiet.
@supercat, ponieważ wtedy masz pętlę, która szuka wielu rzeczy. nadal szuka końca częściowego pakietu i szuka początku nowego, nieuszkodzonego pakietu. To sprawia, że ​​logika jest znacznie bardziej złożona pod względem praktycznego kodowania.
Nie jestem pewien, na czym polega trudność. Jeśli ktoś używa pętli odbierającej bajt, będzie musiał się z niej wyrwać, jeśli nastąpi przekroczenie limitu czasu lub zostanie wyświetlony bajt początkowy. Oba zachowania muszą być obsługiwane identycznie, z wyjątkiem faktu, że sekwencja startowa powinna ustawić flagę, więc następny kod, który będzie jej szukał, nie będzie przeszkadzał.


To pytanie i odpowiedź zostało automatycznie przetłumaczone z języka angielskiego.Oryginalna treść jest dostępna na stackexchange, za co dziękujemy za licencję cc by-sa 3.0, w ramach której jest rozpowszechniana.
Loading...