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

Jak odebrać bajty 1..32 i 126..255 z RS232 - BASCOM

TomekMus 16 Lis 2009 13:45 2130 6
REKLAMA
  • #1 7268019
    TomekMus
    Poziom 17  
    Witam,

    Jak sprawnie odebrać dane bajty lub znak ascii z przedziałów:
    - 1..32
    - 126..255

    Gdyż program sprawuje się rewelacyjnie i NIEZAWODNIE jak odbieram tylko znaki z klawiatury, a ja chcę przesłać z PC do uC ok 1MB danych z zakresu Bajt = 1..255

    Rozwiązanie jakie jest poniżej - rewelacja! Lecz moja ramka danych jest 128bajtowa i docelowo 128bajt jak jest znamiek Bytematch powinien uzupełnić zmienną Linia, lecz jak w czasie wysyłania danych pojawia się w środku chociasz jeden znak #13 to automatycznie kończy odbiór danych i wyświetla zmienną Linia gdzie jest to błędne w tym przypadku.

    Mam taki programik(sprawdza się tylko jak wysyłam dane 33..125 - znaki z klawiatury):

    'Nie chce stosować tego bo się nie sprawdza jeśli dane są inne niż z zakresu ASCII Char = 33..125
    'Config Serialin = Buffered , Size = 128 , Bytematch = 13
    
    
    Config Serialin = Buffered , Size = 128
    
    Do
      If Getline() > 0 Then
        Print Linia                                             ' w celu kontroli co przyszło z rs232
      End If
    Loop
    
    End
    
    
    Serial0charmatch:                                           'po odebraniu znaku Chr(13) zwiększenie licznika lini(zdarzeń)
    lds r24,{event}
    inc r24
    sts {event},r24
    Return
    
    
    Function Getline()as Byte
    Linia = ""
    If Event > 0 Then
       If _rs_bufcountr0 > 0 Then
         Input Linia , Noecho
         Err = 0
         Getline = Len(linia)
    
         Cli
         Decr Event
         sei
       End If
    End If
    End Function


    Jak ulepszyć kod by bezproblemowo odbierać cały zakres bajta.
    Z góry dziękuję za propozycję.
  • REKLAMA
  • Pomocny post
    #2 7268022
    _Robak_
    Poziom 33  
    Znaczy ze chcesz wklepac w cyfy na klawiaturze np. 125 i zeby program wyslal liczbe 125? Jesli tak to musisz zamienic stringa na uinta8
  • REKLAMA
  • #3 7268052
    TomekMus
    Poziom 17  
    Chcę z Dalphi wysłać np. 1MB danych w ramkach po 128Bajtów,
    Działa mi to, jeśli nie wystąpi wcześniej niż na końcu ramki znak #13.

    A wysyłając dane czyli bajty wiadomo, że gdzieś w środku ramki pojawi się znak #13.
    Jak zmienię Bytematch na inny znak, to i tak nie da, nic bo jak wystąpi znak, zdefiniowany w Bytematch, prędzej w ramce automatycznie będzie interpretowany jako zakończenie ramki.
  • REKLAMA
  • Pomocny post
    #4 7268194
    _Robak_
    Poziom 33  
    No to mi przychodzi do glowy taki pomysl. Z gory zakladasz ze wysylasz po 128 bajtow, jesli odbiorca odebral np 127 bajtow to czekasz jakis czas, jesli minie (np 10ms) i nie odebrales wszystkiego, wysylasz cala paczke ponownie, badz tez wymyslasz jakis algorytm dosylu tylko brakujacego bajtu :) Sposob z bajtem startu i stopu, w przypadku gdy wysylasz losowe znaki, jest raczej kiepski :)
  • Pomocny post
    #5 7268376
    mirekk36
    Poziom 42  
    Skoro chesz przesyłać dane czyste dane binarne to chyba zrozumiałe, że odpada ci konstrikcja Bytematch z zastosowaniem dowolnego bajtu, który byłby końcem jakiejś tam ramki

    w związku z tym musisz je albo:

    1. wysyłać czysto binarnie z kompa a w procku po prostu czekać na zakończenie transmisji - wprowadzając jakiś TimeOUT (ale to czasami mało eleganckie rozwiązanie)

    2. skonstruować swój własny typ ramki do przesyłania danych ale ramki a nie ciągu jakichś znaków. Bo ty nazwałeś sobie ramką danych - dane binarne kończące się znakem ENTER. Jak sam widzisz to jest bez sensu. A więc, ramka to znaczy jakiś pakiet danych o stałej długości, który zaczyna się jakąś ustaloną przez ciebie sekwencją kilku bajtów (aby można było tą sekwencję rozpoznać w procku jako FRAME_START, po tej sekwencji warto wrzucić sobie jakąś sumę kontrolną i to dobrą całej ramki danych - jakieś CRC - aby można było w razie czego odrzucić błędną ramkę (BAD_FRAME) , a następnie taka ramka może kończyć się jakimś znowu jednym lub kilkoma batami, które będą oznaczały jej koniec FRAME_END

    dzięki takiemu podejściu zaczynasz odbierać ramkę jeśli jako pierwsze znaki wpadają ci bajty FRAME_START, jeśli nie to czekasz na nie spokojnie przepuszczając wszystkie inne, które lecą sobie w "kosmos"

    po odebraniu FRAME_START odbierasz swoje CRC, następnie - część FRAME_DATA oraz na końcu FRAME END. Jeśli odbiór takiej ramki zakończył się prawidłowo tzn sprawdziłeś jeszcze czy CRC odebranej ramki się zgadza - to robisz z częścią FRAME_DATA co tam sobie potrzebujesz i - zabierasz się za odbieranie kolejnej ramki itd itd itd

    oczywiście jak sam widzisz można sobie taką ramkę zmodyfikować tak aby np jej długość mogła zmieniać się dynamicznie, wystarczy, że np po CRC prześlesz jeszcze długość w bajtach części FRAME_DATA i wtedy odbierzesz tyle właśnie bajtów jako FRAME_DATA po czym musi nastąpić FRAME_END

    Oczywistym jest też to, że przy takim sposobie warto sobie jeszcze wprowadzić ew jakąś kontrolę błedów tzn błędnych ramek i system potwierdzeń odbioru, gotowości itp ;)

    jednym słowem wtedy można sobie kombinować do woli i na różne sposoby. A to powyżej to tylko taki zarys przykład - jak można podchodzić do tematu tworzenia własnych ramek - i żebyś zobaczył, że to nie jest nic takiego skomplikowanego ;)
  • REKLAMA
  • #6 7271078
    TomekMus
    Poziom 17  
    Wszystko co napisałeś się zgadza, ja widze ramkę następująco:

    |START|CRC16|CRC16|ILE_BAJT|......|KONIEC|

    tylko mam jeden probelm z którym moje doświadczenie nie może sobie poradzić a mianowicie jakich finkcji użyć w Bascom'ie - tak by prawdopodobieństwo odbioru błędnej ramki "coś uleci w kosmos" zminimalizować do jak najmniejszego liczby.
  • Pomocny post
    #7 7271114
    xury
    Specjalista automatyka domowa
    Po prostu nie możesz korzystać z instrukcji Input tylko z instrukcji np. Inkey i odbierać 128 bajtów o dowolnej zawartości (nawet bajtów zerowych) Po odebraniu 128 bajtów sprawdzić sumę kontrolną, tak jak pisał kolega mirekk36. Jeśli odebrałeś wysłasz ack spowrotem np. z sumą crc ramki
    Instrukcja Input się nie nadaje do tego celu. Tylko odbieranie za pomocą Inkey, Waitey lub "zmienna=udr" Jeśli w ramce pojawiają się znaki zerowe to trzeba korzystać też z Ischarwaiting.
    Można też ustawić sobie bufor np 128 lub lepiej 256 bajtów i odbierać kiedy naleci nam do niego te 128 bajtów.
    Można tez nie korzystać z buforu Bascomowego tylko utworzyć własny w zmiennej i kopiować do innej kiedy nam się zapelni 128 bajtami. Po odebraniu znaku zwiększać licznik itd. Taki przykład niedawno dyskutowałem z kolegą Mirkiem właśnie.
REKLAMA