22 lutego 2012

Rejestry AVR i operacje bitowe na zmiennych w C

W czasie programowania procesorów AVR mamy do dyspozycji rejestr kierunku – DDRx(x – A, B, C.. dla portów PORTA, PORTB, PORTC…). Możemy w nim zapisać kierunek przepływu danych – aby to wykonać musimy modyfikować poszczególne bity tego rejestru. Używamy także PORTx – rejestr wyjściowy, oraz PINx – rejestr wejściowy.

Aby programować poszczególne nogi procesora należy modyfikować poszczególne bity rejestrów. Jak to zrobić? Na początek przytoczę tabele prawdy funkcji boolowskich:

p q p or q
0 0 0
0 1 1
1 0 1
1 1 1
p q p and q
0 0 0
0 1 0
1 0 0
1 1 1
p q p xor q
0 0 0
0 1 1
1 0 1
1 1 0
p not p
0 1
1 0

W języku C operatory(bitowe) zapisujemy następująco:

Operator Nazwa Zapis w C
OR alternatywa |
AND koniunkcja &
XOR alternatywa wykluczająca ^
NOT negacja ~

Używając ich odpowiednio możemy modyfikować poszczególne bity rejestrów – a ogólnie mówiąc zmiennych.

Rejestry mają po 8 bitów(procesory 8-bitowe)


Ustawianie bitu

Ustawianie x-owego bitu zmiennej abc:

abc |= (1<<x);&#91;/code&#93;

Przykładowo, chcemy ustawić 3 bit rejestru kierunkowego DDRD - port PD3.Korzystamy z kodu podanego wcześniej:

&#91;code&#93;DDRD |= (1<<3);&#91;/code&#93;

albo

&#91;code&#93;DDRD |= (1<<PD3);&#91;/code&#93;

Jak to działa?
Najpierw liczba 1 (binarnie: <span style="font-family: courier new,courier;">0b00000001</span>, <span style="font-family: courier new,courier;">0b</span>-nieformalny przedrostek trybu binarnego w AVR-GCC) zostaje przesunięta o 4 w lewo:


00000001 << 4
->
00001000

Następnie jest ona poddawana bitowemu OR z rejestrem. Niech ten rejestr ma stan początkowy(0b00000000):

   00000000
   00001000
OR --------
   00001000

W wypadku kiedy byśmy już mieli ustawiony ten i kilka pozostałych bitów w rejestrze:

   00101110
   00001000
OR --------
   00101110

Stan rejestru się nie zmienia, bit nr 4 jest cały czas ustawiony.


Reset bitu

Zresetowanie x-owego bitu zmiennej abc:

abc &= ~(1<<x);&#91;/code&#93;

Reset 4 bitu wykonujemy poleceniem:

&#91;code&#93;DDR &= ~(1<<4);&#91;/code&#93;

Następuje przesunięcie oraz negacja tego przesunięcia:

&#91;code&#93;
    00001000
NOT --------
    11110111
&#91;/code&#93;

następnie wynik jest poddawany koniunkcji z rejestrem(0b00000000):

&#91;code&#93;
    00101110
    11110111
AND --------
    00100110
&#91;/code&#93;

Co w wypadku, gdy rejestr posiada inne bity ustawione?

&#91;code&#93;
    00000000
    11110111
AND --------
    00000000
&#91;/code&#93;

Analogicznie jak z alternatywą, pozostają one na swoim miejscu.

<hr />

<h2>Odwrócenie(wymiana) bitu</h2>
Odwrócenie x-owego bitu zmiennej abc. Polega to na tym, że jeśli dany bit ma wartość 1 to zostanie on zamieniony na 0 i odwrotnie:

abc ^= (1<<x);&#91;/code&#93;

Odwrócenie 7 bitu:

&#91;code&#93;abc ^= (1<<7);&#91;/code&#93;

W tabeli:

&#91;code&#93;
    10111001
    01000000
XOR --------
    11111001
&#91;/code&#93;


<hr />

<h2>Operacje bitowe na kilku bitach na raz</h2>
Oczywiście można przyspieszyć ustawianie bitów robiąc to w jednej komendzie - używamy operatora bitowego OR do ich połączenia.

Przykład: wyłączenie(reset) bitu 2,3,6,8 w zmiennej x:

x &= ~( 1<<2 | 1<<3 | 1<<6 | 1<<8 );&#91;/code&#93;

W tabelce:

&#91;code&#93;
   00000010
   00000100
   00100000
   10000000
OR --------
   10100110
 ~ --------
   01011001
&#91;/code&#93;

Dla zmiennej x = <span style="font-family: courier new,courier;">0b10100111</span>:


   10100111
   01011001
 & --------
   00000001

Dodatkowa literatura:

[TUT] [C] Bit manipulation (AKA "Programming 101")

Bit operations with AVR-GCC

Problemy C - Ustawianie i zerowanie bitów

Zagrożenia ze stosowania #define

AVR-GCC - wejście i wyjście binarne

TrackBack

TrackBack URL dla tej wiadomości:
https://blog.kkthx.pl/2012/02/rejestry-avr-i-operacje-bitowe-na-zmiennych-w-c/trackback/

Komentarze

Mały błąd się wkradł 🙂 W ostatnim przykładzie wynikiem powinna być wartość 00000001

Dzięki za sugestię – poprawione 😉

Napisz komentarz