Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[C] - Błędny odbiór przez UART

splawik00 26 Gru 2014 17:38 1005 16
  • #1 26 Gru 2014 17:38
    splawik00
    Poziom 23  

    Witam.
    Mam pewien problem z UART. Próbuję zrealizować odbiór danych na Atmega8.
    Rzecz wydawałaby się prosta, ale jednek gdzieś mam błąd i nie mogę go znaleźć.
    Biblioteka jaką wykorzystuję jest napisana przez Peter'a Fleury. Wykorzystuje ona bufor cykliczny, więc samo odbieranie danych z rejestru i zapis do stringa są już realizowane przez bibliotekę. Ja chcę je odczytać z tego stronga i zapisać do swojego stringa. Niestety nie udaje mi się to.
    Założenie mam takie, że odbieram w pętki głównej znak. Sprawdzam, czy jest to jakaś dana. Jak tak to odbieram w pętli to co nadchodzi, dopóki odebrany znak będzie zerem. Później chcę wysłać "x" na znak, że dane odebrane.
    Problem jest taki, że po wysłaniu tekstu "test" do atmegi program odczyta mi "t". Później w pętli powinien odczytać jeszcze "est", ale niestety wychodzi z tej pętli (widocznie uznaje, że nie ma danych w buforze).
    Efekt jest taki, że jeżeli wysyłam "test" z terminala (bez CR i LF) to Atmega wyśle mi cztery razy "x". Ewidentnie program zamiast siedzieć w pętli odbioru danych dopóki nie dobierze wszystkich znaków, po prostu z niego wychodzi za każdym razem gdy odbierze jeden znak i wraca do pętli głównej gdzie dopiero następuje jego odebranie. I tak cztery razy.
    Co ciekawe jeśli dodam opóźnienie ~5ms w pętli odbioru to wszystko odbiera się normalnie. Ale przecież nie mogę stosować opóźnienia, bo gdyby string miał ze 100 znaków to będę go odbierał pół sekundy. Dodam również, że zmiana prędkości transmisji nie ma znaczenia (9600 - 38400). Gdzie może być błąd?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 16
  • #2 26 Gru 2014 19:22
    666w
    Poziom 9  

    brakuje mi nawiasu kończącego blok kodu po if(chr != UART_NO_DATA){
    brak zabezpieczenia przed przekroczeniem tablicy string[100];

    0
  • #3 26 Gru 2014 19:37
    splawik00
    Poziom 23  

    Nawias w kodzie jest, tylko mi się na forum coś źle wkleiło. Już poprawione w poście.
    Natomiat jeżeli chodzi o zabezpieczenie tablicy przed nadpisaniem, to jestem w pełni tego świadomy. Ale specjalnie nie dodawałem na razie takich rzeczy, bo chodzi o samą ideę, że nie działa odbiór. Nie wysyłam do testu żadnych długich stringów. Co najwyżej kilka znaków.

    0
  • #4 26 Gru 2014 20:36
    zumek
    Poziom 39  

    splawik00 napisał:
    ... Ewidentnie program zamiast siedzieć w pętli odbioru danych dopóki nie dobierze wszystkich znaków, po prostu z niego wychodzi za każdym razem gdy odbierze jeden znak i wraca do pętli głównej gdzie dopiero następuje jego odebranie...

    Ja tu nie widzę nic dziwnego :D
    Twoja druga pętla while(1) jest dużo szybsza od magistrali szeregowej i to wszystko.
    A odpowiedź już sam właściwie podałeś, pisząc o 5ms opóźnieniu.
    Musisz inaczej rozwiązać kopiowanie danych z bufora. Jżeli to będą wyłącznie dane tekstowe, to dobrym rozwiązaniem będzie dodawanie na końcu takiego stringu, CR+LF albo jakieś własne rozwiązanie.

    0
  • #5 26 Gru 2014 20:45
    splawik00
    Poziom 23  

    No właśnie też na taki pomysł wpadłem, dlatego to opóźnienie na próbę.
    Ale jak to inaczej rozwiązać w takim razie? Dane będę odbierał z zewnętrznego modułu, który komunikuje się z UARTem, więc nie mam wpływu na to co wysyła. Chciałem odczytać stringa, żeby móc go później sparsować z innym.

    0
  • #6 26 Gru 2014 20:54
    tmf
    Moderator Mikrokontrolery Projektowanie

    Nie ma siły, string musi się kończyć jakimś znakiem terminującym. Zwykle takim znakiem jest kod NUL (0x00). Inna możliwość to po prostu czekanie, jeśli przez określony czas nie pojawia się kolejny znak to mamy timeout i uznajemy, że nastąpił koniec transmisji.

    0
  • #7 26 Gru 2014 20:59
    zumek
    Poziom 39  

    splawik00 napisał:
    Dane będę odbierał z zewnętrznego modułu, który komunikuje się z UARTem, więc nie mam wpływu na to co wysyła. Chciałem odczytać stringa, żeby móc go później sparsować z innym.
    Przyślij mi ten moduł na parę dni ... :wink:

    splawik00 napisał:
    Ale jak to inaczej rozwiązać w takim razie?
    ... to Ci podpowiem jak :D

    To taki Świąteczny żart :spoko:

    Opisz jakie dane ten moduł wysyła, to coś zaradzimy, bo wróżyć nie mam zamiaru.

    0
  • #8 26 Gru 2014 21:25
    splawik00
    Poziom 23  

    Jest to ESP8266, moduł WIFI.
    Ciężko określić co ten moduł wysyła, bo jest to tyle różnych stringów o tak różnych długościach, nawet kilkuset znaków. Przy odbieraniu strony www mamy cały kod HTML. Z tego chcę wyłowić co mi potrzebne.
    Ale główne założenie to odbiór danych z innego modułu WIFI po TCP.
    Więc znaków kilkaset, ale to nie znaczy, że muszę je wszystkie odebrać.
    Wystarczy mi pierwszych, powiedzmy 50 znaków w których mam tę swoją przesłaną wiadomość. Ona zawsze jest w miare na początku, ale jednak jej pozycja różni się o kilka znaków co jakiś czas.
    Dla przykładu z poniższego ciągu znaków chcę jedynie sprawdzić, czy występuje tam ciąg znaków "GET". Do użycia będzie strstr() z biblioteki string.h, ale na razie chodziło mi o sam odbiór, żebym mógł ten odebrany string do tej funkcji przekazać.

    Cytat:
    Link

    +IPD,0,367:GET / HTTP/1.1
    Host: 192.168.4.1
    Connection: keep-alive
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36
    DNT: 1
    Accept-Encoding: gzip, deflate, sdch
    Accept-Language: pl-PL,pl;q=0.8,en-US;q=0.6,en;q=0.4


    OK
    Unlink

    0
  • #9 26 Gru 2014 21:33
    tmf
    Moderator Mikrokontrolery Projektowanie

    Przyjrzyj się jak ta wiadomość wygląda w rozpisaniu na kody, idę o zakład, że linie końcą się CR+LF.

    0
  • #13 27 Gru 2014 21:30
    tmf
    Moderator Mikrokontrolery Projektowanie

    Ulepszyłbym o tyle, że skoro wykorzystujesz soft posiadający bufor cykliczny, to zamiast tak jak napisałeś blokującej obsługi USART, zmieniłbym kod tak, żeby odbierał w przerwaniach kolejne znaki i po natrafieniu na CR/LF sygnaizował, że do sparsowania jest cały wiersz. W ten sposób odblokowujesz pętlę główną. Oczywiście warto też zrobić tak, żeby przerwa resetowała bufor.

    0
  • #15 27 Gru 2014 22:23
    splawik00
    Poziom 23  

    Tylko, że biblioteka UARTa używa przerwań. To musiłałbym przerwanie odbioru przenieść do main.c i kombinować. Trochę wyjdzie namieszane. Jak znajdę chwilę to spróbuję poczytać jak to jest rozwiązane w tym artykule z linka.
    Akurat w tym kodzie nie zależy mi na prędkości, a w pętli głównej nie będzie nic poza odbiorem danych i przełączaniem pinów procka.

    0
  • #16 27 Gru 2014 22:35
    tmf
    Moderator Mikrokontrolery Projektowanie

    To zmień kod źródłowy tej biblioteki i dostosuj ją do własnych potrzeb. Pisanie nieblokujących funkcji warto ćwiczyć w każdym przypadku - tu main masz wolny, ale w innej aplikacji będzie to przeszkadzać. Czemu więc nie napisać tego raz a dobrze, posłuży na lata :)
    Swoją drogą jeśli cała biblioteka sprowadza się tylko do getc(), które sprawdzasz w pętli, to po co ci ta biblioteka i bufor pierścieniowy?

    0
  • #17 29 Gru 2014 16:53
    nsvinc
    Poziom 35  

    To klasyczne bujanie sie z parserem AT. Na forum rozne parsery tego juz sie przewijały, były tam rozwiązania od średnio działających, przez standardowe i sprawdzone, do hardcorów (na wątku, z DMA, 'inteligentnych', potrafiących sprawdzać poprawność składniową odpowiedzi).

    BTW, nie licz na to, ze bezposrednio po jednoznacznym pytaniu dostaniesz jednoznaczną odpowiedź. Poprawny parser AT powinien potrafić:
    a) znać pytanie i oczekiwać na odpowiedź, najlepiej sprawdzac rowniez jej poprawność pod kątem zadanego pytania
    b) niezaleznie od faktu, czy pytanie było, czy też nie, parsować tzw. URC i wpychać je do jakiejs oddzielnej kolejki

    Jesli parser nie będzie spełniac powyzszych, to stabilna komunikacja softu z modemem będzie zgoła niemożliwa...

    0