Elektroda.pl
Elektroda.pl
X
Serwerowe OpowieściSerwerowe Opowieści
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[stm32]Modbus i CRC16. Czujnik nie odpowiada.

31 Maj 2012 00:47 5449 13
  • Poziom 27  
    Musze połączyć się z czujnikami pracującymi na magistrali Modbus.
    Ponieważ mam z tym problemy, ominąłem magistralę 485 i połączyłem bezpośrednio USARTy obu urządzeń. Niestety, czujnik nie odpowiada. Wysyłam mu jako pytanie jego nr, kod odczytu rejestrów (0x03), dwa bajty adresu pocz. (00,00,) itd. Na końcu wysyłana jest suma kontrolna, też dwa bajty. W opisie Modbusa znalazłem opis obliczania sumy CRC, wg której zrobiłem funkcję wyliczającą ją. Dla jednego bajtu wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    dla nastepnych bajtów powtarza się procedurę, podstawiając odpowiednio bajt2, bajt3 itd... Nie wiem czy funkcja jest dobra, czujniki nie odpowiadają. Jeżeli ktoś robił cos z Modbusem może wie jak zrobić odpowiednią funkcję, lub może ta powyżej jest z jakimś błedem?

    Dodano po 15 [minuty]:

    Dla mnie procedura jest trochę bez sansu, bo traci się informacje o wartosci najmłodszego bitu danych - najpierw przesuniecie w prawo, potem sprawdzanie. Opis wygląda tak (i może coś źle rozumię):

    1) załadowanie wartości FFFFh do 16-bitowego rejestru;
    2) pobranie bajtu z bloku danych (zabezpieczana wiadomość) i wykonanie operacji EXOR
    z młodszym bajtem rejestru, umieszczenie rezultatu w rejestrze;
    3) przesunięcie zawartości rejestru w prawo o jeden bit połączone z wpisaniem 0 na
    najbardziej znaczący bit (MSB=0);
    4) sprawdzenie stanu najmłodszego bitu (LSB) w rejestrze, jeżeli jego stan równa się 0, to
    następuje powrót do kroku 3 (kolejne przesunięcie) , jeżeli 1, to wykonywana jest operacja EXOR rejestru ze stałą A00lh;
    5) powtórzenie kroków 3 i 4 osiem razy, co odpowiada przetworzeniu całego bajtu;
    6) powtórzenie sekwencji 2, 3, 4, 5 dla kolejnego bajtu wiadomości, kontynuacja tego
    procesu aż do przetworzenia wszystkich bajtów wiadomości;
    7) zawartość rejestru po wykonaniu wymienionych operacji jest poszukiwaną wartością
    CRC.
  • Serwerowe OpowieściSerwerowe Opowieści
  • Użytkownik usunął konto  
  • Pomocny post
    Poziom 19  
    W stosie, który wykopałem ze źródeł mam:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jak co to sobie porównaj ;]
  • Serwerowe OpowieściSerwerowe Opowieści
  • Poziom 27  
    nibbit - mój kompilator zbuntował się na takie rzeczy;) Zmieniałem tak i chyba zrobiłem to ok?

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Ale nie wiem jak tego użyć - jak otrzymać sume CRC z kilku bajtów, nie z jednego?

    Dodano po 2 [minuty]:

    markosik20 = dziekuję, sprawdzę czy zadziała:)
  • Poziom 19  
    Kod: c
    Zaloguj się, aby zobaczyć kod


    To jest już do całej ramki korzystając z wcześniejszego kodu. Aczkolwiek równie dobrze możesz użyć ten wcześniejszy kod markosika. Wtedy nie będziesz musiał liczyć tej tablicy tylko podstawiać odrazu.

    A co do typów, jestem zdecydowanym zwolennikiem standardowych czyli uintXX_t intXX_t
  • Poziom 12  
    Witam

    W przypadku pracy z MODBUSem gdy są problemy z połączeniem proponuję skorzystać z jakiegoś gotowego programu do komunikacji i sprawdzić czy on się połączy z slavem.
    Programów jest pewno sporo, ja mogę zaproponować Modbus tester z strony http://polish.modbus.pl/node/5
    swojego czasu sporo z niego korzystałem. Ma możliwość podglądnięcia transmisji wychodzącej i przychodzącej.

    Pozdrawiam
  • Pomocny post
    Specjalista - Mikrokontrolery
    Ta wersja chyba nie powinna ci sprawić problemów?

    Kod: c
    Zaloguj się, aby zobaczyć kod
  • Poziom 27  
    Wielkie dzięki wszystkim za pomoc:) Na razie podglądnąłem transmisję i wpisałem CRC na stałe, bo inne bajty tez się nie zmieniają, transmisja zaskoczyła, choć nie jest zbyt stabilna, tu musze jeszcze powalczyć. Potem dołaczę funkcję rzeczywistego obliczania CRC, bedę miał łatwiej, bo już wiem ile powinna wyjść dla tego konkretnego przypadku.
  • Poziom 27  
    Zapytam tu o inną jeszcze sprawę, bo nie chcę dla tego drobiazgu zakładać nowego tematu. Muszę ustawić timeout ramki, jezeli po odpowiednim czasie odbiornik nie odpowie, to transmisja zostaje przerwana z flagą błędu. Chcę do tego użyć timera, np.TIM4. Uruchomiony bedzie w najprostszej konfiguracji zwykłego licznika, ładowanego przed rozpoczeciem transmisji. Będzie np. odliczał w dół, potrzebna mi jest flaga uzyskania przez licznik 0 (underflow). Czytając o rejestrach liczników, jedyną taką flagą (którą znalazłem), jest TIMx_SR_UIF, czyli UpdateInterruptFlag. Co prawda nie będę włączał przerwania, ale jest to chyba jedyna flaga którą mogę w tym celu wykorzystać, czy też jest jakaś inna lepsza do tego celu?
  • Pomocny post
    Specjalista - Mikrokontrolery
    dziechu napisał:
    Czytając o rejestrach liczników, jedyną taką flagą (którą znalazłem), jest TIMx_SR_UIF, czyli UpdateInterruptFlag. Co prawda nie będę włączał przerwania, ale jest to chyba jedyna flaga którą mogę w tym celu wykorzystać, czy też jest jakaś inna lepsza do tego celu?

    To jest właśnie flaga która jest Ci potrzebna.

    4\/3!!
  • Poziom 27  
    Dziękuję za potwierdzenie:)

    Dodano po 3 [godziny] 3 [minuty]:

    Mam jeszcze takie pytanie - w ramach jednej funkcji, instrukcje warunkowe typu if () nie modyfikują stosu? Chodzi mi konkretnie o cos takiego:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Nie powinno być problemu ze stosem przy takim wyjściu z ifa?

    Dodano po 3 [godziny] 46 [minuty]:

    pewnie nie, w asm będą to jakieś krótkie skoki warunkowe...
    Bardzo lubię w C rozkaz goto, łacznie z if skok warunkowy, główna atrakcja z asm:)

    Dodano po 6 [minuty]:

    Ok, Modbus chodzi, CRC16 liczy prawidłowo, timeout też działa, w zasadzie program bliski końca, i tak 90% programu to bajery ekranowe, kolorowy TFT+dotyk wymaga głównie bajerów, Photoshop jest tu koniecznym narzędziem programisty ;)

    Dodano po 4 [minuty]:

    Do obliczania CRC16 skorzytałem z funkcji Michalko12, krótka i działa ok, podobna do tej którą pokazałem na poczatku i oparłem o niepoprawny opis.

    Dodano po 6 [minuty]:

    Choć jak tak sie przygladam, to jakby to samo (tylko moja dla jednego bajtu, trzeba by dodać pętlę ilosci bajtów).... bo to crc>>1; wykonywane jest bez względu na wartość if, więc mozna je wyrzucić poza if do góry i będzie jak moje...