W tym poście opiszę w jaki sposób obsłużyć wyświetlacz 2x16 ze sterownikiem HD44780.
Program
Poniżej przejdę po poszczególnych głównych funkcjach całego programu.
Rozpoczęcie pracy z wyświetlaczem należy rozpocząć od jego poprawnego włączenia, co się wykonuje na podstawie przedstawionej poniżej funkcji inicjującej pracę wyświetlacza oraz uruchamiającą potrzebne wyprowadzenia GPIO.
Definicję rejestrów:
Funkcja rozpoczynająca pracę układu z mikrokontrolerem:
Funkcja ustawiająca piny:
Definicję rejestrów:
- #define HD44780_CLEAR 0x01
- #define HD44780_HOME 0x02
- #define HD44780_ENTRY_MODE 0x04
- #define HD44780_EM_SHIFT_CURSOR 0x00
- #define HD44780_EM_SHIFT_DISPLAY 0x01
- #define HD44780_EM_DECREMENT 0x00
- #define HD44780_EM_INCREMENT 0x02
- #define HD44780_DISPLAY_ONOFF 0x08
- #define HD44780_DISPLAY_OFF 0x00
- #define HD44780_DISPLAY_ON 0x04
- #define HD44780_CURSOR_OFF 0x00
- #define HD44780_CURSOR_ON 0x02
- #define HD44780_CURSOR_NOBLINK 0x00
- #define HD44780_CURSOR_BLINK 0x01
- #define HD44780_DISPLAY_CURSOR_SHIFT 0x10
- #define HD44780_SHIFT_CURSOR 0x00
- #define HD44780_SHIFT_DISPLAY 0x08
- #define HD44780_SHIFT_LEFT 0x00
- #define HD44780_SHIFT_RIGHT 0x04
- #define HD44780_FUNCTION_SET 0x20
- #define HD44780_FONT5x8 0x00
- #define HD44780_FONT5x10 0x04
- #define HD44780_ONE_LINE 0x00
- #define HD44780_TWO_LINE 0x08
- #define HD44780_4_BIT 0x00
- #define HD44780_8_BIT 0x10
- #define HD44780_SETCGRAM 0x40
- #define HD44780_SETDDRAM 0x80
Funkcja rozpoczynająca pracę układu z mikrokontrolerem:
- void LCD_HD44780_Init(void)
- {
- //Deklaracja zmiennych
- volatile unsigned char i = 0;
- //volatile unsigned int delayCnt = 0;
- //Wlaczenie pinow
- LCD_InitPins();
- //Ustawienie wszystkich pinów w stan niski
- ((LCD_D4_Port)->BSRRH = (LCD_D4));
- ((LCD_D5_Port)->BSRRH = (LCD_D5));
- ((LCD_D6_Port)->BSRRH = (LCD_D6));
- ((LCD_D7_Port)->BSRRH = (LCD_D7));
- ((LCD_RS_Port)->BSRRH = (LCD_RS));
- ((LCD_RW_Port)->BSRRH = (LCD_RW));
- ((LCD_EN_Port)->BSRRH = (LCD_EN));
- //Opoznienie przynajmniej 40ms
- LCD_Delay(300000);
- //Wybranie trybu 4 bitowego, nalezy dane wyslac 3 razy
- for(i = 0; i < 3; i++)
- {
- LCD_WriteNibble(0x03);
- //Odczekac przynajmniej 40ms
- LCD_Delay(30000);
- }
- //Wlaczenie trybu 4 bitowego
- LCD_WriteNibble(0x02);
- //Delay
- LCD_Delay(6000);
- //Ustawienie wielkosci czcionek rozmiar linie komunikacje
- //HD44780_FUNCION_SET = 0x20 | HD44780_FONT5x8 = | HD44780_TWO_LINE = 0x08
- //| HD44780_4_BIT = 0x00
- LCD_WriteCommand(HD44780_FUNCTION_SET | HD44780_FONT5x8 |
- HD44780_TWO_LINE | HD44780_4_BIT);
- //Wlaczenie oraz wylaczenie wyswietlacza w pelnym trybie
- //HD44780_DISPLAY_ONOFF = 0x08 | HD44780_DISPLAY_OFF = 0x00
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF);
- //Wyczyszczenie wyswietlacza
- //HD44780_CLEAR - 0x01
- LCD_WriteCommand(HD44780_CLEAR);
- //Ustawienie dodatkowe do trybów wyswietlania, kursora
- //HD44780_ENTRY_MODE = 0x04 | HD44780_EM_SHIFT_CURSOR = 0x00 |
- //HD44780_EM_INCREMENT = 0x02
- LCD_WriteCommand(HD44780_ENTRY_MODE | HD44780_EM_SHIFT_CURSOR | HD44780_EM_INCREMENT);
- //HD44780_DISPLAY_ONOFF = 0x08 | HD44780_DISPLAY_ON = 0x04| HD44780_CURSOR_OFF = 0x00 //| HD44780_CURSOR_NOBLINK = 0x00
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_ON | HD44780_CURSOR_OFF | HD44780_CURSOR_NOBLINK);
- }
Funkcja ustawiająca piny:
- //Wlaczenie pinów===================================
- void LCD_InitPins()
- {
- //Wlaczenie pinow dla wyswietlacza
- GPIO_InitTypeDef GPIO_InitDef;
- //Ustawienia dla poszczególnych wyprowadzen
- RCC->AHB1ENR |= RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB |
- RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOE;
- //Linie sygnalowe
- //Wybranie pinów
- GPIO_InitDef.GPIO_Pin = LCD_D4 | LCD_D5 | LCD_D6 | LCD_D7;
- GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
- GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_InitDef.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_Init(Signal_Port, &GPIO_InitDef);
- //E
- GPIO_InitDef.GPIO_Pin = LCD_EN;
- GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
- GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_InitDef.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_Init(LCD_EN_Port, &GPIO_InitDef);
- //RS
- GPIO_InitDef.GPIO_Pin = LCD_RS;
- GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
- GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_InitDef.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_Init(LCD_RS_Port, &GPIO_InitDef);
- //RW
- GPIO_InitDef.GPIO_Pin = LCD_RW;
- GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
- GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
- GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
- GPIO_InitDef.GPIO_Speed = GPIO_Speed_2MHz;
- GPIO_Init(LCD_RW_Port, &GPIO_InitDef);
- }
Pętla opóźniająca, wykonana za pomocą pętli for();
Funkcja wysyłająca tzw. nibbla czyli młodszą oraz starszą część bitu, którego należy podać w dwóch partiach. Spowodowane jest to wykorzystywanie 4 bitowego trybu transmisji danych:
Oraz odczytująca 4 bity:
Funkcja włączająca oraz wyłączająca wyświetlacz:
- void LCD_Delay(volatile unsigned int delayLic)
- {
- for(delayLic = 0; delayLic < 30000; delayLic++);
- }
Funkcja wysyłająca tzw. nibbla czyli młodszą oraz starszą część bitu, którego należy podać w dwóch partiach. Spowodowane jest to wykorzystywanie 4 bitowego trybu transmisji danych:
- void LCD_WriteNibble(unsigned char cmd)
- {
- GPIO_WriteBit(LCD_EN_Port, LCD_EN, Bit_SET);
- GPIO_WriteBit(LCD_D4_Port, LCD_D4, (cmd & 0x01));
- GPIO_WriteBit(LCD_D5_Port, LCD_D5, (cmd & 0x02));
- GPIO_WriteBit(LCD_D6_Port, LCD_D6, (cmd & 0x04));
- GPIO_WriteBit(LCD_D7_Port, LCD_D7, (cmd & 0x08));
- GPIO_WriteBit(LCD_EN_Port, LCD_EN, Bit_RESET);
- }
Oraz odczytująca 4 bity:
- unsigned char LCD_ReadNibble(void)
- {
- unsigned char tmp = 0;
- GPIO_WriteBit(LCD_EN_Port, LCD_EN, Bit_SET);
- tmp |= (GPIO_ReadInputDataBit(LCD_D4_Port, LCD_D4) << 0);
- tmp |= (GPIO_ReadInputDataBit(LCD_D5_Port, LCD_D5) << 1);
- tmp |= (GPIO_ReadInputDataBit(LCD_D6_Port, LCD_D6) << 2);
- tmp |= (GPIO_ReadInputDataBit(LCD_D7_Port, LCD_D7) << 3);
- GPIO_WriteBit(LCD_EN_Port, LCD_EN, Bit_RESET);
- return tmp;
- }
Funkcja włączająca oraz wyłączająca wyświetlacz:
- void LCD_HD44780_BlinkOn(void)
- {
- //HD44780_CURSOR_BLINK = 0x01
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_CURSOR_BLINK);
- }
- void LCD_HD44780_BlinkOff(void)
- {
- //HD44780_CURSOR_NOBLINK = 0x00
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_CURSOR_NOBLINK);
- }
Funkcja przesyłająca funkcje sterującą:
Funkcja wprowadzające dane do wyświetlania:
Wprowadzanie tekstu na wyświetlacz:
Funkcja wyłączająca oraz włączająca kursor:
Przesunięcie kursora w lewo oraz w prawo:
- void LCD_WriteCommand(unsigned char data)
- {
- //Przed wyslanie nalezy RW oraz RS ustawic
- //w stanie niski,
- GPIO_WriteBit(LCD_RW_Port, LCD_RW, Bit_RESET);
- GPIO_WriteBit(LCD_RS_Port, LCD_RS, Bit_RESET);
- //Wyslanie starszej czesci
- LCD_WriteNibble(data >> 4);
- //Wyslanie mlodszej czesci
- LCD_WriteNibble(data & 0x0F);
- //Odczytanie stanu przycisku
- while(LCD_ReadStatus() & 0x80);
- }
Funkcja wprowadzające dane do wyświetlania:
- void LCD_WriteData(unsigned char dataToWrite)
- {
- //Reset RW | ustawienie bitu RS
- GPIO_WriteBit(LCD_RW_Port, LCD_RW, Bit_RESET);
- GPIO_WriteBit(LCD_RS_Port, LCD_RS, Bit_SET);
- LCD_WriteNibble(dataToWrite >> 4);
- LCD_WriteNibble(dataToWrite & 0x0F);
- }
Wprowadzanie tekstu na wyświetlacz:
- void LCD_WriteText(unsigned char * text)
- {
- while(*text)
- LCD_WriteData(*text++);
- }
Funkcja wyłączająca oraz włączająca kursor:
- void LCD_HD44780_CursorOff(void)
- {
- //HD44780_DISPLAY_ONOFF = 0x08 | HD44780 = 0x00
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_DISPLAY_OFF);
- }
- void LCD_HD44780_CursorOn(void)
- {
- //HD44780_DISPLAYCONTROL = 0x08 | HD44780_CURSORON = 0x02
- LCD_WriteCommand(HD44780_DISPLAY_ONOFF | HD44780_CURSORON);
- }
Przesunięcie kursora w lewo oraz w prawo:
- //Przesuniecie w lewo
- void LCD_ShiftLeft(void)
- {
- //HD44780_DISPLAY_CURSOR_SHIFT = 0x10 | HD44780_SHIFT_LEFT = 0x00
- //HD44780_SHIFT_DISPLAY = 0x08
- LCD_WriteCommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_LEFT | HD44780_SHIFT_DISPLAY);
- }
- //Przesuniecie kursora w prawo
- void LCD_ShiftRight(void)
- {
- //HD44780_DISPLAY_CURSOR_SHIFT = 0x10 | HD44780_SHIFT_RIGHT = 0x04| HD44780_SHIFT_DISPLAY = 0x08
- LCD_WriteCommand(HD44780_DISPLAY_CURSOR_SHIFT | HD44780_SHIFT_RIGHT | HD44780_SHIFT_DISPLAY);
- }
Czyszczenie wyświetlacza:
Dodatkowo istnieje jeszcze możliwość tworzenia własnej tablicy znaków, którą można stworzyć poprzez wprowadzenie go do pamięci wyświetlacza. Układ może przechowywać do 8 własnych zdefiniowanych znaków:
- void LCD_HD44780_Clear(void)
- {
- //HD44780_CLEAR = 0x01
- LCD_WriteCommand(HD44780_CLEAR);
- LCD_Delay(300000);
- }
Dodatkowo istnieje jeszcze możliwość tworzenia własnej tablicy znaków, którą można stworzyć poprzez wprowadzenie go do pamięci wyświetlacza. Układ może przechowywać do 8 własnych zdefiniowanych znaków:
- void HD44780_Char(uint8_t location, uint8_t *data)
- {
- uint8_t i;
- //Maksymalnie mozna zdefiniowac 8 znakow
- location &= 0x07;
- LCD_WriteCommand(HD44780_SETCGRAM | (location << 3));
- for (i = 0; i < 8; i++)
- {
- LCD_WriteData(data[i]);
- }
- }
Podłączenie
- VSS - Masa GND
- VDD - Zasilanie
- V0 - Potencjometr do regulacji kontrastu
- RS - Do zdefiniowanego pinu
- RW - Do zdefiniowanego pinu
- E - Do zdefiniowanego pinu
- D4 - Do zdefiniowanego pinu
- D5 - Do zdefiniowanego pinu
- D6 - Do zdefiniowanego pinu
- D7 - Do zdefiniowanego pinu
- A - Podświetlenie do 3,3V
- K - Masa podświetlenia
W części głównej programu należy włączyć wyświetlacz po czym można kolejnymi komendami go obsługiwać.