![]() |
Wyjście Spis treści Poprzedni Następny
Autor artykułu: mgr Jerzy Wałaszek Konsultacja: Wojciech Grodowski, mgr inż. Janusz Wałaszek |
©2015 mgr
Jerzy Wałaszek
|
| Tematy pokrewne | Podrozdziały | |
| (w budowie) |
Funkcje logiczne Manipulacje bitami Modyfikacja |
Manipulacje bitami |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
W operacjach na bitach pojawia się pojęcie maski
bitowej (ang. bit mask). Jest to po
prostu jeden z argumentów bitowej funkcji logicznej, w którym w
odpowiedni sposób zostały ustawione bity, tak aby otrzymać pożądany
wynik operacji. Cechą wspólną wszystkich przedstawionych tutaj
operacji bitowych będzie to, że zmianie ulegną wybrane bity.
Pozostałe będą niezmienione. Jest to bardzo istotne, ponieważ w
rejestrach mikrokontrolera, co zobaczymy później, bity mogą posiadać
różne znaczenia i zwykle chcemy zmienić stan określonych bitów,
które kontrolują jakąś funkcję. Pozostałe bity powinny pozostać w
swoim stanie. Ustawianie bitów na 1Operacja ta jest bardzo prosta do wykonania. Tworzymy maskę bitową, w której pożądane bity. Następnie wykonujemy bitową operację alternatywy argumentu z maską. W wyniku otrzymujemy wartość, w której zostaną ustawione na 1 bity odpowiadające bitom maski 1. Pozostałe bity zachowają swój stan z argumentu. Przykład:
Podłącz do płytki bazowej APP000 płytkę APP001, płytkę bazową połącz z programatorem, a programator z gniazdem USB twojego komputera. Ustaw obie zworki J0 i J1 na płytce APP001 w położenie górne (diody D0 i D1 mają być dołączone do linii PB0 i PB1). Następnie uruchom środowisko Eclipse, utwórz w nim nowy projekt dla ATTINY13, skopiuj poniższy program do edytora, skompiluj go i prześlij do programatora. Program tworzy w zmiennej licznik liczący w górę. Stan licznika z ustawionym na 1 bitem b2 jest przesyłany do rejestru PORTB. W ten sposób dioda D2 zawsze świeci.
W programie pojawiła się nowa konstrukcja: stała. Stała jest nazwą, której przypisano stałą wartość. Stałe definiujemy za pomocą konstrukcji:
#define nazwa wyrażenie
Nie umieszczaj za definicją stałej średnika. Powodem jest to, że powyższa deklaracja tworzy nazwę, która w programie zostanie zastąpiona podanym wyrażeniem wraz ze wszystkimi znakami, które to wyrażenie zawiera. Tak zdefiniowanej stałej nie możesz w programie zmieniać, ponieważ nie jest ona zmienną. Jeśli bity maski muszą się zmieniać, to maskę tworzymy dynamicznie lub w zmiennej. Zerowanie bitówW tym przypadku tworzymy maskę, w której bity do wyzerowania są ustawione na 0. Następnie wykonujemy bitową operację koniunkcji argumentu z maską. Wynikiem jest wartość, w której zostaną wyzerowane bity odpowiadające bitom o stanie 0 w masce. Pozostałe bity zachowają swój stan z argumentu. Przykład:
Program tworzy w zmiennej licznik liczący w górę. Stan licznika z wyzerowanym bitem b2 jest przesyłany do rejestru PORTB. W ten sposób dioda D2 zawsze jest zgaszona.
Kolejny program działa identycznie jak poprzedni. Pokazujemy w nim jedynie jak utworzyć maskę dynamicznie bezpośrednio w wyrażeniu:
Przeanalizujmy to wyrażenie:
Widzisz zatem, że została utworzona maska z wyzerowanym bitem PB2. Negacja bitówOperacja jest równie prosta jak ustawianie bitu na 1. Tworzymy maskę bitową z ustawionymi na 1 bitami, które mają zostać zanegowane. Następnie wykonujemy operację bitowej sumy symetrycznej argumentu z maską. W wartości wynikowej bity argumentu odpowiadające bitom maski 1 zostaną zanegowane. Przykład:
Program tworzy w zmiennej licznik liczący w górę. Stan licznika z zanegowanym bitem b2 jest przesyłany do rejestru PORTB.
Operacje złożoneWykorzystując podane tutaj operacje bitowe, możemy tworzyć różne skomplikowane wyrażenia. W następnym programie tworzymy licznik, który zlicza w górę co 1/10 sekundy. Następnie przenosimy do rejestru PORTB bity b3 i b4 licznika (na linie PB0 i PB1). Po tej operacji bity PB1...PB3 przesuwamy o 1 pozycję w lewo na bity PB2...PB4. Otrzymujemy w ten sposób dosyć ciekawy efekt świetlny.
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Modyfikacja |
||||||||||||||||||||||||||||||||||||||||||
|
Modyfikacja rejestru lub zmiennej polega na zmianie
zawartości na podstawie tego, co dana zmienna lub rejestr zawiera.
Brzmi to może i skomplikowanie, lecz w rzeczywistości jest bardzo
proste. Wyobraźmy sobie, że chcemy dodać do zmiennej np. liczbę 3.
Możemy wykonać to następująco:
zmienna = zmienna + 3;
A gdybyśmy chcieli ją pomnożyć przez 3, to zastosowalibyśmy polecenie:
zmienna = zmienna * 3;
To właśnie jest modyfikacja, czyli zmiana zawartości, lecz nie na zupełnie nową, oderwaną od poprzedniej, tylko na wartość, która w jakiś sposób jest powiązana z poprzednią zawartością. Ponieważ tego rodzaju konstrukcje programowe są często wykorzystywane, w języku C istnieją specjalne operatory modyfikacji zmiennych i rejestrów. Jeden z operatorów modyfikacji już
poznałeś:
zmienna++ ++zmienna
Jeśli takie wyrażenie stosujesz samodzielnie, to nie ma znaczenia, który z nich wybierzesz. W obu wypadkach zmienna zwiększy swoją zawartość o 1. Różnica pojawia się, gdy użyjesz takiej konstrukcji w wyrażeniu. Np.:
a = b++; a = ++b;
W pierwszym przypadku wartością wyrażenia b++ jest pierwotna zawartość zmiennej b. Dopiero później b zostaje zwiększone o 1. Czyli do zmiennej a trafi b sprzed modyfikacji. W przypadku drugim zmienna b jest najpierw zwiększana, a następnie wynik (czyli b zwiększone o 1) staje się wartością wyrażenia. Czyli do zmiennej a trafi wartość b już zwiększona o 1. Istnieje prosty sposób zapamiętania działania operatora ++. Wyrażenie czytamy od strony lewej do prawej, jeśli natkniemy się najpierw na zmienną, to wartością wyrażenia jest zawartość zmiennej (mówimy wtedy o tzw. późnej modyfikacji). Jeśli natkniemy się na operator ++, to wartością wyrażenia jest zwiększona o 1 zawartość zmiennej (mówimy o tzw. wczesnej modyfikacji). W
podobny sposób działa operator
zmienna-- --zmienna
Dla każdej operacji dwuargumentowej mamy odpowiednie operatory modyfikacji:
zmienna = zmienna
operator wyrażenie; → zmienna operator= wyrażenie;
Na przykład operator
zmienna += wyrażenie; a += 5; // do zmiennej a dodaj 5 a += b-1; // do zmiennej a dodaj b-1
W poniższej tabeli zebraliśmy operatory modyfikacji dla poznanych dotychczas operacji arytmetycznych, logicznych i bitowych:
Ciekawą cechą operacji przypisania i modyfikacji w języku C jest to, że posiadają one wartość i mogą uczestniczyć jako argumenty w wyrażeniach. Wyrażenie z operatorem przypisania = ma wartość przypisywaną. Na przykład wyrażenie:
a = 5;
ma wartość 5, ponieważ tyle przypisujemy zmiennej a. Pozwala to wykonywać łańcuchowe przypisania:
a = b = c = d = 10;
Do wszystkich zmiennych a, b, c i d trafi liczba 10. A całość wyrażenia dalej ma wartość 10. Wartością wyrażenia z operatorem modyfikacji jest wartość zmodyfikowanej zmiennej. Jeśli np. zmienna a zawiera 10, to wyrażenie:
a += 5;
Przyjmie wartość 15, ponieważ taką wartość będzie posiadać zmodyfikowane a. Jeśli teraz użyjemy tej operacji w wyrażeniu:
b = 5 * (a += 5);
to do zmiennej a trafi 15, a do zmiennej b trafi 15 x 5, czyli 75. Możliwości te mogą kusić początkujących programistów, jednakże ja preferuję czytelny, zrozumiały kod od poniższego horroru:
a *= ++b - (d %= (a /= c++ + --d)) * (b &= --c - d++); Poniższy program tworzy w rejestrze PORTB licznik zwiększający swą zawartość o 3 przy każdym obiegu pętli (co 1 sekundę). Licznik zlicza od 0 do 30. Program jest przeznaczony dla płytki APP001. Zworki J0 i J1 na płytce APP001 ustaw w górnym położeniu.
|
||||||||||||||||||||||||||||||||||||||||||
![]() | I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe