Programowanie mikroprocesorów ( mikrokontrolerów )

Uruchomienie wyświetlacza HD44780


1. Wstęp

Poniżej przedstawiony zostanie sposób uruchomienia wyświetlacza HD44780. W kolejnych etapach przedstawiane będą części programu składające się na pełną obsługę wyświetlacza HD44780. Przedstawione przezemnie rozwiązanie nie wykorzystuje gotowych bibliotek które można znaleźć w internecie lecz pozwala napisać od podstaw program obsługi wyświetlacza HD44780 dzięki czemu można przybliżyć sobie jego zasadę działania oraz dostosować program jego obsługi do swoich indywidualnych wymagań. W poniższym programie przedstawione są jedynie podstawowe funkcje takiego wyświetlacza. Żeby w pełni wykorzystać jego mozliwości należy zaczerpnąć informacji o możliwościach konfiguracji wyświetlacza HD44780. Ja wykorzystałem jedną z możliwych konfigurację (bez widocznego migającego kursora, treść dodawana addytywnie). W miarę możliwości można dodać kilka komend np zapalających i gaszących kursor lub zmienić sposób w jaki tekst będzie wyświetlany. Ja jednak ogranicze się do przedstawienia najprostrzego sposobu jak można uruchomić taki wyświetlacz w konfiguracji której sam używam w swoich aplikacjach.

2. Przygotowanie

Uruchomienie wyświetlacz HD44780
  1. //  Załączniki
  2. // Include
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5.  
  6. //  Definicje
  7. #define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  8. #define sbi(sfr,bit) ((_SFR_BYTE(sfr) |= _BV(bit)))
  9. #define lcd_ster PORTD
  10. #define lcd_data PORTD
  11. #define ddr_lcd_ster DDRD
  12. #define ddr_lcd_data DDRD
  13. #define pin_lcd PIND
  14. #define e 4
  15. #define rs 6
  16. #define rw 7
  17. #define rs_0 cbi(lcd_ster,rs)
  18. #define rs_1 sbi(lcd_ster,rs)
  19. #define rw_0 cbi(lcd_ster,rw)
  20. #define rw_1 sbi(lcd_ster,rw)
  21. #define e_0 cbi(lcd_ster,e)
  22. #define e_1 sbi(lcd_ster,e)
  23. #define LCD_czysc LCD_wyslij(0x01,0)

W pierwszym etapie przygotujemy sobie biblioteki z których będziemy korzystać pisząc program obsługi wyświetlacza HD44780. W sekcji Include linijki (1) i (2) załączone zostały kolejno biblioteki obsługi mikrokontrolera (avr/io.h) oraz biblioteka umożliwiająca korzystanie z funkcji opóźniających delay (util/delay.h). W dalszej części zdefiniowane zostały przezwania pewnych operacji ułatwiające późniejsze pisanie programu i poprawienie przejrzystości programu obsługi wyświetlacza HD44780. Sekcje tą można pominąć i wówczas zamiast przezwań zawartych w programie należy wstawić zamiast nich odpowiednie wartości komend czy portów. W linijkach (7) i (8) zdefiniowane zostają przezwania dla komend kasowania i ustawiania bitu opisane o dziale Programowanie -> Sterowanie portami. Kolejne linijki pełnią następujące funkcje:

  • (9) przezywa port na jakim porcie podpięte zostały linie sterujące wyświetlaczem (Enable - E nóżka 6 wyświetlacza HD44780, Register Select - RS nóżka 4 wyświetlacza HD44780, Read Write - RW nóżka 5 wyświetlacza HD44780) nazwą lcd_ster
  • (10) przezywa port na jakim porcie podpięte zostały linie danych wyświetlacza HD44780 (DB0-7 nóżki od 7 do 14) nazwą lcd_data
  • (11) przezywa rejestr kierunku portu dla lini sterujących wyświetlacza HD44780 nazwą ddr_lcd_ster
  • (12) przezywa rejestr kierunku portu dla lini danych wyświetlacza HD44780 nazwą ddr_lcd_data
  • (13) przezywa rejestr PIN nazwą pin_lcd (przydatne to będzie tylko raz w przypadku odczytywania wartości jednego konkretnego pinu podczas sprawdzania stanu bitu zajętości wyświetlacza HD44780
  • (14) przezywa numer pinu portu na którym podpięty jest sygnał Enable nazwą e
  • (15) przezywa numer pinu portu na którym podpięty jest sygnał Register Select nazwą rs
  • (16) przezywa numer pinu portu na którym podpięty jest sygnał Read Write nazwą rw
  • (17) przezywa komendę zerującą bit cbi(lcd_ster,rs) nazwą rs_0 (zauważyć należy że od tej linijki dalej funkcje zawarte w przezwaniach korzystają już z poprzednio zdefiniowanych przezwań cbi(lcd_ster,rs) tzn. są ich złożeniem)
  • (18) przezywa komendę zerującą bit sbi(lcd_ster,rs) nazwą rs_1
  • (19) przezywa komendę zerującą bit cbi(lcd_ster,rw) nazwą rw_0
  • (20) przezywa komendę zerującą bit sbi(lcd_ster,rw) nazwą rw_1
  • (21) przezywa komendę zerującą bit cbi(lcd_ster,e) nazwą e_0
  • (22) przezywa komendę zerującą bit sbi(lcd_ster,e) nazwą e_1
  • (23) przezywa komendę zerującą wyświetlacz nazwą LCD_czysc

W dalszej części programu będziemy wykorzystywać powyższe przezwania dzięki czemu program obsługi wyświetlacza HD44780 stanie się czytelniejszy

3. Inicjalizacja wyświetlacza HD44780

Uruchomienie wyświetlacz HD44780
  1. // inicjowanie LCD w trybie 4 bitowym
  2. void LCD_init(void)
  3. {
  4.         _delay_ms(50);
  5.         unsigned char i;
  6.         ddr_lcd_ster=0xff;
  7.         ddr_lcd_data=0xff;
  8.         rw_0;
  9.         rs_0;
  10.         _delay_ms(10);
  11.         for (i=1;i<3;i++)       // trzykrotne wysłanie 3-
  12.         {
  13.                 e_1;
  14.                 lcd_data=(lcd_data&0xf0)|0x03;  //wysłanie 3- do LCD
  15.                 _delay_ms(1);
  16.                 e_0;
  17.                 _delay_ms(1);
  18.         }
  19.         e_1;
  20.         lcd_data=(lcd_data&0xf0)|0x02;  // wysłanie 2- do LCD
  21.         _delay_ms(1);                   // od tego momentu sprawdzamy gotowosc LCD
  22.         e_0;
  23.         LCD_wyslij(0x28,0);             // interfejs 4 bitowy, 2 linie
  24.         LCD_wyslij(0x08,0);             //wyłącz LCD, wyłącz kursor, wyłącz mruganie 00001000
  25.         LCD_wyslij(0x01,0);             //czysc LCD
  26.         LCD_wyslij(0x06,0);             //zwiekszanie pozycji kursora po każdy  znaku
  27.         LCD_wyslij(0x0c,0);             //wlacz wyswietlacz bez kursora
  28.         _delay_ms(1);
  29. }

Aby poprawnie zainicjować wyświetlacz HD44780 należy w pierwszym kroku odczekać minimum 40ms po uruchomieniu układu aby napięcie zasilające osiągnęło wymagany poziom.  W moim programie (4) odczekujemy 50ms i wartość ta w zupełności wystarcza do poprawnego zainicjowania wyświetlacza HD44780. W kolejnych linijkach  (5) deklarujemy zmienną pomocniczą i oraz przygotowujemy porty sterujący (6) oraz port danych (7) ustawiając je jako porty wyjściowe. Następnie ustawiamy sygnał sterujący RW na zero (8) co oznacza ustawienie tego sygnału sterującego na zapis danych do wyświetlacza HD44780 oraz sygnału RS na zero co oznacza że wysyłane będą rozkazy konfiguracyjne do wyświetlacza HD44780. Odczekujemy 10ms (9) i przechodzimy do wysłania do wyświetlacza HD44780 trzykrotnie wartości 3 wykorzystując pętlę for (10). Wartość 3 wynika z dokumentacji wyświetlacza HD44780 oraz ze sposobu podłączenia go do mikrokontrolera. W naszym przypadku jak wynika ze schematu inicjalizacji czterobitowej przedstawionej w dziale peryferia do wyświetlacza należy wysłać trzykrotnie sygnał RS = 0, RW=0 oraz DB7=0 DB6=0 DB5=1 i DB4=1 co przy naszym podłączeniu skutkuje ustawieniem linii sterujących na odpowiednie wartości i wartości dwóch najmłodszych bitów na jedynki bez zmiany wartości czterech starszych bitów portu (14) wykorzystując odpowiednią operację bitową. Wartość 3 wynika stąd że dwa najmłodsze bity są jedynkami a reszta zerami. W linii (13) ustawiony został sygnał strobujący na 1. Po  wystawieniu odpowiednich wartości na porty (14) i odczekaniu 1ms (15) opadającym zboczem sygnału strobującego E (16) wysyłamy dane do wyświetlacza HD44780. Dokumentacja wymaga aby takie dane zostały wysłane trzykrotnie bez sprawdzania flagi zajętości co gwarantuje nam pętla FOR (11). Po wysłaniu trzykrotnie odpowiedniego rozkazu do wyświetlacza przechodzimy do kolejnego punktu. Do wyświetlacza w analogiczny sposób jak przed chwilą wysyłamy wartość 2 linia (20) wcześniej przygotowując sobie sygnał strobujący E ustawiając go na 1 (19) .  Wysyłamy rozkaz zmieniając stan sygnału E na zero. Od tego momentu możemy sprawdzać flagę zajętości wystawianą przez wyświetlacz LCD funkcją LCD_busy opisaną w kolejnym punkcie a wykorzystywaną w funkcji LCD_wyslij wysyłającą znak lub rozkaz do wyświetlacza LCD również opisaną w punktach poniżej. Kolejne kroki i wartości wysyłanych danych wynikać będą z wybranie takiej a nie innej konfiguracji wyświetlacza dane te można dobrać w dowolny inny sposób opisany przez dokumentacje wyświetlacza lub w dziale peryferia wyświetlacz HD44780 dopasowując sposób działania wyświetlacza do swoich upodobań. Ja wybrałem następującą konfiguracje wyświetlacza. Przy użyciu funkcji LCD_wyslij wysyłam kolejno zmienne konfiguracyjne do wyświetlacza HD44780. W lini (23) wysłana zostaje do wyświetlacza HD44780  wartość komendy konfiguracyjnej 0x28 oznaczającej pracę wyświetlacza HD44780 jako tryb 4bitowy wyświetlanie w dwóch liniach wyświetlacza. Linia (24) wysłana zostaje do wyświetlacza HD44780  komenda 0x08 (wyłącz wyświetlanie, wyłącz widoczność kursora, wyłącz miganie kursora). W linii (25) wysłana zostaje do wyświetlacza HD44780  wartość 0x01 jest to komenda czyszcząca wyświetlaną aktualnie zawartość wyświetlacza HD44780. (26) wysłana zostaje do wyświetlacza HD44780  wartość 0x06 określająca zwiększanie się pozycji kursora przy wysyłaniu każdego kolejnego znaku ( efekt na wyświetlaczu jest taki jak by się pisało tekst w wordzie – znaki pojawiają się na kolejnych pozycjach wyświetlacza HD44780). (27) wysłana zostaje do wyświetlacza HD44780  wartość 0x0c załącza ona wyświetlacz z wcześniej wprowadzonymi parametrami konfiguracyjnymi. (28) opóźnienie czasowe 1ms. W ten sposób zainicjalizowany wyświetlacz HD44780 gotowy jest do dalszej pracy.

4. Funkcja sprawdzania flagi zajętości wyświetlacza HD44780

Uruchomienie wyświetlacz HD44780
  1. // bussy flag check
  2. unsigned char LCD_busy(void)
  3. {
  4.         unsigned char flaga;    //zmienna pomocnicza
  5.         rs_0 ;
  6.         rw_1 ;
  7.         ddr_lcd_data=ddr_lcd_data&0b11110111;
  8.         e_1;
  9.         _delay_us(1); // aaaa
  10.         flaga=pin_lcd&0x08;
  11.         e_0;
  12.         e_1;
  13.         _delay_us(1); // aaaa
  14.         e_0;
  15.         ddr_lcd_data=ddr_lcd_data|0b00001000;
  16.         _delay_us(1); // aaaa
  17.         return flaga;
  18. }

Funkcja LCD_busy realizuje funkcję sprawdzenia flagi zajętości wyświetlacza HD44780 i wykorzystywana jest przy wysyłaniu znaków do wyświetlacza w funkcji LCD_wyslij. (4) Deklarujemy zmienną pomocniczą „flaga” która będzie zmienną przyjmującą wartość 1 lub 0 w zależności od stanu bitu zajętości wyświetlacza HD4470. Ustawiamy linie (5) RS na 0 i (6) RW na 1 w celu przygotowania wyświetlacza HD44780 do odbierania danych z linii DB7 na której zostaje wystawiany bit zajętości wyświetlacza HD44780. (7) Ustawiamy kierunek jednego bitu na wejściowy wygląd tej linijki będzie zależał od projektu naszego układu !!! W tym wypadku dane wyświetlacza DB4-DB7 podpięte są do młodszej części portu a więc bit DB7 przypada na 4 nóżkę portu więc w linii tej przestawiany na wejściowy jest 4 bit portu w przypadku innego podpięcia np. jako starszą część portu wówczas zero wystąpi na ostatniej pozycji (0x011111111). (8) Przygotowanie sygnału E ustawiając go na 1 do odczytu flagi zajętości wyświetlacza HD44780. (9) Opóźnienie czasowe 1us. (10) Przypisanie zmiennej flaga wartości bitu do którego podpięty jest pin odpowiedzialny za flagę zajętości wyświetlacza HD44780 wykorzystując odpowiednią operację bitową. (11) Ustawienie sygnału E na zero odczytanie starszej cześci bitowej zakończone. (12) Przygotowanie sygnału E na odczytanie młodszej częsci bajtu dla nas w tej chwili bezużytecznego. (13) Opóźnienie czasowe 1us. (14) Ustawienie E na zero zakańczając odczyt młodszej częsci bajtu. (15) Ustawienie pinu jako wyjściowy żeby powrócić ze stanem do punktu wyjścia (do stanu sprzed wywołania funkcji LCD_busy). (16) Opóźnienie czasowe 1us. (17) Zwrócenie wartości flagi jako wartości wyjściowej funkcji LCD_busy.

5. Wysłanie pojedynczego znaku lub rozkazu do LCD HD44780

Uruchomienie wyświetlacz HD44780
  1. // wyslanie znaku lub komendy do LCD
  2. void LCD_wyslij(unsigned char dana,char litera)
  3. {
  4.         while(LCD_busy());      // oczekiwanie na zwolienie wyswietlacza
  5.         rw_0;
  6.         if (litera==0)
  7.         {
  8.                 rs_0;
  9.         }
  10.         else
  11.         {
  12.                 rs_1;
  13.         }
  14.         e_1;
  15.         lcd_data=(lcd_data&0xF0)|((dana&0xf0)>>4);      // przygotuj starszy bajt do LCD
  16.         _delay_us(2); // aaaa   _delay_ms(5);
  17.         e_0;
  18.         _delay_us(2); // aaaa   _delay_ms(5);
  19.         e_1;
  20.         lcd_data=(lcd_data&0xF0)|(dana&0x0f);   // przygotuj młodszy bajt do LCD
  21.         _delay_us(2); // aaaa   _delay_ms(5);
  22.         e_0;
  23.         _delay_us(2); // aaaa   _delay_ms(10);
  24. }

Funkcja LCD_wyslij wysyła dane i komendy do wyświetlacza HD44780. Funkcja ta ma dwa parametry oddzielone przecinkiem znajdujące się w nawiasie. Jednym z nich jest „dana” a drugim z nich jest „litera”. Może i nazewnictwo zmiennych zostało niefortunnie dobrane ale postaram się wyjaśnić co i jak. Zmienna „dana” jest to zmienna którą chcemy wysłać do wyświetlacza linią danych, natomiast zmienna „litera” definiuje czy wysyłana zmienna jest znakiem który ma się wyświetlić na wyświetlaczu czy jest komendą (rozkazem) konfigurującym wyświetlacz HD44780. Ponieważ funkcja LCD_tekst wykorzystuje LCD_wyslij w sposób cykliczny przy wysyłaniu znaków do wyświetlacza HD44780 w (4) linijce znalazło się wywołanie funkcji sprawdzenia flagi zajętości wyświetlacza HD44780 przed dalszą procedurą wysyłania czegokolwiek do wyświetlacza HD44780. Jeśli flaga zajętości jest aktywna (równa 1) wówczas program zapętla się w tej linijce aż do momentu gdy warunek zostanie złamany i flaga zmieni się na 0. Wówczas wyświetlacz HD44780 gotowy jest na przyjęcie kolejnego znaku. W linijce (5) ustawiamy wartość linii RW na zero gdyż będziemy zapisywać dane do wyświetlacza HD44780. (6) Przygotowujemy sobie sygnał zapisujący zmienne w wyświetlaczu HD44780 ustawiając sygnał E na 1. W linii (6) następuje sprawdzenie warunku czy zmienna „litera” równa jest zero jeśli jest linia RS ustawiona zostaje na 0 (7) i wyświetlacz HD44780 przygotowany jest do odczytu komendy. Natomiast gdy zmienna litera jest różna od zera (10) np. wynosi 1 wówczas zmienna RS ustawiana jest na 1 (12) i wyświetlacz HD44780 przygotowany jest na przyjmowanie znaków do wyświetlenia na ekranie ciekłokrystalicznym. (14) Przygotowujemy sobie sygnał zapisujący zmienne w wyświetlaczu HD44780 ustawiając sygnał E na 1. Uwaga!!! W linii (15) zostają przygotowane dane do wysłania na port do którego podpięty jest wyświetlacz HD44780. Wygląd tych linijek może różnić się w zależności od filozofii podpięcia linii danych wyświetlacza do mikrokontrolera. Jeśli dane DB4-DB7 podpięte są jako młodsze bity czyli do nóżek PX0-PX4 to program będzie wyglądał jak w tym przypadku jeśli natomiast podpięte są do starszej częśći portu PX5-PX7 wówczas linijka ta musi zostać zmodyfikowana. Postaram się opisać sposób modyfikacji dla tych dwóch przypadków na końcu artykułu. W linijce tej (15) przygotowana zostaje starsza część bajtu do wysłania. (lcd_data&0xF0) zeruje cztery młodsze bity portu do którego podpięty jest LCD nei zmieniając wartości starszych natomiast w tej operacji bitowej ((dana&0xf0)>>4); zerowane są 4 młodsze bity zmiennej i cała zmienna jest przesuwana o 4 bity w prawo co daje w efekcie że 4 starsze bity przesuwają się na miejsce młodszych i operatorem | wpisywane są na 4 młodsze bity portu wyświetlacza HD44780. Następnie po opóźnieniu czasowym (16) w linni (17) sygnał E zostaje wyzerowany wysyłając dane do wyświetlacza HD44780. Po opóźnieniu czasowym (18) przygotowany zostaje sygnał E na 1 (19) w linii (20)  przygotowane zostają cztery młodsze bity do wysłania i po opóźnieniu czasowym (21) wysłane zostają do wyświetlacza HD44780 (22). Po opóźnieniu czasowym (23) jeden pełen znak 8 bitowy jest wysłany do wyświetlacza HD44780 i funkcja kończy się. Opóźnienia czasowe wykorzystywane w funkcjach nie są wymagane, powstały w czasie testów i przy niektórych wyświetlaczach wolałem pozostawić je ze względu na dziwne zachowania niektórych modeli wyświetlaczy przy zbyt szybkim wysyłaniu do nich kolejnych danych.

6. Wgranie polskich znaków do pamięci LCD HD44780

Uruchomienie wyświetlacz HD44780
  1. // wgranie polskich znaków do LCD
  2. void LCD_polskie_znaki(unsigned char dana)
  3. {
  4.         while(LCD_busy());      // oczekiwanie na zwolienie wyswietlacza
  5.         rs_1;
  6.         rw_0;
  7.         e_1;
  8.         lcd_data=(lcd_data&0xF0)|((dana&0xf0)>>4);      // przygotuj starszy bajt do LCD
  9.         _delay_us(1); // aaaa
  10.         e_0;
  11.         _delay_us(1); // aaaa
  12.         e_1;
  13.         lcd_data=(lcd_data&0xF0)|(dana&0x0f);   // przygotuj młodszy bajt do LCD
  14.         _delay_us(2);
  15.         e_0;
  16.         _delay_us(1); // aaaa
  17. }
  18.  
  19. void LCD_znakipl_load(void)
  20. {
  21.         LCD_wyslij(0x40,0);
  22.         unsigned char znaki[]={ 0,0,14,1,15,17,15,2,            // ą
  23.                                                 2,4,14,16,16,17,14,0,           // ć
  24.                                                 0,0,14,17,31,16,14,2,           // ę
  25.                                                 12,4,6,4,12,4,14,0,             // ł
  26.                                                 2,4,22,25,17,17,17,0,           // ń
  27.                                                 2,4,14,17,17,17,14,0,           // ó
  28.                                                 2,4,14,16,14,1,30,0,            // ś
  29.                                                 2,4,31,2,4,8,31,0};                     // ż
  30.         unsigned char znak;
  31.         for (unsigned char i=0;i<64;i++)
  32.         {
  33.                 znak=znaki[i];
  34.                 LCD_polskie_znaki(znak);
  35.         }
  36.         _delay_us(1); // aaaa
  37. }

Wczytywanie polskich znaków do pamięci wyświetlacza HD44780 odbywa się w dwóch etapach. Pierwszym z nich jest LCD_polskie_znaki jest to nieznacznie zmodyfikowany program wysyłania znaku do wyświetlacza0 HD447 LCD_wyslij. W zasadzie jest on zbędny gdyż można by odpowiednio sparametryzować funkcję LCD_wyslij i zaoszczędzić kilka linijek kodu, nie mniej jednak ja postanowiłem napisać sobie osobną funkcję przeznaczoną do tego celu w celu większej przejrzystości działania programu. Pierwszym elementem jest funkcja LCD_polskie_znaki działająca analogicznie do funkcji LCD_wyslij z tą różnicą że wysyła ona jedynie komendy do wyświetlacza HD44780 w wyniku czego pozbyliśmy się parametru „litera”. Drugą częścią realizującą wgranie polskich znaków do wyświetlacza HD44780 jest LCD_znakipl_load. Na początku tej funkcji sprawdzona zostaje flaga zajętości (21) wyświetlacza HD44780. W linii (22) zdefiniowana zostaje tablica znaków „znaki[]” w tablicy tej zdefiniowane zostają wszystkie znaki polskojęzyczne (22-29). W linii (30) zdefiniowana zostaje zmienna pomocnicza „znak” do której zaczytywane będą kolejno znaki z tablicy „znaki[]” i wysyłane pojedynczo do wyświetlacza HD44780. Do wysyłania wszystkich znaków służy pętla for (31) jest to 8 znaków po 8 bajtów co daje 64 przejścia przez pętlę. W linii (33) pobierana jest pierwsza zmienna z tblicy „znaki[]” i przekazywana do wysłania do funkcji wysyłającej znak do wyświetlacza HD44780 (34). Każdy znak składa się z 8 bajtów danych. Sposób tworzenia znaków można znaleźćw opisie wyświetlacza HD44780 w dziale peryferia. Po przejścu 64 razy przez pętle i wysłaniu wszystkich znaków do wyświetlacza funkcja przechodzi do opóźnienia czasowego (36) i zostaje zakończona.

7. Funkcja wypisująca zadany tekst na LCD HD44780

Uruchomienie wyświetlacz HD44780
  1. //pisze tekst na LCD
  2. void LCD_tekst(char *tekst)
  3. {
  4.         unsigned char i=0;
  5.         while (tekst[i]) LCD_wyslij(tekst[i++],1);
  6.         _delay_us(10);
  7. }

Funkcja LCD_tekst służy do pisania całych tekstów na wyświetlaczu HD44780. W linii (4) zdefiniowana zostaje zmienna pomocnicza i potrzebna do iteracji kolejnych wysyłanych znaków. Funkcja ta posiada daną wejściową jaką jest wpisywany tekst. Tekst ten jest traktowany jako tablica znaków tekst[]. W linni (5) mamy funkcję while która wczytuje znak po znaku z tabeli tekst[] do momentu aż napotka brak danych w tabeli. Wczytywane dane z tabeli są wysyłane jedno po drugim przez funkcję LCD_wyslij. W tej samej linii. Co wejście w pętle zmienna i jest inkrementowana i zostaje wysłany kolejny znak. W linii (6) mamy opóźnienie czasowe 10us po czym funkcja kończy się.

8. Funckja ustawiająca kursor w wybranej pozycji na LCD HD44780

Uruchomienie wyświetlacz HD44780
  1. void LCD_xy(unsigned char w, unsigned char h)
  2. {
  3.         LCD_wyslij((w*0x40+h)|0x80,0);
  4.         _delay_us(10);
  5. }

Funkcja LCD_xy służy do ustawienia kursora na wyświetlaczu w odpowiednim miejscu w którym chcemy rozpocząć wyświetlanie znaków. W (3) linijce umieszczony został wzór wyliczający dla podancych w nawiasie funkcji koordynatów wartość komórki pamięci w wyświetaczu HD44780 w której ma się ustawić kursor tak żeby wyświetlić tekst w odpowiednim miejscu. Ja osobiście nie analizowałem tego wzoru ale sprawdziłem go na dwóch wyświetlaczach 2X8 oraz 4X16 i działa prawidłowo. Koordynaty odliczane są od pozycji (0,0) do pozycji (1,15) dla wyświetlacza 2X16. W linii (4) mamy opóźnienie czasowe zakańczające funkcję.

9. Wyświetlacz uruchomiony. Napisanie dowolnego tekstu na LCD HD44780

Uruchomienie wyświetlacz HD44780
  1. int main(void)
  2. {
  3.  
  4. DDRD=0xff;                              // ustalenie kierunku portu (wyjście)
  5. PORTD=0xff;                     // wystawienie wartości AAh na port czyli 10101010b
  6.  
  7. sei();
  8.  
  9. // Uruchomienie LCD
  10. LCD_init();
  11. LCD_xy(0,6);
  12. LCD_czysc;
  13. LCD_tekst("Jakis tekst");
  14.  
  15.         while(1)
  16.     {
  17.        
  18.     }
  19. }

Funkcja programu głównego wykorzystująca wyświetlacz HD44780 przedstawiona została powyżej. Linie (3) i (4) to ustawienie portu na którym podłączony został wyświetlacz HD44780 na wyjściowy i wystawienie na niego wartości 0xff. (7) Uaktywnienie obsługi przerwań globalnych (do wyświetlacza nie konieczne jednak przydatne w przypadku korzystania z przerwań od timerów, ADC i innych komponentów mikroprocesora. (10) wywołanie funkcji inicjującej wyświetlacz HD44780. (11) Ustawienie kursora w pozycji siódmego znaku w pierwszej linijce. (12) Wywołanie funkcji czyszczącej wyświetlacz HD44780. (13) Wywołanie funkcji wyświetlającej napis „jakiś tekast” na wyświetlaczu. (15) wywołanie pętli głównej programu.

10. Sposoby podłączenia i wiążące się z nimi modyfikacje

CDN

11. Program obsługi wyświetlacza w całości

 Poniżej przedstawiony został pełen program obsługi wyświetlacza HD44780 opisany powyżej.

UWAGA !!! Czytaj programy ze zrozumieniem. NIE KOPIUJ 1:1 ... PAMIĘTAJ ... Zanim program zacznie działać dostosuj konfiguracje portów do swojego rzeczywistego układu. 

 

Uruchomienie wyświetlacz HD44780
  1. //  Załączniki
  2. // Include
  3. #include <avr/io.h>
  4. #include <util/delay.h>
  5.  
  6. //  Definicje
  7. #define cbi(sfr,bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
  8. #define sbi(sfr,bit) ((_SFR_BYTE(sfr) |= _BV(bit)))
  9. #define lcd_ster PORTD
  10. #define lcd_data PORTD
  11. #define ddr_lcd_ster DDRD
  12. #define ddr_lcd_data DDRD
  13. #define pin_lcd PIND
  14. #define e 4
  15. #define rs 6
  16. #define rw 7
  17. #define rs_0 cbi(lcd_ster,rs)
  18. #define rs_1 sbi(lcd_ster,rs)
  19. #define rw_0 cbi(lcd_ster,rw)
  20. #define rw_1 sbi(lcd_ster,rw)
  21. #define e_0 cbi(lcd_ster,e)
  22. #define e_1 sbi(lcd_ster,e)
  23. #define LCD_czysc LCD_wyslij(0x01,0)
  24.  
  25. // Wyświetlacz LCD ***********************************************************
  26. unsigned char LCD_busy(void)
  27. {
  28.         unsigned char flaga;    //zmienna pomocnicza
  29.         rs_0 ;
  30.         rw_1 ;
  31.         ddr_lcd_ster=ddr_lcd_data&0b11110111;
  32.         e_1;
  33.         _delay_us(1); // aaaa
  34.         flaga=pin_lcd&0x08;
  35.         e_0;
  36.         e_1;
  37.         _delay_us(1); // aaaa
  38.         e_0;
  39.         ddr_lcd_ster=ddr_lcd_data|0b00001000;
  40.         _delay_us(1); // aaaa
  41.         return flaga;
  42. }
  43.  
  44. // wyslanie znaku lub komendy do LCD
  45. void LCD_wyslij(unsigned char dana,char litera)
  46. {
  47.         while(LCD_busy());      // oczekiwanie na zwolienie wyswietlacza
  48.         rw_0;
  49.         e_1;
  50.         if (litera==0)
  51.         {
  52.                 rs_0;
  53.         }
  54.         else
  55.         {
  56.                 rs_1;
  57.         }
  58.         e_1;
  59.         lcd_data=(lcd_data&0xF0)|((dana&0xf0)>>4);      // przygotuj starszy bajt do LCD
  60.         _delay_us(2); // aaaa   _delay_ms(5);
  61.         e_0;
  62.         _delay_us(2); // aaaa   _delay_ms(5);
  63.         e_1;
  64.         lcd_data=(lcd_data&0xF0)|(dana&0x0f);   // przygotuj młodszy bajt do LCD
  65.         _delay_us(2); // aaaa   _delay_ms(5);
  66.         e_0;
  67.         _delay_us(2); // aaaa   _delay_ms(10);
  68. }
  69.  
  70.  
  71. // wgranie polskich znaków do LCD
  72. void LCD_polskie_znaki(unsigned char dana)
  73. {
  74.         while(LCD_busy());      // oczekiwanie na zwolienie wyswietlacza
  75.         rs_1;
  76.         rw_0;
  77.         e_1;
  78.         lcd_data=(lcd_data&0xF0)|((dana&0xf0)>>4);      // przygotuj starszy bajt do LCD
  79.         _delay_us(1); // aaaa
  80.         e_0;
  81.         _delay_us(1); // aaaa
  82.         e_1;
  83.         lcd_data=(lcd_data&0xF0)|(dana&0x0f);   // przygotuj młodszy bajt do LCD
  84.         _delay_us(2);
  85.         e_0;
  86.         _delay_us(1); // aaaa
  87. }
  88.  
  89. void LCD_znakipl_load(void)
  90. {
  91.         LCD_wyslij(0x40,0);
  92.         unsigned char znaki[]={ 0,0,14,1,15,17,15,2,            // ą
  93.                                                 2,4,14,16,16,17,14,0,           // ć
  94.                                                 0,0,14,17,31,16,14,2,           // ę
  95.                                                 12,4,6,4,12,4,14,0,             // ł
  96.                                                 2,4,22,25,17,17,17,0,           // ń
  97.                                                 2,4,14,17,17,17,14,0,           // ó
  98.                                                 2,4,14,16,14,1,30,0,            // ś
  99.                                                 2,4,31,2,4,8,31,0};                     // ż
  100.  
  101. /*                                              14,17,17,31,17,17,19,0, // Ą
  102.                                                 2,14,21,16,16,17,14,0,          // Ć
  103.                                                 31,16,30,16,16,31,2,0,          // Ę
  104.                                                 16,16,20,24,16,16,31,0, // Ł
  105.                                                 2,21,25,21,19,17,17,0,          // Ń
  106.                                                 2,14,21,17,17,17,14,0,          // Ó
  107.                                                 2,14,16,14,1,1,30,0,            // Ś
  108.                                                 31,1,2,14,8,16,31,0};           // ż
  109. */
  110.  
  111.         unsigned char znak;
  112.         for (unsigned char i=0;i<64;i++)
  113.         {
  114.                 znak=znaki[i];
  115.                 LCD_polskie_znaki(znak);
  116.         }
  117.         _delay_us(1); // aaaa
  118. }
  119.  
  120. // inicjowanie LCD w trybie 4 bitowym
  121. void LCD_init(void)
  122. {
  123.         _delay_ms(50);
  124.         unsigned char i;
  125.         ddr_lcd_ster=0xff;
  126.         ddr_lcd_data=0xff;
  127.         rw_0;
  128.         _delay_ms(10);
  129.         for (i=1;i<3;i++)       // trzykrotne wysłanie 3-
  130.         {
  131.                 e_1;
  132.                 lcd_data=(lcd_data&0xf0)|0x03;  //wysłanie 3- do LCD
  133.                 _delay_ms(1);
  134.                 e_0;
  135.                 _delay_ms(1);
  136.         }
  137.         e_1;
  138.         lcd_data=(lcd_data&0xf0)|0x02;  // wysłanie 2- do LCD
  139.         _delay_ms(1);                   // od tego momentu sprawdzamy gotowosc LCD
  140.         LCD_wyslij(0x28,0);             // interfejs 4 bitowy, 2 linie
  141.         LCD_wyslij(0x08,0);             //wyłącz LCD, wyłącz kursor, wyłącz mruganie 00001000
  142.         LCD_wyslij(0x01,0);             //czysc LCD
  143.         LCD_wyslij(0x06,0);             //zwiekszanie pozycji kursora po każdy  znaku
  144.         LCD_wyslij(0x0c,0);             //wlacz wyswietlacz bez kursora
  145.         LCD_wyslij(0x28,0);             // interfejs 4 bitowy, 2 linie
  146.         e_0;
  147.         _delay_ms(1);
  148. }
  149.  
  150. //pisze tekst na LCD
  151. void LCD_tekst(char *tekst)
  152. {
  153.         unsigned char i=0;
  154.         while (tekst[i]) LCD_wyslij(tekst[i++],1);
  155.         _delay_us(10);
  156. }
  157.  
  158. void LCD_xy(unsigned char w, unsigned char h)
  159. {
  160.         LCD_wyslij((w*0x40+h)|0x80,0);
  161.         _delay_us(10);
  162. }
  163.  
  164. // napis poczatkowy
  165. void intro(void)
  166. {
  167.         LCD_czysc;
  168.         LCD_xy(0,0);
  169.         LCD_tekst("HALLO MI");LCD_wyslij(0x06,1);
  170.         LCD_xy(1,0);
  171.         LCD_tekst("Herbatka Gotowa");
  172. }
  173. //^ Wyświetlacz LCD ***********************************************************
  174.  
  175. int main(void)
  176. {
  177.  
  178. DDRD=0xff;                              // ustalenie kierunku portu (wyjście)
  179. PORTD=0xff;                     // wystawienie wartości AAh na port czyli 10101010b
  180.  
  181. sei();
  182.  
  183. // Uruchomienie LCD
  184. LCD_init();
  185. LCD_xy(0,6);
  186. LCD_czysc;
  187. LCD_tekst("Jakis tekst");
  188.  
  189.         while(1)
  190.     {
  191.        
  192.     }
  193. }
  194.  

.






 
Wszelkie prawa zastrzeżone! Kopiowanie, powielanie i wykorzystywanie zdjęć, treści oraz jej fragmentów bez zgody autora zabronione.
© mikroprocesory.info.pl@gmail.com 2013.