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

[Rozwiązano] [AVR] Jak przekonwertować 16-bit hex na dec w AVR C dla modułu pomiarowego?

Adrian1978 13 Lis 2017 12:28 2385 18
REKLAMA
  • #1 16820188
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    Witajcie , pomoże ktoś naprowadzić jak najbardziej komfortowo i prosto przekonwertować liczbę 16-bit hex na dec ?

    Odbieram dane 2 bajty z modułu pomiarowego (ultradźwiękowy moduł pomiaru odległości) który wyniki pomiaru wysyła w 2 liczbach :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ponieważ pierwszy bajt to starsza część wyniku (H_DATA) a drugi bajt to część młodsza (L_DATA) to składam to w całość tak :

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jeżeli dobrze kombinuję to teraz w liczniku mam liczbę 16bit odebraną z UARTA ale w reprezentacji heksadecymalnej. Tak jak deklaruje producent modułu pomiarowego.

    No i teraz chcę to obrabiać , przeliczać na metry itp. Także wyświetlić na LED jako wartość milimetrów od przeszkody. Mam procedurę obsługi wyświetlacza LED która wyświetla bardzo ładnie liczbę ze zmiennej na wyświetlacz LED. (0...9999 w zmiennej - i to wyświetli)
    No ale jeżeli próbuję to wyświetlić na LED wprost to mi się bzdury wyświetlają, bo wynik jest w hex (np. odbieram 0x07A1 - z tego co podaje producent trzeba to przekonwertować na wartość dziesiętną (decimal) i powinienem uzyskać po operacji konwersji '1953' (elegancki wynik w milimetrach od przeszkody). Próbowałem na różne sposoby ale wynik nie jest prawidłowy.

    Proszę o wskazówkę jak tego prosto dokonać ?

    Próbowałem :
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Próbowałem również:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Niestety głupoty mi z tego wychodzą bo nie do końca rozumiem jak to działa.

    Podpowie ktoś jak tego szybko dokonać ? Z góry dziękuję za pomoc !
  • REKLAMA
  • Pomocny post
    #2 16820197
    tos18
    Poziom 42  
    Posty: 7023
    Pomógł: 1089
    Ocena: 1811
    Jak deklarujesz dane_RX[] ?
  • #3 16820210
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    jako tablica char:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #4 16820218
    tos18
    Poziom 42  
    Posty: 7023
    Pomógł: 1089
    Ocena: 1811
    Więc spróbuj tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #5 16820224
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • Pomocny post
    #6 16820242
    Pokrentz
    Poziom 22  
    Posty: 546
    Pomógł: 19
    Ocena: 81
    W Twoim przypadku zapisujesz pierwszy (starszy) przychodzący bajt w dane_RX[1] a drugi (młodszy) - w dane_RX[0], bo, jak sam napisałeś, masz dane nadchodzące w big endian a AVR pracuje w little endian, więc musisz odwrócić kolejnośc bajtów w pamięci.
    I teraz możesz sobie przykładać wskaźnik do typu uint16_t tam, gdzie chcesz, czyli do tablicy dane_RX:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W ten sposób użyte w kodzie *p_licznik zwróci Ci odczytaną wartość jako uint16_t. Po prostu, nie w heksie, decymalu, czy czymkolwiek - tej wartości możesz uzywac do obliczeń jak każdego typu całkowitego - bo tym to jest. heksadecymal, decymal, czy cokolwiek - to tylko na poziomie wyświetlania dla uzytkownika, w pamięci masz zawsze reprezentację binarną.

    A nawet można obejśc się bez wskaźnika uzywając operatora rzutowania:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #7 16820245
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    Kolega tos18 - Rewelacja ! Działa pięknie , bardzo Ci dziękuję - serdecznie pozdrawiam :)
  • #8 16820250
    Konto nie istnieje
    Konto nie istnieje  
  • REKLAMA
  • #9 16820282
    Konto nie istnieje
    Konto nie istnieje  
  • Pomocny post
    #10 16820301
    tos18
    Poziom 42  
    Posty: 7023
    Pomógł: 1089
    Ocena: 1811
    Adrian1978 napisał:
    Rewelacja ! Działa pięknie

    Czy rozumiesz gdzie był błąd ?
  • REKLAMA
  • #11 16820531
    BlueDraco
    Specjalista - Mikrokontrolery
    Posty: 6479
    Pomógł: 939
    Ocena: 421
    Ja tu widzę całe mnóstwo błędów, w zadanym pytaniu, w programie oryginalnym z pierwszego postu i w kilku "rozwiązaniach" pokazujących, jak skutecznie zaciemnić kod programu.

    Pytanie powinno brzmieć: jak z dwóch bajtów złożyć liczbę 16-bitową. Biedny procesor nie wie nic ani o reprezentacji szesnastkowej, ani o dziesiętnej.
    Błędny jest odbiór danych: "poczekaj na pierwszy bajt, odbierz go, poczekaj 4 ms i odczytaj drugi bajt, nie sprawdzając, czy nadszedł. Brawo! A może przez te 4 ms przyjdzie 5 kolejnych bajtów?

    Rozwiązanie z unią jest oczywiście najsympatyczniejsze, pod warunkiem, że nie będziemy przenosić w przyszłości programu na zupełnie inną platformę z inną kolejnością bajtów.
  • #12 16820577
    Konto nie istnieje
    Konto nie istnieje  
  • #13 16820599
    grko
    Poziom 33  
    Posty: 1386
    Pomógł: 247
    Ocena: 141
    Piotrus_999 napisał:
    @BlueDraco No to bardziej uniwersalnie
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Przecież ten Twój kod to kompletne banialuki.

    Choćby tutaj:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wszystkie 3 symbole: value, LITTLE_ENDIAN_32, BIG_UNDIAN32 podczas preprocessingu są niezdefiniowane i mają wartość 0. Dalej jest nie lepiej. Najwidoczniej preprocesor nie jest dla początkjących.
  • #14 16820714
    Konto nie istnieje
    Konto nie istnieje  
  • #15 16821169
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    BlueDraco napisał:
    poczekaj na pierwszy bajt, odbierz go, poczekaj 4 ms i odczytaj drugi bajt, nie sprawdzając, czy nadszedł. Brawo! A może przez te 4 ms przyjdzie 5 kolejnych bajtów?

    - zrobiłem to naprościej, bo wedle dokumentacji producenta modułu wiadomo co i w jakich odstępach czasu wysyła. Proste i skuteczne. Przy próbie oczekiwania na kolejne dane niestety kolejne bajty (nie wiedzieć czemu) - nie ładowały się do poszczególnych komórek w tablicy poprawnie. A co do pytania czy rozumiem błąd (kolega "tos18") to zaprezentował sposób o jakim ja nie myślałem natomiast to że błędnie przesuwałem liczbę młodszą zamiast starszą - jasna sprawa , to mój błąd.
  • #16 16821195
    Konto nie istnieje
    Konto nie istnieje  
  • #17 16821229
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    Spróbuję, jednak jeżeli dawałem pętlę odbierania kolejnych znaków z modułu - to pierwszy znak był odebrany poprawnie a kolejne już nie (moduł de facto wysyła 4 bajty : bajt startu, 2 bajty wyniku i bajt sumy kontrolnej) - no i jak czekałem na te dane sprawdzając flagę to mi głupoty wskakiwały albo tablica pusta była. Ale sprawdzę - dziękuję raz jeszcze.
  • Pomocny post
    #18 16821618
    excray
    Poziom 41  
    Posty: 5498
    Pomógł: 739
    Ocena: 655
    Adrian1978 napisał:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    To jest źle. Powinno być:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #19 17002551
    Adrian1978
    Poziom 11  
    Posty: 75
    Ocena: 7
    Dziękuję serdecznie za wszelkie sugestie - temat zamykam jako rozwiązany, skończyłem na przesunięciach bitowych, działa szybko, zajmuje mało pamięci i jest proste. Pozdrawiam i raz jeszcze dziękuję za wszelką pomoc !

Podsumowanie tematu

✨ W dyskusji poruszono problem konwersji 16-bitowej liczby w formacie hex na decimal w kontekście odbioru danych z ultradźwiękowego modułu pomiarowego. Użytkownik opisał sposób odbierania danych przez UART, gdzie dane są przesyłane w dwóch bajtach. W odpowiedziach zasugerowano poprawne składanie bajtów, uwzględniając różnice w kolejności bajtów (endianness). Użytkownicy podali różne metody, w tym użycie wskaźników oraz unii, aby uzyskać wartość 16-bitową. Wskazano również na błędy w oryginalnym kodzie, takie jak niewłaściwe oczekiwanie na dane. Ostatecznie użytkownik potwierdził, że zastosowanie przesunięć bitowych okazało się skuteczne i efektywne.
Wygenerowane przez model językowy.
REKLAMA