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

Feedback kontrolny - wykrywanie kolizji na rs485

misiakufal 10 Lis 2010 21:20 2136 2
REKLAMA
  • #1 8727337
    misiakufal
    Poziom 10  
    Witam!

    Usilnie próbuje opracowąć protokół komunikacji miedzy wieloma węzłami w sieci RS485 multimaster. Węzły zbudowane są za pomocą AtMega8. Ramka wyglada tak:

    1 bajt - długosć ramki
    2 bajty - adres odbiorcy (word)
    2 bajty - adres nadawcy (word)
    x bajtów - dane właściwie
    1 bajt suma kontrolna z wszystkich poprzednich

    Transmisja odbywa się na prędkosci 19200bps przy użyciu transcieverów MAX1483. Uporałem się z przypadkiem, gdy jeden z węzłów chce nadawać w momencie, gdy inny już nadaje, poprzez sprawdzanie ile czasu minęło od odebrania poprzedniego bajtu. Jeśli ten czas jest wystarczajaco duży, to uC uznaje ze linia jest wolna i nadaje, a jak nie, to kręci się w kółko aż ustalony czas minie.
    Teraz męczę się z przypadkiem, gdy obydwa węzły miałyby ochotę nadawac w tym samym czasie. Wpadłem na pomysł, żeby automatycznie po wysłaniu wiadomości, odczytywać kolejne bajty tej wiadomosci. Coś na zasadzie feedbacku, sprzężenia zwrotnego, bo przecież wszystko co się pojawia na magistali może byc od razu odebrane przez wszystkie wężły - jak i przez węzeł nadający właśnie w celu sprawdzenia, czy to co miało zostać wysłane, zostało odebrane (a nie że przypadkiem 2 ramki się nałożyły na siebie).

    Jeśli chodzi o kod, to fragment odbioru danych (wykonywany po przerwaniu Urxc):

     
    Port:
    Buff = Inkey()     'odczytanie bajtu
     Bit_order_count = 0
     If Pind.3 = 0 Then     'jeśli nie nadajemy (obca wiadomosć)
      Verif = Verif + Buff     'Zliczamy sume kontrolną
      Tbuff(index) = Buff     'wpisujemy dany bajt do tablicy
      If Index = 1 Then    'Jeżeli jest to pierwszy bajt w ramce
       Leng = Buff    'Ustawiami długośc ramki
       Isbusy = 1     'Flaga zajętości linii (nie możemy w tym momencie niczego wysłać)
      End If
      If Leng = Index Then    'jeżeli została osiągnieta długosć ramki
       Isbusy = 0    ' flaga zajętosci - można już nadawać jeśli trzeba
       Verif = Verif - Buff    ' usuwamy z sumy kontrolnej sume kontrolną (ostatni bajt któwy w tą sumę nie wchodzi
       If Verif = Buff Then     'jezeli suma kontrolna zgadza się z ostatnim bajtem
        Sendid = Tbuff(2);   ' składanie adresu odbiorcy z 2 bajtów do zmiennej word
        Shift Sendid , Left , 8
        Sendid = Sendid + Tbuff(3)
         If Sendid = Id Then Isramkaok = 1    ' Jeżeli id odbiorcy zgadza się z ID urządzenia, ustaw flagę, że ramka jest ok.
       End If
      Index = 1    ' przygotowanie do odbioru następnej ramki
      Verif = 0
      Else
       Incr Index    'jeżeli nie została osiągnieta długosc ramki, zwiększaj index
      End If
     Else     ' jeżeli nadajnik włączony = to nasza wiadomosć, i musimy sprawdzić czy się zgadza z tym co nadajemy
      Thelp(erro) = Buff
      Incr Erro
     End If
    Return
    



    Natomiast to jest fragment odpowiedzialny na wysyłanie:

    
    Portd.3 = 1   'włączenie nadajnika
     Dlug = Dlug + 5   'dodanie do długosci danych długosci narzutu (id odb, id nad, suma)
     Tbuffout(dlug + 1) = 0   ' czyszczenie sumy kontrolnej
     Tbuffout(1) = Dlug + 1   ' ustawienie końcowej dlugosci ramki
     Tbuffout(2) = High(adres)  'konwersja word do bajtów ramki
     Tbuffout(3) = Low(adres)
     Tbuffout(4) = High(id)
     Tbuffout(5) = Low(id)
     For I = 1 To Dlug   ' generowanie sumy kontrolnej
      Tbuffout(dlug + 1) = Tbuffout(dlug + 1) + Tbuffout(i)
     Next I
     Incr Dlug
     Erro = 0
     For I = 1 To Dlug   ' wysyłanie kolejnych bajtów wiadomosci
      Print Chr(tbuffout(i));
     Next I
      Waitms 1
    For I = 1 To Dlug    ' wysyłanie feedbacku (tego co sami odczytaliśmy z wiadomosci którą wysyłaliśmy)
     Print Chr(thelp(1));
    Next I
    Waitms 1
    Portd.3 = 0  ' wyłączenie nadajnika
    Verif = 0
    


    Pod PORTD.3 podpięte jest wejscie uaktywniajace nadajnik w MAX'ie.
    Pod każde inne wyjście występujące w kodzie podpięte są diody.

    Ramka która jest wysyłana z urządzenia na komputerze jest odbierana w postaci:

    9 - Długośc ramki
    234 - Pierwszy bajt Odbiorcy (60000)
    96 - Drugi bajt Odbiorcy (60000)
    0 - Pierwszy bajt Nadawcy (1)
    1 - Drugi bajt Nadawcy (1)
    8 - Dane
    0 - Dane
    1 - Dane
    93 - Suma kontrolna (Suma wszystkich poprzednich mod 256)

    Natomiast sam węzeł widzi odebrane przez siebie dane w postaci:

    234
    234
    234
    234
    234
    234
    234
    234
    234

    Czy ktos ma jakiś pomysł co może powodowac takie zachowanie? Czy bascom/MAX1483/mega8 mają jakieś problemy z nadawaniem i równoczesnym odbieraniu danych w tym samym momencie? Z góry dzięki za pomoc:)

    PS. Wcześniej dałem ten wątek do Milkrokontrolery AVR, ale właściwie to nie jest problem z uC, tylko z transmisją danych, dlatego wrzucam to tutaj...

    Do moderatorów. Proszę o nie usuwanie na razie żadnego z wątków. Po uzyskaniu właściwiej odpowiedzi będzie można usunąć mniej konstruktywny wątek.
  • REKLAMA
  • #2 8735281
    pidorek
    Poziom 15  
    Witam

    Kiedyś działałem z tym samym tematem jak dobrze wszystko rozumiem. Nadawałem z procka i sprawdzałem czy to samo do mnie wraca. Korzystałem jak dobrze pamiętam z ST485 (producent STmicro). Niestety sprawa wyglądała tak, że w pół duplexie kiedy scalak nadaje, to nie odbiera tego co jest na magistari, co jest przecież logiczne skoro calak ustawiony jest w danym momencie na nadawanie.
  • #3 8745598
    arturt134
    Poziom 27  
    Twoje rozumowanie jest ja najbardziej słuszne. Procek powinien odbierać to co nadaje. Mam tylko jedną uwagę: zdajesz sobie sprawę oczywiście, że musisz mieć odblokowany nadajnik i odbiornik w MAX1483?
    Jeżeli tak jest, to masz coś pomieszane w kodzie. Tu może Ci pomóc ktoś, kto zna się na BASCOM-ie, bo ja niestety nie.
REKLAMA