logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Delphi + Tcomport] Jak poprawnie odbierać paczki danych 5 bajtów z RS232?

wicy 19 Lut 2011 11:26 1787 9
REKLAMA
  • #1 9172202
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Niby prosta sprawa, ale mam problem, z którym sam nie mogę sobie poradzić.

    Urządzenie zewnętrzne przesyła po RS232 5 bajtów danych odbieranych przez Tcomport w zdarzeniu OnRxChar.
    W OnRxChar wypełniam danymi tablicę poprzez comport.Read(din,count) i dalej w tym samym zdarzeniu przetwarzam sobie dane z tablicy.
    Problem w tym, że czasem przesłana 5 bajtowa paczka danych wywołuje dwa razy zdarzenie OnRxChar - raz z count=3 a drugi raz z count=2. Ostatnie zdarzenie nadpisuje mi 2 pierwsze bajty tablicy danych i psuje dalszą obsługę.
    Jak sobie z tym poradzić? Jak zapobiec wywoływaniu zdarzenia dwukrotnie albo zmusić program by przy drugim (może nawet trzecim) zdarzeniu uzupełnił tablicę danych a nie nadpisywał ją od początku?

    Dodam, że urządzenie z każdym razem wysyła paczkę 5 bajtów "ciurkiem" nie robiąc przerw w nadawaniu, więc wina leży po stronie programu.
  • REKLAMA
  • #2 9172348
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #3 9172398
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Nie wiem czemu tak się dzieje, ale paczki zazwyczaj odbierane są przez program:
    - w jednym wywołaniu OnRxChar z count=5
    - w dwóch wywołaniach z count=3 za pierwszym razem i count=2 za drugim.

    Warunek
    Kod: text
    Zaloguj się, aby zobaczyć kod

    jest spełniany za każdym razem jeśli paczka jest odebrana prawidłowo. Jeśli zaś przychodzi "podzielona" tracę ją a chciałbym ją posklejać.
  • REKLAMA
  • #4 9172451
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #5 9172514
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    No nie wiem bo....
    Przy obsłudze odbioru pozbawionej warunków, przyjście przykładowej paczki danych 112,3,8,1,18 wywołuje dwukrotnie procedurę odczytu. I mam:
    1) przy count=3 za pierwszym razem 112,3,8,x,x - pierwsze 3 bajty prawidłowe na prawidłowym miejscu. Dwa ostatnie x to pozostałość po prawidłowo odebranej poprzedniej paczce
    2) za drugim razem, count=2 dostaję 1,18,8,x,x

    Czyli za drugim razem w buforze nie ma już 112,3,8 odebranego przy pierwszym wywołaniu OnRxChar.
  • #6 9172576
    Konto nie istnieje
    Konto nie istnieje  
  • #7 9172649
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Nie napisałem, że za każdym razem paczka odbierana jest źle.
    Zdarza się (w 90% przypadków), że paczka odbierana jest jednym wywołaniem OnRxChar z prawidłową wartością count=5. Wtedy wypełnia tablicę din prawidłowo pięcioma bajtami np. 112,4,10,9,19.
    Jeśli kolejna transmisja jest błędna i program (nie wiem czemu) wywoła dwa razy OnRxChar, nadpisuje tablice danych od początku. Dlatego w pierwszym błędnym wywołaniu z count=3 nadpisze pierwsze 3 pozycje, pozostawiając x,x,x,9,19 na końcu tablicy. W kolejnym wywołaniu dobierze sobie te brakujące dwa bajty, ale już z count=2 i znów nadpisze tablice danych od początku, pozostawiając ostatnie 3 bajty tablicy bez zmian.

    Poradziłem sobie tymczasowo czymś takim
    Kod: text
    Zaloguj się, aby zobaczyć kod

    ale nie jest to najbardziej eleganckie rozwiązanie, bo działa tylko jeśli program odbierze paczkę prawidłowo (5 bajtów) lub podzieli ją 3/2.

    Zastanawia mnie czemu to zdarzenie w ogóle odpalane jest czasem dwukrotnie?
  • #8 9173486
    krru
    Poziom 33  
    Posty: 1819
    Pomógł: 230
    Ocena: 214
    wicy napisał:
    Jeśli kolejna transmisja jest błędna i program (nie wiem czemu) wywoła dwa razy OnRxChar,


    To nie jest błedna transmisja.

    wicy napisał:

    nadpisuje tablice danych od początku. Dlatego w pierwszym błędnym wywołaniu z count=3 nadpisze pierwsze 3 pozycje, pozostawiając x,x,x,9,19 na końcu tablicy. W kolejnym wywołaniu dobierze sobie te brakujące dwa bajty, ale już z count=2 i znów nadpisze tablice danych od początku, pozostawiając ostatnie 3 bajty tablicy bez zmian.

    Poradziłem sobie tymczasowo czymś takim

    <ciach kod bez sensu>

    ale nie jest to najbardziej eleganckie rozwiązanie, bo działa tylko jeśli program odbierze paczkę prawidłowo (5 bajtów) lub podzieli ją 3/2.

    Zastanawia mnie czemu to zdarzenie w ogóle odpalane jest czasem dwukrotnie?



    Bo RS to transmisja znakowa. Nie istnieją tam żadne ramki. Dostajesz zdarzenie jak coś przyszło i akurat komputer ma trochę czasu. Musisz być przygotowanym na odebranie dowolnej liczby bajtów - od pojedynczych znaków do nawet kilku 'ramek' jednocześnie (chyba, że nadajnik nie nada następnej ramki bez potwierdzenia poprzedniej, ale i w takiej sytuacji stosuje się timeouty, powtórzenia itp.).
    Elegenckim rozwiązaniem jest automat stanowy, dla którego zdarzeniem jest odebranie pojedynczego znaku. Jeśli odbierzesz więcej wywołujesz ten automat kilkakrotnie, dla każdego odebranego znaku oddzielnie. A sam automat może być banalny - po prostu licznik do 5 z buforem na 5 znakow.
  • Pomocny post
    #9 9173510
    Konto nie istnieje
    Konto nie istnieje  
  • #10 9173797
    wicy
    Poziom 22  
    Posty: 670
    Pomógł: 30
    Ocena: 111
    Myślę, że problemem był zbyt długi czas obsługi zdarzenia. W tym wypadku akurat dopisane było więcej poleceń dla pewnych konkretnych danych i tylko po ich 'przyjściu' i tylko przy ich 'odczycie' OnRxChar dzielił pakiet na 2 części.

    Zastosowałem warunek
    Kod: text
    Zaloguj się, aby zobaczyć kod

    i wyrzuciłem całe przetwarzanie odebranych danych do obsługi timera. Teraz wydaje się być OK. Obsługa zdarzenia trwa teraz tyle samo czasu dla każdej 'paczki' przychodzących danych i myślę, że na tyle krótko, że count zawsze będzie 5.

    Wiem, że zamiast uruchamiania timera i obróbki danych w jego przerwaniu lepiej byłoby zastosować inny wątek, ale wątków nie umiem i to już oddzielna bajka.
    Póki co dziękuję. Jeszcze będę robić testy.

Podsumowanie tematu

LABEL_AI_GENERATED
Użytkownik napotkał problem z odbieraniem 5-bajtowych paczek danych z urządzenia zewnętrznego przez RS232 przy użyciu komponentu TComPort. Zdarzenie OnRxChar wywołuje się wielokrotnie, co prowadzi do nadpisywania danych w tablicy. Użytkownik zauważył, że w 90% przypadków paczka jest odbierana poprawnie w jednym wywołaniu, ale w pozostałych przypadkach dane są dzielone na dwa wywołania z różnymi wartościami count. Proponowane rozwiązania obejmują użycie warunków do odczytu danych oraz przeniesienie przetwarzania do obsługi timera, co poprawiło sytuację. Zastosowanie automatu stanowego do obsługi pojedynczych znaków również zostało zasugerowane jako eleganckie rozwiązanie.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA