Mikrokontrolery - Jak zacząć?

... czyli zbiór praktycznej wiedzy dot. mikrokontrolerów.

czwartek, 10 lutego 2011

Kurs języka C: Operator przesuwania bitów w lewo <<


Autor: Dondu

Kurs języka C: Spis treści

Operator przesuwania bitów w lewo << przesuwa bity o zadaną ilość pozycji uzupełniając zerami najmłodsze przesunięte bity. Najstarszy bit "wypada" i jest gubiony. Przesuwać bity można o dowolną ilość pozycji.

Ponieważ podstawą kodu dwójkowego jest liczba dwa, stąd przesunięcie o jeden bit w lewo, jest równoznaczne z mnożeniem przez dwa. Analogicznie przesunięcie o dwa bity jest mnożeniem przez 4, itd. Należy oczywiście uważać, by nie przekroczyć dozwolonego zakresu typu zmiennej.

76543210 numery bitów
--------
00001111 zmienna a
--------
00011110 wynik przesunięcia bitowego w lewo          o 1 pozycję: a = a<<1

Przesuwamy bit o jeden w lewo.

Przykład 1 (w kompilatorze)
  unsigned char a = 0b00001111;
  a = a << 1;  //przesuń bity o jeden w lewo, a na najmłodszy wstaw zero


Bity można przesuwać o dowolną ilość pozycji:

Przykład 2 (w kompilatorze)
  a = a << 4;  //przesuń bity o cztery w lewo, a na najmłodsze wstaw zero


Najstarszy bit jest tracony.

Przykład 3 (w kompilatorze)
  unsigned char a = 0b10000000;
  a = a << 1;  //przesuń w lewo o jeden, tracimy najstarszy bit


Przekroczenie ilości bitów w zmiennej oznaczać będzie, że na wszystkich bitach pojawią się zera.

Przykład 4 (w kompilatorze)
  
  unsigned char a = 0b10000001;
  a = a << 8;  //przesuń w lewo o osiem pozycji, tracimy wszystkie bity  





Łączenie operatorów: <<=

Operator przesunięcia w lewo może być łączony z operatorem przypisania.

Przykład 5 (w kompilatorze)
  a <<= 1;  //równoznaczny z: a = a << 1;






Rolowanie bitów w lewo

Rolowanie w lewo, to przesuwanie w lewo z jednoczesnym przenoszeniem wypadającego bitu na najmłodszy bit. Niestety język C, to nie assembler i nie posiada operatorów rolowania w lewo. Należy posłużyć się dodatkowym kodem. Poniżej kilka przykładów dla zmiennych typu char.


1. rolowanie w postaci funkcji z użyciem if( ):

Przykład 6 (w kompilatorze)
//funkcja rolująca bity w lewo
unsigned char dd_rol( unsigned char a ) 
{ 
  //sprawdzamy najstarszy bit (bit tracony przy przesuwaniu w lewo)
  if( a & 0x80  ){ 
    // gdy jest równy jeden 
    return ( (a<<1) | 0x01 ); // trzeba przenieść tracony bit na najmłodszy 
  }
  
  //gdy jest równy zero
  return (a<<1); //tylko przesuwamy, a standardowo na najmłodszym bicie
                 //ląduje zero
} 



2. rolowanie z użyciem definicji z instrukcją wyboru (skrócony if):

Przykład 7 (w kompilatorze)
  //definicja dd_rol()
  #define dd_rol(a) ((a&0x80)? 0x01|(a<<1) : a<<1 ) 

Można oczywiście dwa powyższe przykłady "wymieszać" definiują własną funkcję ze skróconym if( ).



3. Rolowanie z użyciem wstawki kodu assemblera:

Przykład 8 (w kompilatorze)
  //przesuń bity o jeden w lewo, za pomocą wstawki kodu assemblera
  asm volatile ("rol %0" : "=r" (a) : "0" (a));





Składnia kodu

Nie ma znaczenia, czy piszesz ze spacjami, czy bez.
  //dozwolone formy
  a = a << 1;
  a=a<<1;

  a <<= 1;
  a<<=1;

Ale uwaga: Nie może być spacji pomiędzy operatorami!
  //niedozwolone formy
  a << = 1;




Ćwiczenie

Spróbuj zrozumieć poniższy kod zanim uruchomisz go w kompilatorze CManiak.

Przykład 9
(w kompilatorze)
  unsigned char i;
  unsigned char a = 0b00000001;

  for(i = 0; i<9; i++){
        printf("%d \n",  a);
        a<<=1;
  }
Kurs języka C: Spis treści
16
Oceń artykuł.
Wasze opinie są dla nas ważne, gdyż pozwalają dopracować poszczególne artykuły.
Pozdrawiamy, Autorzy
Ten artykuł oceniam na:

4 komentarze:

  1. Nie rozumiem dlaczego w przykładzie z rolowaniem badasz if( a & 0x80 ) ? Z tego co wiem, wynikiem wewnatrz nawiasu może być 0x00 lub 0x80 - tak czy siak nie jest to jedynka (tzn 0x01) -czyli wewnątrz nawiasu wartość a&0x80 zawsze będzie różna od jedynki, a więc cały if będzie dawał zero...?

    OdpowiedzUsuń
    Odpowiedzi
    1. Wynikiem a & 0x80 (czyli koniunkcji) będzie liczba różna od zera (a dokładnie 0x80) tylko wtedy, gdy na najbardziej znaczącym 7 bicie zmiennej a będzie jedynka. W przeciwnym wypadku wyrażenie to będzie równe zero.

      Testowałeś przykład w CManiaku?

      Usuń
    2. Ok, mój błąd wynikał z tego że sądziłem iż tylko if(1) wykonuje komendy wstawione pod "if". Własnie widzę że jeśli pod "if" wyladuje jakakolwiek liczba różna od zera, wtedy komendy też sa wykonywane. Tak czy siak, niepotrzebnie narobiłem wiatru, sorry za zamieszanie i dzięki za szybką odpowiedź :)

      Usuń
  2. witam

    przykład 8 - błąd kompilacji

    Poniżej błędy oraz warning'i według szablonu:
    NR_LINII_PROGRAMU : NUMER_ZNAKU_W_LINII : OPIS

    In function 'main':
    20:3: error: 'asm' undeclared (first use in this function)
    asm volatile ("rol %0" : "=r" (a) : "0" (a));
    ^
    20:3: note: each undeclared identifier is reported only once for each function it appears in
    20:7: error: expected ';' before 'volatile'
    asm volatile ("rol %0" : "=r" (a) : "0" (a));
    ^

    pozdrawiam

    michał

    OdpowiedzUsuń

Działy
Działy dodatkowe
Inne
O blogu




Dzisiaj
--> za darmo!!! <--
1. USBasp
2. microBOARD M8


Napisz artykuł
--> i wygraj nagrodę. <--


Co nowego na blogu?
Śledź naszego Facebook-a



Co nowego na blogu?
Śledź nas na Google+

/* 20140911 Wyłączona prawa kolumna */
  • 00

    dni

  • 00

    godzin

  • :
  • 00

    minut

  • :
  • 00

    sekund

Nie czekaj do ostatniego dnia!
Jakość opisu projektu także jest istotna (pkt 9.2 regulaminu).

Sponsorzy:

Zapamiętaj ten artykuł w moim prywatnym spisie treści.