Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

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

Adrian1978 13 Lis 2017 12:28 663 17
  • #1 13 Lis 2017 12:28
    Adrian1978
    Poziom 9  

    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 !

  • #2 13 Lis 2017 12:36
    tos18
    Poziom 35  

    Jak deklarujesz dane_RX[] ?

  • #3 13 Lis 2017 12:47
    Adrian1978
    Poziom 9  

    jako tablica char:

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • Pomocny post
    #4 13 Lis 2017 12:52
    tos18
    Poziom 35  

    Więc spróbuj tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #5 13 Lis 2017 12:57
    Marek_Skalski
    Poziom 33  

    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.

  • #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

  • #7 13 Lis 2017 13:06
    Adrian1978
    Poziom 9  

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

  • #8 13 Lis 2017 13:10
    R-MIK
    Poziom 38  

    Zła nazwa tematu, chciał juz dac kod do konwersji na BCD.

  • #9 13 Lis 2017 13:36
    Piotrus_999
    Poziom 40  

    Albo po prostu type punning na uniach

    Kod: c
    Zaloguj się, aby zobaczyć kod


    i wtedy w zależnosci od endianes:
    little endian

    Kod: c
    Zaloguj się, aby zobaczyć kod


    big endian
    Kod: c
    Zaloguj się, aby zobaczyć kod


    a dana będzie dostępna jako

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #10 13 Lis 2017 13:53
    tos18
    Poziom 35  

    Adrian1978 napisał:
    Rewelacja ! Działa pięknie

    Czy rozumiesz gdzie był błąd ?

  • #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.

  • #13 13 Lis 2017 17:09
    grko
    Poziom 32  

    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.

  • #15 13 Lis 2017 20:30
    Adrian1978
    Poziom 9  

    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 13 Lis 2017 20:36
    Piotrus_999
    Poziom 40  

    @Adrian1978 Posłuchaj @BlueDraco bo tak jak to robisz jest bardzo źle. Chociaż sprawdzaj w pętli kiedy coś się pojawi w rejestrze danych. Akurat tak ja zrobiłeś jest to najgorzej możliwie.

    Poszukaj w dokumentacji flagi która ustawia się jak dane są w rejestrze. Wtedy (i tylko wtedy) je odczytuj. W pierwszym i drugim czytaniu.

  • #17 13 Lis 2017 20:45
    Adrian1978
    Poziom 9  

    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.

  • #18 13 Lis 2017 23:09
    excray
    Poziom 38  

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

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

 
Black Friday do -15%
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME
Ferguson