lif opóźnienie > 2‘.
ABC... C
Generowanie własnych błędów i ostrzeżeń
Gdy kompilator natknie się na dyrektywę flerror, zakończy swoją pracę wyświetlając opis błędu który podajemy zaraz za dyrektywą.
Aby wyjaśnić sposób oraz ideę tworzenia własnych informacji o błędzie posłużmy się troszkę uproszczoną częścią kodu z listingu 42. Posiadamy tutaj funkcję opóźnienia, która działa prawidłowo dla liczby o wartości najwyżej 255, próba podania wartości większej spowoduje zignorowanie najstarszych bitów, o czym nie zostaniemy nawet poinformowani Gest to jedna z przykrości wstawek asemblerowych - kompilator ich nie pilnuje). Jeśli opóźnienie jest wartością stałą, możemy za pomocą prostej konstrukcji z kompilacją warunkową (poprzednia
ramka) sprawdzić czy zakres nie został przekroczony:
i Ifdefine Opóźnienie 256
Oczywiście przedstawiony przykład jest banalny -zawsze uzyskamy informację o błędzie wyglądającą mniej więcej jak poniżej:
Kliknięcie na powyższy tekst w okienku Output spowoduje przeniesie kursora na pozycje, gdzie pojawiła się dyrektywa /terror, Przytoczony przykład, oczywiście w praktyce, nie ma większego sensu. Jednak, już jeśli wartość stałej opóźnienie będzie wynikiem jakiś: obliczeń, przeprowadzenie stosownego sprawdzenia jest:całkowicie uzasadnione.
Ważne jest to, aby zrozumieć, że kompilator zgłosi błąd zawsze gdy natknie się na dyrektywę tterror. W praktyce więc używamy jej łącznie z dyrektywami kompilacji warunkowej.
Jeśli rozumiesz już ideę komendy /terror, nic będziesz miał żadnych problemów z komendą ttwar-ning. Jej działanie jest bardzo zbliżone. Różni się jedynie tym, że po zgłoszeniu ostrzeżenia kompilacja jest kontynuowana. Możesz postanowić, że błąd przepełnienia zakresu-OąSzego opóźnienia nie jest tak ważny aby zatrzymywać kompilację i pozostawić jedynie generowanie ostrzeżenia. Nic prostszego: wystarczy zamienić słowo error na warning,
jednego słowa programu: dla kolejnych przypadków będzie to kolejno: nop, rjmp, rcall. Dla opóźnień z zakresu 3-8 cykli wywoływana jest funkcja zawierająca tylko jedną instrukcję: nop. Wywołanie podprogramu, nop, powrót z podprogramu - daje to 5 cykli. Rozwiązanie nie jest „super” dokładne, ale też „super” dokładności nie potrzebujemy. Zwracam uwagę na to, że instrukcja NOP() jest konieczna - inaczej kompilator usunie całą funkcję i jej wywołania. Dla opóźnień dłuższych tworzona jest znana nam już pętla - ten fragment nie powinien sprawiać problemów. Nowością w tym przypadku jest jedynie sprawdzenie, czy ilość powtórzeń pętli może być wykonana. Jeśli nie - zgłaszana jest informacja o błędzie.
Kod nie jest taki straszny. Przyjrzyj się zastosowaniu instrukcji warunkowych - z elementów tych będziemy korzystać coraz częściej, tworząc coraz bardziej uniwersalne moduły.
Na listingu 43 możesz zobaczyć funkcje zmieniające odpowiednio fizyczne wyprowadzenia portów. Moglibyśmy się bez nich obejść - wpisując w programie bezpośrednio instrukcje odwołujące się do portów. Byłoby to niewygodne przede wszystkim ze względu na linię SDA - decydując się na wewnętrzne podciąganie musimy się liczyć z koniecznością bardziej skomplikowanego sterowania portem - dla stanu wysokiego konieczne jest ustawienie portu jako wejścia i włączenia podciągania, dla stanu niskiego wyłączenie podciągania i przełączenie portu w tryb wyjścia. Wykonanie analogicznych funkcji dla linii zegara zwiększa czytelność kodu.
Moglibyśmy w tym miejscu posłużyć się także makrami - tak jak robiliśmy to w poprzednich częściach. Dużo zależy od preferencji. Mnie funkcje w tym miejscu wydają się bardziej przyjazne.
Serce obsługi I2C znajduje się na listingu 44. Przyjrzyj się, w jaki sposób generowane są warunki START i STOP. W razie potrzeby psłuż się rysunkami 28-31. Generacja warunku start została troszkę skomplikowana ze względu na możliwość jego wywołania także bez kończenia transmisji. Konieczne jest uwzględnienie faktu, że funkcja wysyłająca i odbierająca bajt zostawia zawsze linię SCL w stanie niskim, jednak stan linii SDA nie jest określony.
Pośród naszych funkcji nie ma takich, które obsługiwałyby kompletne ramki, takie jak na rysunku 31. W najprostszym przypadku nie są one potrzebne - wysłanie dowolnej ramki może być zrealizowane przez wyższą część programu za pomocą czterech tylko funkcji z listingu 44.
Modpł i2c zamyka wpisanie do pliku nagłówkowego zawartości listingu 45.
46 Grudzień 2005 Elektronika dla Wszystkich