poniedziałek, 18 stycznia 2016

AVR cz2 - arytmetyka bitowa.



Aby efektywnie oprogramowywać mikrokontrolery AVR kluczową umiejętnością jest umiejętność programowania w języku C ze szczególnym uwzględnieniem operatorów bitowych. Jako pierwsze omówmy przesunięcie bitowe w lewo ( operator << ). Polega to na przesunięciu bitów w bajcie o określoną ilość pozycji, bity z prawej strony uzupełniane są zerami). Na przykład zapis  PORTB<<3 oznacza przesunięcie w lewo bitów portu PORTB o 3 bity.



PORTB               00010101
PORTB<<3        10101000

 Często spotykany zapis w programowaniu AVR to na przykład 1<<PD3. Piny Atmegi oznaczamy jako Pxy - x oznacza port (B,C,D), y - numer pinu(bitu) w porcie (0,1,3,...,7). Co to oznacza? Oznacza to tyle, że zapisana binarnie jedynka zostanie przesunięta to pozycji pinu D3 (3 pozycje w lewo, gdyż bity numerujemy od 0 ). Czyli mamy:

1                  00000001
1<<PD3      00001000

Widać, że przesunięcie bitowe możemy użyć do ustawiania dowolnego bitu w porcie. W języku C może to wyglądać:

PORTD=0x0;  //zerujemy port D
PORTD=1<<PD2; //pin 2 portu D ustawiamy na 1

Niestety łatwo zauważyć, że zastosowanie tej metody nie jest do końca dobre. W razie jej zastosowania tracimy wartość innych bitów (pinów) portu. Czy można temu zaradzić? Okazuje się, że tak. Wystarczy użyć logicznej funkcji OR. Funkcja OR dwóch bajtów w systemie binarnym daje w wyniku same 1 z wyjątkiem gdy alternatywie poddajemy dwa 0 wtedy jej wartość wynosi 0. Na przykład:

BAJT_A                  11011011
BAJT_B                  01100010
BAJT_A|BAJT_B   11111011

Zapis | oznacza OR w języku C. Co nam to daje. Rozważmy przykład.

PORTD                           11100000 /początkowa wartość portu
1<<PD3                          00001000
PORTD|(1<<PD3)          11101000

"Zapaliliśmy" bit3 nie zmieniając wartości innych bitów. Oznacza to, że funkcję OR możemy używać do zapalania bitów. Możemy jednocześnie zapalać kilka bitów. W języku C zapisujemy to jako:

PORTD|=(1<<PD3)|(1<<PD1) //zapalamy bity 3 i 1


Zapis PORTD|=(1<<PD3)|(1<<PD1) oznacza w notacji C: PORTD=PORTD|(1<<PD3)|(1<<PD1).
Skoro istnieje prosty sposób na zapalanie bitów to musi istnieć również metoda ich gaszenia. Aby to osiągnąć musimy rozważyć dwa następne operatory binarne NOT (~) i AND (&). Operator NOT zamienia wartość bitu na przeciwną czyli z 1 na 0 i z 0 na 1. Operator AND dwóch bajtów da wartość 1 tylko wtedy gdy dwa bity będą równe 1, w pozostałych przypadkach da wartość 0. Rozważmy przykład.

PORTD                                 11111011
1<<PD4                                00010000
~(1<<PD4)                            11101111
PORTD &~(1<<PD4)          11101011

Zauważmy, iż został zgaszony tylko bit 4. Zatem nasza metoda działa. Można też gasić bity hurtowo :

PORTD&=~((1<<PD4)|(1<<PD5));

Ostatnią przydatną metodą jest metoda negowania wybranego bitu. W tym celu musimy kykorzystać funkcję XOR (^). Wartość funkcji XOR dla dwóch bajtów przyjmuje wartość 1 gdy dwa bity są różne np. 0 i 1, jeżeli wartość bitów jest taka sama to XOR zwraca 0. Rozważmy przykład.

PORTD                      11101011
1<<PD4                     00010000
PORTD^(1<<PD4)    11111011

Zanegowaliśmy bit 4. I o to chodziło. W języku C można to zapisać jako:

PORTD^=(1<<PD4);

Przydatna tabelka wartości funkcji:


W następnej części pierwszy układ.

Brak komentarzy:

Prześlij komentarz