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] Odbiór paczek 2-bajtowych z RS232 przy 600 b/s - jak to zrobić?

robiw 30 Maj 2008 14:05 5537 28
REKLAMA
  • #1 5197334
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Witam Kolegów,
    Do komputera poprzez port RS232 mam podłączony sterownik uPC, który przesyła dane w formie paczek po 2 bajty, przy czym pierwszy bajt zawsze jest > 127 (to pewien wskaźnik) a drugi bajt zawiera się w zakresie 0..47. No i jest problem bo nie mogę tych pełnych paczek odbierać za pomocą zdarzenia RxChar - wydaje się, że komponent odbiera tylko niektóre dane a prędkośc to zaledwie 600 b/sek. Ja zrealizować ten odbiór...proszę... robiw
  • REKLAMA
  • #2 5197622
    JStan
    Poziom 16  
    Posty: 297
    Pomógł: 3
    Ocena: 44
    Witam!!

    W jaki sposób robisz obsługę odbioru danych, jesli masz przykładowe programu dołączone do komponentu cport to sprawdź comport example. Jest tam polecenie ComPort.ReadStr(Str, Count); umieszczone w wywołaniu RxChar. Odbierasz dwa bajty więc w count chyba możesz zadeklarować 2. Jeśli będziesz miał nadal problemy polecam poszukać na www.4programmers.com Ja robiłem tylko obsługe wysyłania danych a nie odbierania.

    Pzdr!!
  • REKLAMA
  • #3 5197900
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    W procedurze zdarzenia RxChar Mam Comport.Read(Dana[i] , 1), gdzie dana to macierz 2-elementowa. W tej procedurze zwiększam i przy jej każdym wywołaniu i gdy i=2 to robię coś z danymi (aktualizuje pewne kontrolki). Sęk w tym, że to Read prawdopodobnie czeka na jakiś znak eventu (np. #0) a u mnie takich nie ma - leci ciąg 2 -bajtowych danych...i utknąłem w miejscu... robiw
  • #5 5198230
    Konto nie istnieje
    Konto nie istnieje  
  • #6 5198252
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Tylko po co Ord? Ja przesyłam wartości Byte i takie chce odczytywać? Poza tym jeśli faktycznie przyjdzie dana>127 to prawdopodobnie w Twojej propozycji odczytu drugiego bajta - on jeszcze nie zdąży przyjść bo baud=600. Dodatkowo, nie wiem dlaczego, przy włączaniu PCta i przy podłączonym układzie na procku - resetuje mi on kilka razy układ...robiw
  • #7 5198291
    Konto nie istnieje
    Konto nie istnieje  
  • #8 5198334
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    RTS itp mam wyłączone na comport. Kabel mam z przeplotką tzn. rx układu na tx PC i vice versa. Nie zdąży przyjść bo w delphi warunek będzie sprawdzony szybciej niż nadejdzie drugi bajt po RSie, no chyba, że procedura read czeka az w buforze pojawi się ten drugi bajt<48... robiw
  • #9 5198341
    Konto nie istnieje
    Konto nie istnieje  
  • #10 5198347
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Sprawdzę jutro ale wątpię,. Ja co prawda nie dawałem warunku tylko czytałem kolejne dane zwiększając indeks i gdy index=2 to coś z nimi robiłem... ale nie działało...myślę, że przez tą flagę event ustawianą we właściwościach...robiw
  • #11 5198371
    Konto nie istnieje
    Konto nie istnieje  
  • #12 5200867
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Działa...tyle,że pomiędzy poszczególnymi paczkami danych (2 bajtowych ze sterownika) muszę dać 100ms delay bo inaczej jakby gubił je - tzn. nie odświeża mi kontrolek suwaków - dokładnie rzecz ujmując to robi to dopiero po zajściu kolejnego zdarzenia RxChar - czyli odświeża tymi nieodczytanymi wcześniej danymi a dopiero jak wyczerpie ich "zapas" to działa na nowych, które przyszły. Przy daniu delayu w sterowniku - radzi sobie w czasie rzeczywistym...robiw
  • REKLAMA
  • #14 5202841
    Konto nie istnieje
    Konto nie istnieje  
  • #16 5203085
    Konto nie istnieje
    Konto nie istnieje  
  • #17 5203347
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Jest zapewne tak:
    - zachodzi zdarzenie RxChar, w którym czytam zmienną "Znak" instrukcją ComPort.Read i jeśli Znak>127 to w obsłudze tego zdarzenia czytam jeszcze raz port. Mając już 2 bajty odświeżam tymi danymi kontrolki znajdujące się na formularzu. Prawdopodobnie gdy odświeżam te kontrolki, a więc jestem w procedurze RxChar, nadchodzą już nowe znaki (paczka 2-bajtowa), które zostaną odczytane dopiero jak zajdzie następne zdarzenie RxChar ale przecież to następne zdarzenie to już kolejna paczka 2-bajtowa a nie ta odczytana czyli nie odświeżam tego formularza na bieżąco i dane w takim razie, mam wrażenie, przychodzą w dziwnej kolejności. Należałoby jakoś obsługiwać ten bufor a może zmienić jego właściwości...ale nie wiem jak...robiw
  • #18 5203555
    Konto nie istnieje
    Konto nie istnieje  
  • #19 5203837
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Dokładnie kodu nie pamiętam ale nie ma tam nic szczególnego. Coś takiego (proszę pominąć błędy w składni ;-) ):
    
    procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    var
     znak:byte;
    begin
     comport1.Read(znak,1);
     if znak>127 then begin
      dana[1]:=znak and 127; {maskuję bit 7 aby dostać "czysty" numer rozkazu}
      comport1.Read(znak,1);{czytam daną związaną z tym rozkazem}
      dana[2]:=znak;
      {odświeżenie suwaków kontrolek w zależności od rozkazu, który mówi dla którego suwaka przyszły dane}
      Case dana[1] of
       1: bar1.Position=50-Dana[2];
       2: bar2.Position=50-Dana[2];
       3: bar3.Position=50-Dana[2];
      end;
     end;
    
    end;
    


    Tak mniej więcej wygląda obsługa zdarzenia. Nic szczególnego. Zastanawiam się jednak nad jednym: zdarzenie RxChar zachodzi jak przyjdzie bajt, ja sprawdzam ten bajt i chcę już czytać kolejny (dla Dana[2]). Skąd wiadomo, że kolejny już jest w buforze skoro zdarzenie zaszło dla tego pierwszego (rozkazu) i jak sprawdzam warunek czy>127 i czytam ponownie to może drugiego bajta jeszcze nie ma? A jeśli jest to przecież dla niego powinno zajść drugie wywołanie zdarzenia w czasie tego które właśnie obsługuję? Jak to jest? A może czytać ilość tych bajtów, które wywołują RxChar (zmienna Count) i jakoś reagować na ich ilość? Bajty ze sterownika wysyłane są parami: rozkaz (>127) i dana związana z rozkazem (<127)? No i po co czyścić bufor - stracę przecież (chyba) nieodczytane jeszcze dane? Czy czytanie bufora nie zdejmuje automatycznie tych przeczytanych? Moje pytania biorą się pewnie z niewiedzy jak działa ta kontrolka ale jej działanie jest dziwne... robiw
  • #20 5203897
    Konto nie istnieje
    Konto nie istnieje  
  • #21 5203952
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Rozkaz może przybierać jedynie 11 wartości i tyle (te wszystkie wartości) sprawdzam w Case... (skróciłem listing) i aktualizuję wybrany suwak. Czy Dana[2] będzie już gotowa po sprawdzeniu warunku? Wątpię, bo przecież przy baud=600 b/sek następny bajt, powiedzmy, że ten Dana[2] przyjdzie dopiero po około 6.25ms a warunek myślę, że będzie sprawdzony dużo wcześniej. I nie wiem czy bufor jest automatycznie przesuwany o odczytane wartości... robiw
  • #22 5204014
    Konto nie istnieje
    Konto nie istnieje  
  • #24 5204382
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #25 5204589
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Rozumiem ale sęk w tym, że właśnie żadna dana nie może być pominięta, nawet ta pierwsza Dana[2] :-(. Może rozwiązaniem byłby odczyt asynchroniczny ale nie wiem jak podejść do tematu lub wprowadzić jakiś bufor FIFO i w innej procedurze Timera go czyścić i aktualizować...robiw
  • #26 5204638
    Konto nie istnieje
    Konto nie istnieje  
  • #27 5204779
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    maks to 30 razy na sekunde... robiw

    Dodano po 22 [minuty]:

    Pomyślmy:
    1. przychodzi nada[1]
    2. wchodzimy w procedurę rxchar
    3. czytamy dana[2]
    4. rozpoczyna sie mozolna aktualizacja kontrolki
    5. przychodzi nowa dana[1]' a my dalej w procedurze rxchar
    6. przychodzi nowa dana[2]' a my dalej j.w.
    7. kontrolka zaktualizowana i wychodzimy z procedury rxchar
    8. przychodzi kolejna dana[1]'' wywołująca zdarzenie rxchar
    9. w procedurze czytamy jakieś dane ale nie wiadomo czy stare jeszcze takie, które nie zaktualizowały kontrolek ( czyli z ') czy nowa (z '')...
    ...itd. itp... a problem może się nawarstwiać kiedy będą przychodziły często czyli pójdzie ich kilka w trakcie czasochłonnej procedury rxchar odświeżającej kontrolki na ekranie... ogólny galimatias... robiw
  • Pomocny post
    #28 5204903
    Konto nie istnieje
    Konto nie istnieje  
  • #29 5205371
    robiw
    Poziom 26  
    Posty: 2032
    Pomógł: 25
    Ocena: 133
    Witam,
    Poszliśmy zupełnie ślepą uliczką :-). Problemem nie były timingi...tylko fakt, iż w procedurze RxChar nie sprawdzamy ile faktycznie przyszło paczek danych (a przychodziło nawet do pięciu) tylko odczytywaliśmy zawsze jedną paczkę i aktualizowaliśmy jeden suwak. Uwzględnienie liczby paczek i obsłużenie ich w procedurze RxChar za jednym razem rozwiązało wszelkie problemy. Oto poniższy, przykładowy kod:
    
    procedure TForm1.ComPort1RxChar(Sender: TObject; Count: Integer);
    var znak, ilosc, i : byte;
    begin
     ilosc:=count div 2;
     for i:=1 to ilosc do
      begin
       comport1.Read(znak,1);
       if znak>127 then begin
         dana[1]:=znak;
         comport1.Read(znak,1);
         dana[2]:=znak;
         memo1.Text:=memo1.text+','+inttostr(dana[1])+','+inttostr(dana[2])+']'+#13#10;
       end;
      end;
    end;
    


    Tak to jest, jak nie zauważy się oczywistej oczywistości jak mawiał nasz były (na szczęście) prime minister ;-)...pozdrawiam... robiw

Podsumowanie tematu

LABEL_AI_GENERATED
Dyskusja dotyczy problemu odbioru dwubajtowych paczek danych z portu RS232 przy niskiej prędkości transmisji 600 b/s w środowisku Delphi, gdzie pierwszy bajt paczki jest zawsze większy niż 127, a drugi mieści się w zakresie 0..47. Problem polegał na niepełnym odbiorze danych w zdarzeniu RxChar, które wywoływało się przy nadejściu pojedynczego bajtu, co powodowało, że nie wszystkie paczki były odczytywane i przetwarzane na bieżąco. Rozwiązaniem okazało się uwzględnienie w procedurze RxChar liczby bajtów (parametr Count) i odczytanie wszystkich dostępnych paczek danych w jednej obsłudze zdarzenia, zamiast tylko jednej paczki na wywołanie. Zaproponowano także stosowanie bufora i ewentualne czyszczenie go, a także zwrócono uwagę na prawidłowe podłączenie kabla RS232 (z przeplotką RX-TX) oraz wyłączenie sygnałów RTS i DTR. Wskazano, że opóźnienia między paczkami (np. 100 ms) mogą pomóc w stabilnym odbiorze, ale kluczowe jest właściwe zarządzanie buforem i odczytem wszystkich dostępnych danych w zdarzeniu RxChar. Przykładowy kod pokazuje pętlę odczytującą wszystkie paczki (Count div 2) i aktualizującą kontrolki na formularzu zgodnie z odebranymi danymi.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA