Konwersja zmiennych integer na char/byte

Konwersja zmiennych integer na char/byte

Często zdarza się, że przez problemy z prostymi czynnościami nasze projekty zatrzymują się w miejscu na bardzo długo.

W moim przypadku dzieje się tak zazwyczaj na etapie programowania mikrokontrolera. Dlatego postanowiłem rozpocząć serię krótkich wpisów z opisami częstych problemów początkujących.

Problem konwersji zmiennych

Pisząc programy na mikrokontrolery, w celu optymalizacji programu, decydujemy się na używanie zmiennych różnego typu. Przeważnie informacje zapisywane są na 1 lub 2 bajtach. Problem pojawia się najczęściej podczas komunikacji układu z otoczeniem.

Transmisja danych przeważnie odbywa się pojedynczymi bajtami. Jest to wymuszone przez stosowany format ramki danych lub sam interfejs komunikacyjny.

Przesyłanie jednego bajta danych nie stanowi problemu, kopiujemy go do rejestru nadawczego i wysyłamy. Co w przypadku, gdy nasza zmienna zapisana jest na 2 bajtach? Wtedy konieczne jest podzielenie zmiennej na młodszy i starszy bajt.

Poniższy obrazek ilustruje podział liczby 5357 zapisanej binarnie na młodszy (L) i starszy (H) bajt:

binarnie5357

Przykład praktyczny

Zmienne składające się z dwóch bajtów często używane są, gdy konieczne jest przesyłanie liczb ujemnych lub oczywiście, dużych wartości dodatnich. Programując moje LineFollowery musiałem przesyłać zmienne składające się z dwóch bajtów informujące o:

  • aktualnych odczytach z enkoderów
  • wartościach członów regulatora PD
  • wartościach ADC podczas odczytu czujników

Rozwiązanie

Jeśli z konwersji korzystamy często najlepiej stworzyć dwie funkcje. Pierwsza z nich będzie dzieliła zmienną na dwa bajty, natomiast druga robiła operację odwrotną.

Na początek zajmijmy się funkcją dzielącą. Oczywiście całość można mocno skomplikować, ale skuteczne rozwiązanie wymaga od nas jedynie kilku linijek oraz znajomości logiki. Najwygodniejsza funkcja jaką możemy stworzyć pobiera liczbę składającą się z dwóch bajtów jako argument, a następnie zwraca wybrany bajt.

Szkielet funkcji:

Pora na najważniejszą operację: podział zmiennej. Najłatwiej wyciągnąć starszy bajt. Do tego wystarczy przesunięcie bitowe o 8 w prawo. Każde przesunięcie w prawo dodaje nam zero z przodu liczby binarnej oraz "kasuje" najmłodszy bit. Jeśli operację wykonamy 8 razy, z liczby

0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 1

otrzymamy:

0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0

Pamiętajmy, że zera z przodu nic nie znaczą, więc tak naprawdę otrzymaliśmy liczbę 8 bitową:

0 0 0 1 0 1 0 0

Wyciągnięcie młodszego bajtu wymaga trochę sprytu. Początkującym może wydawać się, że odpowiednią operacją będzie przesunięcia w lewo, sprawdźmy!

0 0 0 1 0 1 0 0 1 1 1 0 1 1 0 1

Po przesunięciu:

1 1 1 0 1 1 0 1 0 0 0 0 0 0 0 0 

Aby wyciągnąć młodszy bajt konieczny jest iloczyn logiczny. Dla przypomnienia funkcja ta zwraca prawdę (jeden), jeśli na wszystkich porównywanych bajtach znajdzie się 1. W naszym przykładzie:

0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1
0 0 0 1 0 1 0 0
1 1 1 0 1 1 0 1
---------------------------------------
&                    1 1 1 0 1 1 0 1

Dokładnie o to nam chodziło! Teraz dla wygody, zamieniamy 8 jedynek na postać binarną 0xFF:

W ten sposób otrzymaliśmy gotową funkcję, która zwróci wybrany przez nas bajt. Funkcja wykonująca połączenie dwóch zmiennych w jedną jest prostsza i na dobrą sprawę wykonuję, to co powyższa, ale w odwrotnej kolejności:

Przykład w moim programie widoczny jest poniżej. Wysłanie wzmocnienia członu P do kontrolera:

Odebranie danych odesłanych przez kontroler:

Podsumowanie

Mam nadzieję, że rozwiązanie opisałem w sposób zrozumiały nawet dla początkujących. Zasada działania jest identyczna dla dowolnego języka programowania. Jeśli uważasz, że znasz lepszy sposób na rozwiązanie tego problemu - opisz go w komentarzu!

binarny, młodszy, starszy, system

Trwa ładowanie komentarzy...