Systemy wbudowane
Transkrypt
Systemy wbudowane
Systemy wbudowane Porty we/wy mikrokontrolera PIC16F877A Urządzenia wejścia/wyjścia Ogólnie ● ● Porty A, B, C, D i E mikrokontrolerów są portami wejścia/wyjścia ogólnego przeznaczenia. Wyprowadzenia portów mogą również pełnić wiele funkcji dodatkowych, takich jak np.: ● wejście układu czasowo-licznikowego, ● wejście sygnału przerwania, ● wejście przetwornika analogowo-cyfrowego, ● wejścia i wyjścia interfejsu szeregowego i równoległego, magistrali I2C, ● wyprowadzenia układu CCP, itp. Rejestry PORTx ● ● ● ● Z każdym portem wejścia/wyjścia są związane dwa specjalne rejestry: PORTx i TRISx, gdzie ‘x’ odpowiada nazwie portu określonej kolejną literą alfabetu (A, B, C, D, E). Rejestry PORTx stanowią interfejs pomiędzy jednostką centralną mikrokontrolera a portami. Za pomocą tych rejestrów można wysyłać dane na zewnątrz mikrokontrolera, wpisując odpowiednią wartość do odpowiedniego rejestru PORTx. Rejestry PORTx służą też do przekazywania jednostce centralnej wartości wejściowych przychodzących do portów mikrokontrolera, poprzez odczyt odpowiednich rejestrów PORTx. Rejestry TRISx ● ● ● ● ● Rejestry TRISx służą do konfiguracji portów wejścia/wyjścia poprzez określenie kierunku pracy danego portu (wejście lub wyjście). Ustalanie kierunku pracy portu odbywa się poprzez ustawienie odpowiednich bitów w rejestrze TRISx, Ustawienie jedynki w rejestrze TRISx powoduje przełączenie odpowiedniego wyprowadzenia portu PORTx na tryb wejścia, Wpisanie zera – przełączenie na wyjście. W celu łatwiejszego zapamiętania wystarczy zauważyć podobieństwo pomiędzy znakami 1 – I (czyli Input – wejście) oraz 0 – O (czyli Output – wyjście). Inicjalizacja portów Wszystkie porty wejścia/wyjścia należy przed użyciem zainicjalizować. Polega to głównie na wyborze kierunku przesyłania danych za pomocą rejestrów TRISx. Inicjalizację portów można przeprowadzić wykonując następujące czynności: • wybrać bank w którym znajdują się rejestry PORTx (bank nr 0); • wyzerować rejestry zatrzaskowe portu poprzez wpisanie 0 do rejestru PORTx; • wybrać bank w którym znajdują się rejestry TRISx (bank nr 1); • wybrać kierunek przepływu danych portu x, poprzez ustawienie poszczególnych bitów rejestru TRISx. Port A ● ● ● Port A jest dwukierunkowym portem ogólnego przeznaczenia mikrokontrolerów PIC16. Dla mikrokontrolera PIC16F877A wyprowadzenia portu A są współdzielone z układami CCP oraz przetwornikiem analogowocyfrowym. Dla mikrokontrolera PIC16F877A szerokość portu to 6 bitów Wyprowadzenia portu A Nazwa Bit Typ bufora Funkcja RA0/AN0 0 TTL Wyprowadzenie wejścia/wyjścia lub analogowe wejście RA1/AN1 1 TTL Wyprowadzenie analogowe wejście RA2/AN2/VREF-/CVREF 2 TTL Wyprowadzenie wejścia/wyjścia wejście analogowe lub wyprowadzenie układu napięcia odniesienia RA3/AN3/VREF+ 3 TTL Wyprowadzenie wejścia/wyjścia wejście analogowe lub wyprowadzenie układu napięcia odniesienia RA4/T0CKI/C1OUT 4 ST Wyprowadzenie wejścia/wyjścia lub wejście zegara dla układu TIMER0 lub wyjście komparatora. Wyjście jest typu „otwarty dren” RA5/AN4/SS/C2OUT 5 TTL Wyprowadzenie wejścia/wyjścia lub wejście analogowe lub wybór urządzenia podrzędnego dla PSP lub wyjście komparatora wejścia/wyjścia Inicjalizacja portu A ● ● ● Dla mikrokontrolera PIC16F877A wyprowadzenia portu A są współdzielone z wejściami analogowymi przetwornika A/C. Podczas zerowania mikrokontrolera port A jest ustawiany w trybie wejścia analogowego i każdy odczyt z tego portu zwróci wartość równą zero. Dlatego należy pamiętać, aby w przypadku wykorzystywania portu A jako portu cyfrowego przełączyć go w tryb cyfrowy wpisując do rejestru ADCON1 wartość 06h. bcf STATUS, RP0 clrf PORTA bsf STATUS, RP0 movlw B'00000110' movwf ADCON1 clrf TRISA ; wybór banku 0 ; inicjalizacja PORTA przez zerowanie zatrzasków wyjściowych ; wybór banku 1 ; przełączenie wejść na cyfrowe ; poprzez odłączenie przetwornika A/C ; ustawienie wyprowadzeń PORTA na wyjścia Port B ● ● ● Port B jest dwukierunkowym 8-bitowym portem ogólnego przeznaczenia mikrokontrolerów PIC16. Dla mikrokontrolera PIC16F877A wyprowadzenie portu B są współdzielone z wejściami programatora niskonapięciowego i debuggera sprzętowego. Każde wyprowadzenie portu B ma możliwość podłączenia rezystora podciągającego (pull-up). ● Opcja ta jest aktywowana poprzez wyzerowanie bitu RBPU w rejestrze OPTION_REG. ● Rezystory podciągające są automatycznie wyłączane, gdy wyprowadzenia są skonfigurowane jako wyjścia. ● Funkcja ta jest też wyłączana w momencie zerowania mikrokontrolera Inicjalizacja portu B bcf STATUS, RP0 clrf PORTB bsf STATUS, RP0 buf OPTION_REG, RBPU movlw B’00001111’ movwf TRISA ; wybór banku 0 ; inicjalizacja przez zerowanie zatrzasków ; wyjściowych ; wybór banku 1 ; włączenie rezystorów pull-up ; ustawienie wyprowadzeń RB3:RB0 jako ; wejść ; ustawienie wyprowadzeń RB4:RB7 jako ; wyjść Funkcje wyprowadzeń portu B Nazwa Bit Typ bufora Funkcja RB0/INT 0 TTL/ST Wyprowadzenie wejścia/wyjścia lub wejście przerwania zewnętrznego RB1 1 TTL Wyprowadzenie wejścia/wyjścia RB2 2 TTL Wyprowadzenie wejścia/wyjścia RB3/PGM 3 TTL Wyprowadzenie wejścia/wyjścia lub wejście programowania układu w trybie niskonapięciowym RB4 4 TTL Wyprowadzenie wejścia/wyjścia (z funkcją przerwania przy zmianie stanu) RB5 5 TTL Wyprowadzenie wejścia/wyjścia (z funkcją przerwania przy zmianie stanu) RB6/PGC 6 TTL/ST Wyprowadzenie wejścia/wyjścia (z funkcją przerwania przy zmianie stanu) lub wejście zegara przy programowaniu szeregowym RB7/PGD 7 TTL/ST Wyprowadzenie wejścia/wyjścia (z funkcją przerwania przy zmianie stanu) lub wejście danych przy programowaniu szeregowym do Cechy portu B ● ● ● ● Port B posiada także wejście przerwania zewnętrznego (bit nr 0) oznaczone jako RB0/INT (rys. 2.34). Wszystkie wyprowadzenia posiadają bufor TTL na wejściu. Linia 0 portu posiada na wejściu przerzutnik Schmitta, kiedy jest wykorzystywana jako wejście przerwania zewnętrznego. Linie 6 i 7 (dla mikrokontrolera PIC16F877A) posiadają na wejściu przerzutnik Schmitta, gdy są wykorzystywane do programowania mikrokontrolera. Port C ● ● ● ● ● ● Port C jest portem ogólnego przeznaczenia mikrokontrolera PIC16F877A. Nie występuje on w mikrokontrolerze PIC16F84. Wszystkie wyprowadzenia na wejściu posiadają przerzutnik Schmitta. Port C jest współdzielony z kilkoma różnymi układami peryferyjnymi. Kiedy aktywowane są funkcje peryferyjne, należy zwrócić szczególną uwagę na ustawienia rejestru TRISC dla każdego wyprowadzenia portu C. Niektóre układy peryferyjne ignorują ustawienia bitów w rejestrze TRISC i same wymuszają użycie wyprowadzeń jako wejścia lub wyjścia. Z tego powodu przy włączonych urządzeniach peryferyjnych należy unikać używania instrukcji modyfikujących rejestr TRISC, takich jak: BSF, BCF, XORWF. Port D ● ● ● ● Port D jest portem ogólnego przeznaczenia mikrokontrolera PIC16F877A. Port D posiada osiem wyprowadzeń: RD0/PSP0, RD1/PSP1, RD2/PSP2, RD3/PSP3, RD4/PSP4, RD5/PSP5, RD6/PSP6, RD7/PSP7, które są indywidualnie konfigurowalne jako wejścia lub wyjścia. Wszystkie wyprowadzenia na wejściu posiadają przerzutnik Schmitta. Port D może być skonfigurowany jako wejście/wyjście cyfrowe ogólnego przeznaczenia lub jako 8-bitowy port równoległy PSP (Paralel Slave Port) poprzez ustawienie w rejestrze TRISE bitu nr 4 na jedynkę. Port E ● ● ● ● ● ● Port E jest portem specjalnym mikrokontrolera PIC16F877A. Port E posiada trzy wyprowadzenia: RE0/RD/AN5, RE1/WR/AN6 i RE2/CS/AN7, które są indywidualnie konfigurowalne jako wejścia lub wyjścia. Wszystkie wyprowadzenia na wejściu posiadają przerzutnik Schmitta. Wyprowadzenia portu E stają się wejściami kontrolnymi dla portu równoległego PSP po ustawieniu w rejestrze TRISE bitu nr 4 na jedynkę. Oczywiście w tym trybie bity 2:0 rejestru TRISE powinny także być ustawione na jedynkę oraz port powinien być przełączony w tryb cyfrowy za pomocą rejestru ADCON1. Port E służy także jako wejście analogowe mikrokontrolera. Należy pamiętać, że po wyzerowaniu mikrokontrolera port E jest ustawiony w trybie wejścia analogowego. Diody LED ● ● ● ● ● Dioda LED (dioda elektroluminescencyjna, LED – ang. Light Emitting Diode) jest to półprzewodnikowy element elektroniczny, który emituje światło pod wpływem przepływającego prądu elektrycznego. Świecenie diody następuje, gdy dioda LED jest spolaryzowana w kierunku przewodzenia, tzn. do anody podłączony jest biegun dodatni, a do katody biegun ujemny. Diody świecą w różnych kolorach: czerwonym, zielonym, żółtym, niebieskim. Mogą również wysyłać promieniowanie podczerwone. Długość fali światła wypromieniowywanego przez diodę LED (a co za tym idzie kolor diody) zależy od materiałów użytych w procesie produkcyjnym. Diody LED są bardzo często stosowane w systemach wbudowanych do sygnalizacji stanu działania urządzenia. Ich zaletą jest niewielki pobór prądu przy dużej jasności. Podłaczenie diody LED Mikrokontrolery PIC pozwalają na bezpośrednie podłączenie diody LED do wyjścia portu. Wartość rezystora R należy dobrać w taki sposób, aby nie przekroczyć maksymalnego prądu wyjściowego mikrokontrolera oraz nie przekroczyć maksymalnego prądu diody LED. Można ją obliczyć ze wzoru: R=(UOH-UD)/ID gdzie: UOH – napięcie wyjściowe portu mikrokontrolera w stanie wysokim; UD – napięcie na diodzie LED; ID – prąd diody LED, który jest jednocześnie prądem wyjściowym mikrokontrolera w stanie wysokim (IOH). Wartości UOH oraz IOH można znaleźć w dokumentacji mikrokontrolera, natomiast UD oraz ID w dokumentacji diody bądź uzyskać za pomocą prostego układu pomiarowego charakterystyki prądowo-napięciowej diody. Sterowanie diodą LED Sterowanie diodą LED jest bardzo proste i wymaga wykonania dwóch czynności („x” oznacza port, do którego podłączona jest dioda LED): 1) ustawienie wyprowadzenia portu, do którego jest podłączona dioda LED, w tryb pracy wyjścia, poprzez wyzerowanie odpowiedniego bitu w rejestrze TRISx. Czynność tą należy wykonać na początku programu. 2) w zależności od potrzeb należy wyzerować lub ustawić odpowiedni bit w rejestrze PORTx: – jeśli chcemy zapalić diodę, to bit należy ustawić, – jeśli chcemy zgasić diodę, to bit należy wyzerować. Sterowanie LED - przykład #include p16f877A.inc RST CODE pagesel START goto START PGM CODE START banksel TRISA ; dioda LED jest podłączona do portu PORTA bcf TRISA, RA0 ; do wyprowadzania RA0 banksel PORTA bsf PORTA, RA0; ustawienie bitu = zapalenie diody goto END $ Przyciski ● ● ● ● ● Bardzo często istnieje potrzeba sterowania systemem wbudowanym za pomocą przycisku lub zestawu przycisków, a nawet klawiaturą. Przyciski najczęściej wykonywane są w postaci mikroprzełączników, które po naciśnięciu zwierają styki. Ponieważ zwolniony przycisk stanowi rozwarcie, wejście mikrokontrolera należy wstępnie spolaryzować za pomocą rezystora podciągającego (ang. pull-up). Może to być rezystor zewnętrzny o wartości 10 k podłączony do źródła zasilania i wejścia mikrokontrolera, jak również wewnętrzny rezystor pull-up. Mikrokontrolery PIC16 posiadają możliwość włączenia rezystorów podciągających na liniach portu PORTB za pomocą wyzerowania ustawienia bitu RBPU w rejestrze OPTION_REG. Żaden inny port nie posiada wbudowanych rezystorów podciągających. Podłączenie przycisku do uC Odczytywanie wartości na wejściu mikrokontrolera nie jest trudne i wymaga wyłącznie sprawdzenia stanu odpowiedniego bitu rejestru PORTB. Należy zwrócić uwagę, że stan naciśnięcia przycisku sygnalizowany jest za pomocą logicznego zera (niskiego poziomu), natomiast stan zwolnienia przycisku za pomocą logicznej jedynki (wysokiego poziomu). Obsługa przycisku ● ● ● ● ● Naciśnięcie przycisku jest procesem dynamicznym, w trakcie którego stan wejścia zmienia się z wysokiego (logiczna jedynka) na niski (logiczne zero). Dlatego procedury sprawdzające, czy przycisk został naciśnięty nie powinny sprawdzać jedynie wartości bitu w rejestrze, a zmianę wartości (np. poprzez oczekiwanie na pojawienie się zera). Po naciśnięciu przycisku program przechodzi do części oznaczonej w komentarzu „WCIŚNIĘTO”, gdzie można wykonać niezbędne operacje. Następnie program oczekuje na zwolnienie przycisku. Po zwolnieniu przycisku program wraca do początku pętli. Obsługa przycisku - przykład banksel OPTION_REG bcf OPTION_REG, NOT_RBPU banksel TRISB movlw 0xFF movwf TRISB ; włączenie pull-up na PORTB ; przełączenie portu B na wejścia banksel PORTB KB_READ btfsc PORTB, RB0 ; czy naciśnięty przycisk? goto $-1 ; nie – wróć o jeden wiersz w górę ; WCIŚNIĘTO ; tutaj wykonujemy operacje po wciśnięciu przycisku btfss goto PORTB, RB0 ; czy zwolniono przycisk? $-1 ; nie – wróć o jeden wiersz w górę goto KB_READ ; pętla odczytywania stanu klawisza Iskrzenie ● ● ● ● ● Każdy przycisk w trakcie naciskania przez pewien moment generuje ciąg zer i jedynek. Stan taki, zwany iskrzeniem, jest normalnym zjawiskiem wynikającym z fizycznej budowy przełącznika. Procedura sprawdzająca, czy przycisk został naciśnięty odczyta taki stan, jako wielokrotne naciśnięcie i zwolnienie przycisku. Stan iskrzenia trwa z reguły kilka milisekund. Aby zabezpieczyć się przed niepoprawnym odczytem stanu klawisza należy wprowadzić opóźnienia w trakcie odczytywania. Likwidacja iskrzenia KB_READ btfsc goto call PORTB, RB0 ; czy naciśnięty przycisk? $-1 ; nie – wróć o jeden wiersz w górę delay_5ms ; odczekaj 5 ms – likwidacja iskrzenia ; tutaj wykonujemy operacje po wciśnięciu przycisku btfss goto PORTB, RB0 ; czy zwolniono przycisk? $-1 ; nie – wróć o jeden wiersz w górę call delay_5ms ; odczekaj 5 ms – likwidacja iskrzenia goto KB_READ ; pętla odczytywania stanu klawisza Po naciśnięciu przycisku następuje odczekanie przez 5 ms, po którym iskrzenie praktycznie już nie występuje. Identyczna sytuacja ma miejsce przy zwalnianiu przycisku. Wyświetlacz 7-segmentowy LED ● ● ● Wyświetlacz siedmiosegmentowy zbudowany jest z siedmiu (lub ośmiu) diod LED ustawionych w kształcie cyfry „8”. Poszczególne segmenty są oznaczane kolejnymi małymi literami alfabetu od „a” do „g”. Niektóre wyświetlacze posiadają dodatkową diodę wyświetlającą punkt dziesiętny, oznaczany najczęściej „dp” (ang. decimal point). Typy wyświetlaczy ● ● ● Ponieważ wyświetlacz siedmiosegmentowy składa się z diod LED, to jego podłączenie do mikrokontrolera można zrealizować podobnie, jak podłączenie pojedynczej diody. Należy pamiętać, że wyświetlacze są produkowane w dwóch wariantach: ze wspólną anodą i ze wspólną katodą. Należy pamiętać, że włączenie segmentu wymaga podania na port wartości „1” dla wyświetlacza ze wspólną katodą, natomiast dla wyświetlacza ze wspólną anodą segment zostanie zaktywowany po podaniu logicznego zera. Wspólna anoda Wspólna katoda Podłaczenie wyświetlacza do portu B Wyświetlacz siedmiosegmentowy najczęściej podłączany jest do wyprowadzeń jednego portu. W dalszej części przyjęto założenie, że został on podłączony do portu PORTB w sposób przedstawiony w tabeli. RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 dp ● ● ● g f e d c b a Wyświetlenie żądanego symbolu wymaga zapalenia odpowiednich segmentów. Kod, który należy wysłać do rejestru PORTB, aby wyświetlić żądany znak, określony jest za pomocą kombinacji jedynek (segment zapalony) i zer (segment wygaszony). Na przykład do wyświetlenia cyfry „2” należy zapalić segmenty a, b, d, e i g, co daje kod B'01011011' Przykład banksel TRISA clrf TRISA banksel PORTA movlw movwf goto ; wyświetlacz jest podłączony do portu PORTB ; ustaw wszystkie wyprowadzenia PORTB jako wyjścia B'01011011' ; zapal odpowiednie segmenty, aby uzyskać '2' PORTB $ Definiowanie kodów wyświetlacza W przypadku, gdy w programie często występuje potrzeba wyświetlenia symbolu na wyświetlaczu, zapisywanie kodu aktywującego segmenty w postaci binarnej znacznie zmniejsza czytelność programu, a dodatkowo ciągłe wpisywanie ciągu zer i jedynek wydłuża znacznie pisanie programu. Znacznym ułatwieniem może być zadeklarowanie stałych, które będą zawierały kody aktywujące segmenty dla poszczególnych symboli. LED_0 LED_1 LED_2 LED_3 LED_4 LED_5 LED_6 LED_7 LED_8 LED_9 equ equ equ equ equ equ equ equ equ equ B'00111111' B'00000110' B'01011011' B'01001111' B'01100110' B'01101101' B'01111101' B'00000111' B'01111111' B'01101111' ;0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 ;8 ;9 Tablice konwersji Gdy wyświetlana wartość jest wyliczana w programie lepiej jest skorzystać z tablicy konwersji bin2seg addwf dt dt dt dt dt dt dt dt dt dt PCL, f B'00111111' B'00000110' B'01011011' B'01001111' B'01100110' B'01101101' B'01111101' B'00000111' B'01111111' B'01101111' ;0 ;1 ;2 ;3 ;4 ;5 ;6 ;7 ;8 ;9 Wyświetlenie symbolu z wykorzystaniem tablicy konwersji: movlw call movwf 3 bin2seg PORTB ; załaduj wartość do wyświetlenia, np. 3 ; wywołaj procedurę konwersji ; wysłanie na port PORTB Podłączenie multipleksowane ● ● ● ● ● Podłączenie większej liczby wyświetlaczy napotyka znaczne trudności. Jeden wyświetlacz wymaga 7 (lub 8) wyprowadzeń. W związku z tym podłączenie czterech wyświetlaczy wymagałoby 28 (lub 32) wyprowadzeń, co niejednokrotnie przekracza możliwości mikrokontrolera (np. dla układów w obudowach 14-nóżkowych). Rozwiązaniem jest wyświetlanie multipleksowane. Wyświetlanie multipleksowane (inaczej sekwencyjne) jest to taki sposób wyświetlania, w którym w dowolnej chwili aktywny jest zawsze tylko jeden wyświetlacz. Wyświetlacze włączane są po kolei na krótki czas. Ponieważ oko ludzkie wykazuje bezwładność i nie potrafi rozdzielić obrazów zmieniających się z częstotliwością większą, niż 25 Hz, powstaje wrażenie obrazu statycznego, w którym świecą są wszystkie wyświetlacze. Realizacja podłaczenia multipleksowanego ● ● ● ● ● ● ● Połączenie wyświetlaczy do realizacji wyświetlania multipleksowanego wymaga połączenia równoległego segmentów poszczególnych wyświetlaczy (segment „a” wyświetlacza pierwszego z segmentem „a” wyświetlacza drugiego i tak dalej dla wszystkich wyświetlaczy; następnie segment „b” wyświetlacza pierwszego z segmentem „b” wyświetlacza drugiego i tak dalej dla wszystkich wyświetlaczy; czynności te powtarzamy dla wszystkich segmentów). W wyniku uzyskamy 7 (lub 8) wyprowadzeń służących do wyboru segmentów, które mają zostać wyświetlone. Wyprowadzenia segmentów podłączane są, podobnie jak diody LED, poprzez rezystor ograniczający prąd do wyprowadzeń mikrokontrolera. Najlepiej jest podłączyć je do wyprowadzeń jednego portu (np. PORTB). Dodatkowo każdy wyświetlacz powinien być podłączony w taki sposób, żeby była możliwość jego włączenia i wyłączenia. Można wykorzystać zarówno zwykły tranzystor, jak i specjalizowane układy scalone Podłączenie multipleksowane – schemat połączeń ● ● Zaletą tego sposobu wyświetlania jest znaczące zmniejszenie liczby wyprowadzeń mikrokontrolera, które są konieczne do wysterowania wyświetlaczy (np. dla czterech wyświetlaczy z 28 lub 32 do 11 lub 12). Wadą – migotanie, szczególnie widoczne podczas poruszania głową oraz trudniejsze przygotowanie kodu programu. Realizacja programowa ● ● ● na port, który podłączony jest do segmentów wyświetlaczy, należy podać kod aktywujący odpowiednie segmenty (w naszym przykładzie PORTB); ustawić w porcie odpowiedzialnym za włączanie wyświetlaczy odpowiedni bit, który spowoduje włączenie jednego wyświetlacza (w naszym przykładzie są to bity portu PORTA: RA0, RA1, RA2 oraz RA3); odczekać pewien czas i powtórzyć procedurę od początku dla kolejnych wyświetlaczy. Czas, który należy odczekać, można obliczyć z następującego wyrażenia: T = 1 / (N * fR) gdzie: fR jest to częstotliwość odświeżania obrazu (większa niż 25Hz); N – liczba wyświetlaczy. Przykład – liczba 1234 Petla movlw call movwf bsf call bcf 1 ; załadowanie wartości do wyświetlenia bin2seg ; zamiana na kod aktywujący segmenty PORTB ; wysłanie na PORTB – aktywacja segmentów PORTA, RA0; włączenie pierwszego wyświetlacza delay_5ms ; odczekanie 5 ms PORTA, RA0; wyłączenie pierwszego wyświetlacza movlw call movwf bsf call bcf 2 ; załadowanie wartości do wyświetlenia bin2seg ; zamiana na kod aktywujący segmenty PORTB ; wysłanie na PORTB – aktywacja segmentów PORTA, RA1; włączenie drugiego wyświetlacza delay_5ms ; odczekanie 5 ms PORTA, RA1; wyłączenie drugiego wyświetlacza Przykład c.d. movlw call movwf bsf call bcf 3 ; załadowanie wartości do wyświetlenia bin2seg ; zamiana na kod aktywujący segmenty PORTB ; wysłanie na PORTB – aktywacja segmentów PORTA, RA2; włączenie trzeciego wyświetlacza delay_5ms ; odczekanie 5 ms PORTA, RA2; wyłączenie trzeciego wyświetlacza movlw call movwf bsf call bcf 4 ; załadowanie wartości do wyświetlenia bin2seg ; zamiana na kod aktywujący segmenty PORTB ; wysłanie na PORTB – aktywacja segmentów PORTA, RA3; włączenie czwartego wyświetlacza delay_5ms ; odczekanie 5 ms PORTA, RA3; wyłączenie czwartego wyświetlacza goto Petla ; powrót do początku Powyższy fragment kodu korzysta z procedury delay_5ms, która nie została przytoczona Wyświetlanie multipleksowane problemy ● ● ● Problemem wyświetlania multipleksowanego jest konieczność zapewnienia wyświetlania wraz z możliwością wykonywania innych czynności. Dlatego procedurę realizującą wyświetlanie multipleksowane bardzo często umieszcza się w procedurze obsługi przerwania, które wyzwalane jest jednym z układów czasowo-licznikowych (np. Timer1). O przerwaniach i timerach będzie później... LCD ● ● ● ● ● ● ● Wyświetlacz ciekłokrystaliczny LCD (ang. Liquid Crystal Display) jest to rodzaj wyświetlacza, w którym wykorzystywane jest zjawisko skręcenia płaszczyzny polaryzacji przez ciekłe kryształy. Światło jak każda fala elektromagnetyczna może być spolaryzowane, tzn. drgania ośrodka mogą odbywać się w jednej płaszczyźnie. Elementem optycznym, który służy do polaryzowania światła jest filtr polaryzacyjny (polaroid). Pewne substancje mają możliwość skręcania płaszczyzny polaryzacji. Jeżeli spolaryzowane światło zostanie przepuszczone przez polaroid o płaszczyźnie polaryzacji zgodnej z polaryzacją światła padającego, to zostanie ono przepuszczone. Jeżeli jednak płaszczyzna polaryzacji światła zostanie skręcona, to polaroid przepuści tylko tą część, która pozostanie zgodna z jego płaszczyzną polaryzacji. Ciekłe kryształy potrafią skręcać płaszczyznę polaryzacji światła, a dodatkowo kąt skręcenia może być ustalany za pomocą pola elektrycznego. Kontroler wyświetlacza ● ● ● ● ● ● Sterowanie zwykłym wyświetlaczem LCD jest dość skomplikowane, dlatego wielu producentów dostarcza układy sterowników, pozwalające na sterowanie wyświetlaczami za pomocą prostego interfejsu łączącego sterownik z mikrokontrolerem. Alfanumeryczny wyświetlacz LCD oparty na kontrolerze HD44780 stał się w tej dziedzinie standardem przemysłowym. Alfanumeryczny wyświetlacz LCD oparty na HD44780 pozwala na wyświetlenie maksymalnie 4 wierszy po 20 znaków każdy. Znaki mogą pochodzić z wewnętrznego generatora znaków, jak również z generatora znaków użytkownika (maksymalnie 8 znaków). Prosty interfejs łączący wyświetlacz z mikrokontrolerem wymaga od 6 do 11 linii sygnałowych w zależności od wybranego wariantu. Dodatkowo wyświetlacz wymaga podania napięcia zasilającego oraz napięcia sterującego kontrastem wyświetlacza. Interfejs komunikacyjny HD44780 Komunikacja ze sterownikiem HD44780 odbywa się za pomocą dwukierunkowego interfejsu komunikacyjnego o poziomach TTL. ● D0-D7 – dwukierunkowa magistrala danych; w przypadku pracy 8bitowej wykorzystywane są wszystkie sygnały, dla 4-bitowej starszy półbajt (D4-D7); ● RS (Register Select) – sygnał wyboru odbiorcy przesyłanych danych: gdy RS = 1 komunikacja odbywa się z rejestrem danych sterownika, dla RS = 0 zapisywane dane trafiają do rejestru konfiguracyjnego sterownika, odczyt następuje z rejestru stanu sterownika; ● R/W (Read/Write) – sygnał wyboru kierunku transmisji danych; dla R/W = 1 dane są odczytywane z wyświetlacza, gdy R/W = 0 dane są przesyłane do wyświetlacza; ● E (Enable) – sygnał strobujący magistrali danych; wartość E = 1 oznacza, że na magistrali danych są dane gotowe do odebrania. Podłączenie najprostsze ● ● ● ● Do poprawnej pracy wystarczy 6 linii: D4-D7 (interfejs 4-bitowy), RS oraz E. Sygnał R/W jest w takim przypadku na stałe podłączony do logicznego „0”, co oznacza, że można będzie wyłącznie wysyłać dane do sterownika wyświetlacza. W takiej konfiguracji nie jest możliwe odczytywanie danych z wyświetlacza, w tym m.in. sprawdzenie, czy wyświetlacz jest gotowy do przyjmowania kolejnych danych. Dlatego wszystkie operacje na wyświetlaczu wymagają opóźnień zgodnych z informacjami zawartymi w dokumentacji sterownika wyświetlacza. Schemat podłączenia 4-bitowa magistrala danych ●2 sygnały sterujące E i RS ●Podłączenie do portu B ● Pamięci sterownika ● Sterownik HD44780 posiada trzy rodzaje pamięci: DDRAM, CGRAM i CGROM. ● ● ● Pamięć DDRAM (ang. Display Data RAM) służy do przechowywania kodów znaków wyświetlanych na wyświetlaczu. Pamięć CGRAM (ang. Character Generator RAM) przechowuje wzorce znaków definiowanych przez użytkownika. Pamięć CGROM (ang. Character Generator ROM) przechowuje wzorce znaków wyświetlanych na wyświetlaczu (208 znaków w rozmiarze 5x8 pikseli oraz 32 znaki w rozmiarze 5x10 pikseli). DDRAM ● ● Pamięć DDRAM ma rozmiar 80 bajtów. Sposób odwzorowania pamięci DDRAM na znaki wyświetlane na wyświetlaczu zależy od kilku czynników: ● pierwszym z nich jest liczba wyświetlanych wierszy (1 lub 2), ● drugim – przesunięcie wyświetlania uzyskane za pomocą komendy „Cursor/Display Shift” lub podczas wpisywania danych przy ustawionym bicie S w komendzie „Entry Mode Set” DDRAM dla konfiguracji jednowierszowej ● ● ● W przypadku braku przesunięcia (rys. a) na ekranie zostaną wyświetlone znaki zapisane w komórkach o adresach od 00h do 0Fh. Przesunięcie o jeden znak w prawo (rys. b) spowoduje, że na ekranie zostaną wyświetlone znaki zapisane w komórkach o adresach od 01h do 10h. Natomiast przesunięcie o jeden znak w lewo (rys. c) spowoduje, iż na ekranie zostanie wyświetlony znak zapisany w komórce o adresie 4Fh, a następnie znaki spod adresów od 00h do 0Eh. DDRAM dla konfiguracji dwuwierszowej ● ● ● W przypadku braku przesunięcia (rys. a) na ekranie w pierwszym wierszu zostaną wyświetlone znaki zapisane w komórkach o adresach od 00h do 0Fh, natomiast w drugim wierszu znaki z komórek o adresach od 40h do 4Fh. Przesunięcie o jeden znak w prawo (rys. b) spowoduje, że na ekranie w pierwszym wierszu zostaną wyświetlone znaki zapisane w komórkach o adresach od 01h do 10h, a w drugim wierszu znaki z komórek o adresach od 41h do 50h. Przesunięcie o jeden znak w lewo (rys. c) spowoduje, iż w pierwszym wierszu zostanie wyświetlony znak zapisany w komórce o adresie 27h, a następnie znaki spod adresów od 00h do 0Eh, zaś w drugim wierszu znak spod adresu 67h, a dalej znaki spod adresów od 40h do 4Eh. Pamięć CGRAM Pamięć CGRAM posiada rozmiar 64 bajtów, które pozwalają na przechowywanie wzorców do ośmiu znaków o rozmiarze 5x8 pikseli lub 4 znaków o rozmiarze 5x10 pikseli. Znaki zdefiniowane przez użytkownika można wyświetlać używając kodów od 0 do 7 (5x8) lub od 0 do 3 (5x10) wysyłanych do pamięci DDRAM. Kod znaku binarnie Adresy CGRAM(bity adresu) dziesiętnie Wiersz wzorca znaku 543 210 000 0 000 000 000 ... 000 000 000 001 010 ... 110 111 0 1 2 … 6 7 001 1 001 001 001 … 001 001 000 001 010 ... 110 111 0 1 2 … 6 7 ... ... ... ... ... adres komórki pamięci CGRAM jest podzielony na dwie części: numer kodu znaku (bity [5..3]) oraz wiersz wzorca znaku (bity [2..0]). Utworzenie nowego znaku o kodzie np. 4 wymaga zapisania wzorca do pamięci CGRAM pod adresy od 32 do 39 (od 100000b do 100111b) Komendy sterujące Sterownik HD44780 posiada 8 komend sterujących. Identyfikacja komendy odbywa się poprzez ustalenie pozycji najstarszej jedynki w kodzie komendy. Wiele komend posiada dodatkowe parametry, które dołączane są do komendy na bitach młodszych, niż bit identyfikujący komendę. Opis komend 1. Komenda „Entry Mode Set”: – I/D – wybór kierunku zmian adresów po wpisaniu danych do pamięci: dla I/D = 1 następuje zwiększanie, natomiast dla I/D = 0 zmniejszanie adresów; – S – włączanie (dla S = 1) lub wyłączanie (dla S = 0) przesuwania wyświetlacza po wpisaniu danych do pamięci. 2. Komenda „Display on/off”: – D – włączanie (dla D = 1) lub wyłączanie (dla D = 0) wyświetlacza; – C – włączanie (dla C = 1) lub wyłączanie (dla C = 0) widoczności kursora; – B – włączanie (dla B = 1) lub wyłączanie (dla B = 0) migotania znaku na pozycji kursora; 3. Komenda „Cursor/Display Shift”: – S/C – wybór obiektu, którego będzie dotyczyło przesuwanie: dla S/C = 1 wykonane zostanie przesunięcie wyświetlacza, natomiast dla S/C = 0 nastąpi przesunięcie kursora; – R/L – wybór kierunku przesuwania: dla R/L = 1 przesuwanie odbędzie się w prawo, natomiast dla R/L = 0 przesuwanie odbędzie się w lewo; Opis komend 4. Komenda „Function Set”: – DL – wybór szerokości magistrali danych używanej do komunikacji ze sterownikiem; dla DL = 1 magistrala ma szerokość 8 bitów; dla DL = 0 magistrala ma szerokość 4 bitów (transfer danych odbywa się w dwóch cyklach); – N – wyświetlanie jednego (0) lub dwóch (1) wierszy; – F – 8 (0) lub 10 (1) linii wyświetlanego znaku. 5. Komenda Display Clear (kod 0x01) powoduje wyczyszczenie wyświetlacza (cała pamięć DDRAM jest wypełniana kodem spacji – 0x20), powrót kursora pod adres 0x00 oraz przywraca wyświetlanie od adresu 0x00 (likwiduje przesunięcie realizowane komendą Display Shift). 6. Komenda Return Home (kod 0x02) powoduje powrót kursora pod adres 0x00 oraz przywraca wyświetlanie od adresu 0x00 (likwiduje przesunięcie realizowane komendą Display Shift). Opis komend 7. Komenda Set CGRAM (kod 0x40) służy do ustawiania adresu pamięci CGRAM, pod który będą zapisywane dane. Po wykonaniu tej komendy każdorazowe wysłanie danej do wyświetlacza powoduje zapisanie jej w pamięci CGRAM. Po zapisaniu danej adres jest zwiększany lub zmniejszany w zależności od ostatnio ustawionej wartości bitu I/D komendy Entry Mode Set. Aby móc wpisywać dane do pamięci DDRAM należy wykonać komendę „Set DDRAM”. 8. Komenda Set DDRAM (kod 0x80) służy do ustawiania adresu pamięci DDRAM, pod który będą zapisywane dane. Pozwala ona na umieszczanie tekstu w dowolnym miejscu wyświetlacza. Wysyłanie danych – interfejs 8-bitowy ● ● ● ● ustawienie zera logicznego na linii R/W; w przypadku, gdy korzysta się z uproszczonej wersji interfejsu linia ta jest zwarta do masy na stałe; ustawienie odpowiedniej wartości na linii RS; ustawienie właściwej wartości na liniach danych; ustawienie na linii E logicznej jedynki, a następnie logicznego zera; ● czas trwania logicznej jedynki i logicznego zera należy odczytać z dokumentacji sterownika (typowo jest to 0,5 μs dla każdego z poziomów logicznych). Wysyłanie danych – interfejs 4-bitowy ● ● ● ● ● ● ustawienie zera logicznego na linii R/W; w przypadku, gdy korzysta się z uproszczonej wersji interfejsu linia ta jest zwarta do masy na stałe; ustawienie odpowiedniej wartości na linii RS; ustawienie na liniach danych wartości starszych czterech bitów wartości, która ma być wysłana do sterownika; ustawienie na linii E logicznej jedynki, a następnie logicznego zera; ustawienie na liniach danych wartości młodszych czterech bitów wartości, która ma być wysłana do sterownika; ustawienie na linii E logicznej jedynki, a następnie logicznego zera; ● czas trwania logicznej jedynki i logicznego zera na linii E podczas wysyłania starszego i młodszego półbajtu należy odczytać z dokumentacji sterownika (typowo jest to 0,5 μs dla każdego z poziomów logicznych). Odczytywanie wartości z rejestru sterownika odbywa się analogicznie, z tym, że wartość na linii R/W jest równa logicznej jedynce, a dane są odczytywane z linii danych. W przypadku uproszczonej wersji interfejsu, gdy linia ta jest zwarta do masy, nie ma możliwości odczytywania danych ze sterownika. Wysyłanie danych (4-bit) przykład LCD_SEND MACRO RS_VAL movf LCD_data, W ; pobierz daną do wysłania andlw 0xF0 ; tylko 4 najstarsze bity iorlw RS_VAL ; ustaw odpowiednio bity RS i E movwf PORTB ; wrzuć na port swapf LCD_data, W ; ponownie pobierz daną do wysłania andlw 0xF0 ; tylko 4 najmłodsze bity bcf PORTB, RB3 ; stan niski na linii E nop ; odczekaj jeden cykl iorlw RS_VAL ; ustaw odpowiednio bity RS i E movwf PORTB ; wrzuć na port goto$+1 ; poczekaj 2 cykle bcf PORTB, RB3 ; stan niski na linii E ENDM Inicjalizacja wyświetlacza Po włączeniu zasilania sterownik wyświetlacza wykonuje procedurę inicjalizacji, po której jest gotowy do pracy. Wewnętrzna procedura inicjalizacji wykonuje następujące operacje: 1. Kasowanie ekranu (wyczyszczenie zawartości pamięci DDRAM). 2. Ustawienie funkcji: interfejs 8-bitowy, wyświetlanie w jednym wierszu, znaki 5x8. 3. Ustawienie trybu pracy: wyświetlacz wyłączony, kursor wyłączony, migotanie wyłączone. 4. Wyłączenie przesuwania, włączenie inkrementacji. W przypadku, gdy powyższe warunki nie odpowiadają wymaganiom (np. używany jest interfejs 4-bitowy), należy przeprowadzić programową procedurę inicjalizacji. Programowa inicjalizacja w trybie 4-bitowym – – – – – – – – – – – – – – – – – odczekanie min. 15 ms; wysłanie komendy „Function Set” dla 8-bitowego interfejsu; odczekanie min. 4.1 ms; ponowne wysłanie komendy „Function Set” dla 8-bitowego interfejsu; odczekanie min. 100 μs; ponowne wysłanie komendy „Function Set” dla 8-bitowego interfejsu; odczekanie min. 40 μs; wysłanie komendy „Function Set” dla 4-bitowego interfejsu; w tym miejscu interfejs jest nadal 8-bitowy, więc wysyłany jest tylko starszy półbajt; odczekanie min. 40 μs; wysłanie komendy „Function Set” dla 4-bitowego interfejsu z jednoczesnym ustawieniem liczby wierszy i fontu; odczekanie min. 40 μs; wysłanie komendy „Display Off”; odczekanie min. 40 μs; wysłanie komendy „Display Clear”; odczekanie min. 40 μs; wysłanie komendy „Entry Mode Set” z odpowiednimi parametrami; odczekanie min. 40 μs. Klawiatura matrycowa ● ● Zwiększanie liczby przycisków wymaga zwiększenia liczby wyprowadzeń mikrokontrolera zajętych przez dołączone przyciski. Sytuacja taka powoduje znaczne zredukowanie liczby wyprowadzeń, które pozostają do wykorzystania przez inne układ Zwiększanie liczby przycisków ● ● ● ● ● ● ● Załóżmy, że system wymaga podłączenia 4 przycisków. Można to zrealizować przez dołączenie kolejnych przycisków do kolejnych wyprowadzeń mikrokontrolera. Następnie chcemy zwiększyć liczbę przycisków o kolejne 4. Gdyby podłączyć jest do tych samych wyprowadzeń, co poprzednie przyciski, nie mielibyśmy możliwości rozróżnienia, który przycisk został wciśnięty. Można to jednak zrobić dodając dwa dodatkowe sygnały służące do aktywacji odczytu jednego z dwóch zestawów przycisków. Jeśli teraz dodamy jeszcze dwa zestawy po 4 przyciski każdy to uzyskamy układ 16 klawiszy, który może być odczytywany za pomocą 8 (zamiast 16) linii mikrokontrolera ● 4 linie na aktywację każdego z zestawów oraz ● 4 linie do odczytu stanu przycisku w aktywnym zestawie. Układ taki nazywany jest klawiaturą matrycową Klawiatura matrycowa ● ● Każda kolumna wymaga oddzielnego cyklu odczytu. Po podaniu logicznego zera na wyjście podłączone do odczytywanej kolumny, na wyprowadzeniu podłączonym do wciśniętego przycisku pojawi się zero, natomiast gdy przycisk nie jest wciśnięty – jedynka