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.

[Rozwiązano] [AVR][C] Szybka konwersja liczby 16-bit hex na dec

Adrian1978 13 Lis 2017 12:28 1125 18
  • #1 13 Lis 2017 12:28
    Adrian1978
    Poziom 10  

    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
    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
    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
    Zaloguj się, aby zobaczyć kod


    Próbowałem również:
    Kod: 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 !

    0 18
  • #3 13 Lis 2017 12:47
    Adrian1978
    Poziom 10  

    jako tablica char:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #5 13 Lis 2017 12:57
    Marek_Skalski
    Moderator Projektowanie

    Adrian1978 napisał:
    Odbieram dane 2 bajty z modułu pomiarowego ...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
    Zaloguj się, aby zobaczyć kod

    Jeżeli dobrze kombinuję to teraz w liczniku mam liczbę 16bit odebraną z UARTA...

    Nie bardzo, ponieważ to co odebrałeś zapisałeś jako:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Pierwszy element w tablicy to pierwszy bajt, czyli bardziej znaczący.
    Drugi element w tablicy to drugi bajt, czyli mniej znaczący.
    A składając bajty, przesuwasz mniej znaczący na miejsce bardziej znaczącego. Dlatego widzisz dziwne wartości. Liczba to liczba, nie ma tu czegoś takiego jak reprezentacja heksadecymalna. Tak by było, gdybyś tę liczbę rozbił na 4 bajty, z których każdy jest znakiem ASCII.

    0
  • Pomocny post
    #6 13 Lis 2017 13:05
    Pokrentz
    Poziom 21  

    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
    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
    Zaloguj się, aby zobaczyć kod

    0
  • #7 13 Lis 2017 13:06
    Adrian1978
    Poziom 10  

    Kolega tos18 - Rewelacja ! Działa pięknie , bardzo Ci dziękuję - serdecznie pozdrawiam :)

    0
  • #8 13 Lis 2017 13:10
    22053
    Użytkownik usunął konto  
  • #9 13 Lis 2017 13:36
    2675900
    Użytkownik usunął konto  
  • #11 13 Lis 2017 16:30
    BlueDraco
    Specjalista - Mikrokontrolery

    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.

    1
  • #12 13 Lis 2017 16:58
    2675900
    Użytkownik usunął konto  
  • #13 13 Lis 2017 17:09
    grko
    Poziom 33  

    Piotrus_999 napisał:
    @BlueDraco No to bardziej uniwersalnie
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Przecież ten Twój kod to kompletne banialuki.

    Choćby tutaj:
    Kod: 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.

    0
  • #14 13 Lis 2017 18:01
    2675900
    Użytkownik usunął konto  
  • #15 13 Lis 2017 20:30
    Adrian1978
    Poziom 10  

    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.

    0
  • #16 13 Lis 2017 20:36
    2675900
    Użytkownik usunął konto  
  • #17 13 Lis 2017 20:45
    Adrian1978
    Poziom 10  

    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.

    0
  • Pomocny post
    #18 13 Lis 2017 23:09
    excray
    Poziom 39  

    Adrian1978 napisał:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    To jest źle. Powinno być:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #19 31 Sty 2018 14:52
    Adrian1978
    Poziom 10  

    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 !

    0