Programowanie
ABC... C Warunki
Warunki są to pewne specyficzne wyrażenia, które mogą przyjąć dwie wartości: true lub false, czyli po prostu prawda lub fałsz. Zwykle konstruujemy je za pomocą operatorów porównań i ewentualnie operatorów logicznych, przy czym te drugie służą do złożenia prostych warunków w jedną całość. Realizują one funkcje i, luh oraz nie.
Dowolna liczba może zuslać automatycznie zamieniona na warunek, przy czym 0 oznacza fałsz, inna wartość - prawdę. Poniższe zapisy są równoważne: if(a) <£> i£(a!=0)
Można dowolnie mieszać w jednym wyrażeniu operatory warunków, arytmetyczne, logiczne czy bitowe (operatory zostały przedstawione na wkładce du części 2, dostępnej na stronie www) Ważne jest jednak dobre zrozumienie zasady wykonywania obliczeń w C.
Do tworzenia złożonych warunków wykorzystujemy operatory logiczne. Trzeba być tutaj bardzo ostrożnym, ponieważ kompilator nie zgłosi błędu przy instrukcji na przykład jak poniższa: if (d < 12 & b)
Spodziewamy się, że instrukcja if hędzie wykonana, jeśli a jest mniejsze od podanej
zmieniamy typ tablicy g_Dane.Com na prog_uint8_t. Zgodnie z opisem możesz zamiast tego dodać zaraz za deklaracją zmiennej słowo PRÓGMEM. Sposób, jaki wybierzesz, nie ma znaczenia. Efekt będzie taki sam. Ostatnim koniecznym do zmiany punktem jest miejsce, gdzie doczytujemy dane z naszej, przeniesionej do pamięci programu, tablicy. Wszystko to wyjaśniają wspomniane ramki. Aby ułatwić Ci pracę oraz zrozumienie całości konieczne zmiany przedstawia całościowo listing 12. Tablica została umieszczona tutaj w pamięci programu za pomocą słowa PROGMEM.
Po wprowadzeniu zmian skompiluj program... udało się? Kompilacja powinna przebiec bez problemów, po załadowaniu do procesora nie zauważymy z zewnątrz różnicy w porównaniu do poprzedniej wersji. W tej chwili część programu odpowiedzialna za obsługę wyświetlacza LED jest kompletna i w pełni funkcjonalna. Jeśli jeszcze wprowadzimy do niej jakieś zmiany - będą to poprawki kosmetyczne.
Spodziewasz się może. że dostęp do pamięci programu, od strony kodu maszynowego, jest troszkę bardziej skomplikowany niż dostęp do pamięci RAM? Sprawdźmy więc, czym i jak zapłaciliśmy za zwolnione 4 liczby i jednocześnie u jest różne od zera. Jednak zastanówmy się, co się stanie w rzeczywistości:
Nastąpi porównanie liczby a z 12. Działanie to zwróci prawdę lub fałsz, liczbowo rówme 1 luh 0. Jeśli porównanie hędzie fałszywe - instrukcja zadziała lak, jak lego oczekiwaliśmy — bitowy iloczyn z jakąkolwiek liczbą zwróci wartość stalą. Jeśli b jest rówme 0, na tej samej zasadzie wszystko będzie pozornie w porządku. Problem zaczrtic się w pozostałej sytuacji. Gdy poróumanie zwróci wartość 1, a b będzie różrre ud zera, taki bitowy iloczyn może być równy 0 lub 1, zależnie od lego. czy najmłodszy bil b jest ustawiony, czy wyzerowany.
Prawidłowy zapis powinien wyglądać następująco: if(d < 12 && b)
Zapis ten jest też o tyle optymalny, że obliczenia są przerywane w momencie, gdy znany jest jnz wynik. Oznacza to. że jeśli okaże się, na przykład, że pierwsze porówna-nie zwróci fałsz - wartość zmiennej h nawet nie będzie sprawdzana. Uwaga; standard definiuje takie właśnie zachowanie, jednak nie definiuje, w jakiej kolejności testowanie ma hyc wykonywane.
Powyższe wyrażenie może wydawać się poprawne. Kompilator nie zgłosi błędu.
komórki cennej pamięci danych. Rysunek 23 przedstaw ia wyliczoną przez kompilator zaję-tość pamięci w przypadku programu. Podsumowanie takie jest wykonywane po prawidłowym zakończeniu każdej kompilacji. Obydwa programy, zgodnie z proponowaną modyfikacją, zawierały wpisanie początkowej wartości to licznika - co zajmuje dodatkowe 4
Pomyślmy jednak, jakie operacje zostaną wykonane: liczba 5 zostanie porównana ze zmienną a, dopiero wynik tego porównania zostanie porównany ze stałą 10 Co jest wynikiem pierwszego działania? true lub false, które mają wartości liczbowe l i 0. Widzisz już, co się stanie? Cale wyrażenie hędzie zawsze spełnione.
Działanie takie musisz rozbić na dwa. if( && a< )
Teraz wszystko będzie działało zgodnie z naszą intencją.
Widzisz może teraz, że warunki w C pozwalają na tworzenie nawet bardzo złożonych wyrażeń. Aby dobrze z tym sobie ładzić, konieczna jest praktyka. Nie trzeba przecież od razu wykorzystywać wszystkich złożonych możliwości. Jeśli jest to dla Ciebie wygodne, możesz złożony waninek rozbić na prostsze. Wyżej zapisaną instrukcję można by także zapisać w następujący sposób:
if(5<d)
if(d<10)
//Proyiditi dojdzie do Leyu //miFjsca jeśli f><a<10
>
bajty, lak widać, konieczność odwoływania się do pamięci programu zaowocowała zwiększeniem programu jedynie o 2 bajty! Okazuje się więc, żc działanie takie nic jest aż tak bardzo pamicciochłonne. Jeśli chcesz, w ramach ćwiczenia możesz sprawdzić, ile cykli zajmie teraz procesorowi obsługa naszego przerwania.
Listing 12 Tablica g DataCom w pamięci programu
linclude <avr\io.b> linclude cinctypes .h> linclude <avr\signal.h> linclude <avr\interrupt.h>
linclude <avr\pgmspace.h>
( )
uint8_t g_DaneCcm[ J PROGMEM =
{~(1«C0M1) / ~(l«COM2), ~(l«COM3) , ~(1«C0M4)>;
int main(void)
{
(...)
// Cb3luga przerwań SIGNAŁ(SIG_OVERFLOWO >
(
(...)
77 Włączenie odpowiedniego wyświetlacza COMPORT fi= pgm_read_byte(&g_DaneCom[g_AktWyswietLacz]) ; (...)
}
Elektronika dla Wszystkich Lipiec2005 45