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.

[Delphi] Comport i czytanie bajtów - proszę?

robiw 30 Maj 2008 14:05 4952 28
  • #1 30 Maj 2008 14:05
    robiw
    Poziom 26  

    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

    0 28
  • #2 30 Maj 2008 15:34
    JStan
    Poziom 16  

    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!!

    0
  • #3 30 Maj 2008 17:18
    robiw
    Poziom 26  

    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

    0
  • #5 30 Maj 2008 19:24
    190175
    Użytkownik usunął konto  
  • #6 30 Maj 2008 19:31
    robiw
    Poziom 26  

    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

    0
  • #7 30 Maj 2008 19:45
    190175
    Użytkownik usunął konto  
  • #8 30 Maj 2008 19:57
    robiw
    Poziom 26  

    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

    0
  • #9 30 Maj 2008 20:00
    190175
    Użytkownik usunął konto  
  • #10 30 Maj 2008 20:02
    robiw
    Poziom 26  

    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

    0
  • #11 30 Maj 2008 20:10
    190175
    Użytkownik usunął konto  
  • #12 31 Maj 2008 17:03
    robiw
    Poziom 26  

    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

    0
  • #13 01 Cze 2008 09:39
    robiw
    Poziom 26  

    Kurczę, sam już nie wiem jak obsługiwać ten bufor aby czytać wszystko co przyszło? Może jakiś pomysł? robiw

    0
  • #14 01 Cze 2008 11:33
    190175
    Użytkownik usunął konto  
  • #15 01 Cze 2008 12:07
    robiw
    Poziom 26  

    Odbieram ale część pozostaje w buforze do czasu następnego zdarzenia rxchar...robiw

    0
  • #16 01 Cze 2008 12:56
    190175
    Użytkownik usunął konto  
  • #17 01 Cze 2008 14:28
    robiw
    Poziom 26  

    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

    0
  • #18 01 Cze 2008 15:48
    190175
    Użytkownik usunął konto  
  • #19 01 Cze 2008 17:48
    robiw
    Poziom 26  

    Dokładnie kodu nie pamiętam ale nie ma tam nic szczególnego. Coś takiego (proszę pominąć błędy w składni ;-) ):

    Code:

    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

    0
  • #20 01 Cze 2008 18:14
    190175
    Użytkownik usunął konto  
  • #21 01 Cze 2008 18:33
    robiw
    Poziom 26  

    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

    0
  • #22 01 Cze 2008 19:00
    190175
    Użytkownik usunął konto  
  • #23 01 Cze 2008 21:01
    robiw
    Poziom 26  

    Nic nie może zostać pominięte - nie tędy droga :cry:...robiw

    0
  • #24 01 Cze 2008 21:05
    190175
    Użytkownik usunął konto  
  • #25 01 Cze 2008 21:59
    robiw
    Poziom 26  

    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

    0
  • #26 01 Cze 2008 22:11
    190175
    Użytkownik usunął konto  
  • #27 01 Cze 2008 23:07
    robiw
    Poziom 26  

    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

    0
  • Pomocny post
    #28 01 Cze 2008 23:20
    190175
    Użytkownik usunął konto  
  • #29 02 Cze 2008 09:07
    robiw
    Poziom 26  

    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:

    Code:

    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

    0