Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Delphi - RS232 wysyłanie i odczyt danych w sekwencji.

dawid.barracuda 02 Dec 2016 21:44 981 4
  • #1
    dawid.barracuda
    Level 13  
    Szanowni Koledzy :)
    Zastanawiam się nad realizacją pewnego problemu dotyczącego transmisji danych przez port COM z poziomu Delphi (korzystam z najnowszego 10.1 Berlin oraz pakietu AsyncPro).
    O co chodzi? Chciałbym napisać program, który realizowałby taki algorytm:
    - Wysyłam komendę na port COM;
    - Czekam na informację zwrotną;
    - Obrabiam informację zwrotną;
    - Wysyłam następną komendę na port COM;
    - Czekam na informację zwrotną;
    - Obrabiam informację zwrotną;
    - itd. jw.
    - [...]

    W mikrokontrolerze nie byłoby problemu - po prostu obsługuję UART w trybie pollingu + jakieś dodatki w postaci timeout'u po każdej wysłanej komendzie.

    Można rzec, żeby powyższe zrealizować w taki sposób:
    - Wyślij komendę 1;
    - Wyślij komendę 2;
    - Wyślij komendę 3;
    - itd.
    Czyli wysyłka danych hurtem co jakiś czas, np. co 1s odmierzaną timerem w zdarzeniu OnTimer.
    I potem odbiór odpowiedzi hurtem w jednym zdarzeniu odbiorczym.
    Nie chcę jednak robić tego w taki sposób, bo jakaś odpowiedź może przyjść uszkodzona (albo nie przyjść w ogóle). Co więcej, odpowiedzią może być surowa wartość liczbowa, więc nie zawiera w sobie informacji jakiego rozkazu dotyczy więc i żaden parser nie pomoże.
    Po prostu każda dana musi być obrobiona na swój specyficzny sposób, tryb pollingu wyjątkowo wydaje się tu być przydatny.

    Ale jak to przerzucić do Delphi, gdzie wszystko mam poupychane w procedury i wszystko działa podobnie jak na przerwaniach w mikrokontrolerze?

    Proszę uprzejmie o wskazówki i pozdrawiam.

    PS - w sumie to mam jeszcze jedno pytanie, rozważmy przykład:

    Code: delphi
    Log in, to see the code


    Czy w Delphi (lub C++ Builder) jest tak, że najpierw wysyła 3 komendy i wychodzi z procedury, a jeśli odpowiedź przyjdzie w międzyczasie to trzyma dane w buforze i po wyjściu z tej procedury dopiero idzie do procedury odbiorczej czy może jest tak, że jak przyjdzie odpowiedź przed wysyłką drugiej komendy to idzie do procedury odbiorczej, tam robi swoje, a potem wraca do wysyłki drugiej komendy? Chodzi mi o to, czy działa to podobnie jak przerwania w mikrokontrolerze czy może nie opuszcza procedur przed ich całkowitym wykonaniem?
  • Helpful post
    #2
    michcior
    Level 30  
    Nie wiem czy te najnowsze Delphi mają wbudowaną obsługę portu szeregowego czy trzeba dodać jakiś komponent jak to w starym było. Takie komponenty są dostępne w dość dużej liczbie i znalezienie w miarę sensownego to zawsze problem.
    Generalnie, Delphi działając na Windows jest niewolnikiem systemu i od niego wszystko zależy. Dane przychodzą asynchronicznie, kolejkują się w FIFO. Nie można założyć jakiegoś absolutnego podziału na bazie czasu chyba że mamy bardzo wolną transmisję na zasadzie zapytanie-odpowiedź.

    Cóż, są różne "tricki" które można stosować. Wiadomość można zdefiniować tak, że pierwszy znak ma bit 8 ustawiony na 1 a pozostałe są mniejsze od 128. Dobre dla formatu tekstowego. Albo ustalić sekwencję startową, 2-4 charakterystyczne bajty i czekać na jej wystąpienie czyli synchronizować się. Dodatkowo dobrze jest użyć sumy kontrolnej najlepiej w postaci CRC. Zwykle konstruuję pętla właśnie w taki sposób, że cały czas odbiera. W Delphi, dobrze jest po odebraniu poprawnej wiadomości złożyć ją do jakiegoś bufora lub korzystać z alokowanej pamięci, potem wysłać do jakiejś formy wiadomość zamiast wywoływać ze zdarzenia odbierającego znaki naszą procedurę przetwarzania danych.

    W każdym razie, konstrukcja "Wyślij zapytanie --> Czekaj na odpowiedź" w jednej funkcji to bardzo zły pomysł.

    Ogólnie, to program w Delphi różnie się kompletnie od programów na mikroprocesorze. Wszystko jest rozpoczynane przez zdarzenia i wszystkie procedury zdarzeń powinny być wykonywane krótko. Zrób na jakimś zdarzeniu "OnClick" nieskończoną pętlę to zobaczysz co się stanie. Czyli program należy konstruować tak, by składał się z dużej liczby szybko wykonywanych kawałków. Komunikację pomiędzy fragmentami zapewnia współdzielenie danych poprzez obiekty. Istnieje też system wiadomości (moim zdaniem bardzo przydatny) oraz wątki (dla zaawansowanych :) )
  • Helpful post
    #3
    sq9etc
    Level 12  
    Korzystam również z komponentu APro. Robię to z wykorzystaniem maszyny stanów w następujący sposób:
    1. Wysyłam polecenie 1 i ustawiam np. Stan1,
    2. Gdy urządzenie odpowie, to w zdarzeniu OnTriggerAvail sprawdzam jaki jest ustawiony stan i w zależności od tego parsuję odpowiedź,
    3. Wysyłam polecenie 2 i ustawiam np. Stan2,
    4. Gdy urządzenie odpowie, to w zdarzeniu OnTriggerAvail sprawdzam jaki jest ustawiony stan i w zależności od tego parsuję odpowiedź,
    itd...

    Cała obróbka odebranych danych odbywa się w procedurze obsługi zdarzenia OnTriggerAvail, w której są bloki odpowiadające danemu stanowi.
    Oczywiście to co przyjdzie trzeba sobie dopisywać do jakiegoś bufora i obrabiać dopiero po odebraniu pełnej ramki.
  • #4
    dawid.barracuda
    Level 13  
    Czyli - jak rozumiem - ile poleceń tyle stanów ergo tyle flag (np. zmiennych typu logicznego) w programie jakie muszę ustawić, czy tak?
  • #5
    sq9etc
    Level 12  
    Generalnie tak, z tym, że ja raczej stosuję typ wyliczeniowy.