[JAK NAPISAĆ DRIVER] STM32NUCLEO + mbed.org + graficzny LCD = druga aplikacja na STM32 w sieciowym środowisku programistycznym
W przykładzie przedstawiamy obsługę modułu z kolorowym wyświetlaczem LCD o wymiarach matrycy 132×132 piksele z wbudowanym sterownikiem PCF8833 (KAmodTFT2). Schemat podłączenia linii modułu KAmodTFT2 do zestawu przedstawiono na rysunku 1.
Rys. 1. Schemat podłączenia modułu KAmodTFT2 z zestawem Nucleo-F334R8
Komunikacja pomiędzy mikrokontrolerem zamontowanym na płytce Nucleo a kontrolerem wyświetlacza w module KAmodTFT2 odbywa się z wykorzystaniem interfejsu SPI. Długość słowa danych w pojedynczej ramce wynosi 9, a nie – jak zazwyczaj – 8 lub 16 bitów (rysunek 2), na szczęście mikrokontroler STM32F334R8T6 ma możliwość konfiguracji długości słowa danych od 4 do 16 bitów.
Rys. 2. Przebieg sygnałów na magistrali SPI podczas komunikacji mikrokontrolera z PCF8833
Sterownik wyświetlacza
W internetowym środowisku programistycznym mbed można znaleźć co najmniej dwa programowe sterowniki wyświetlacza z kontrolerem PCF8833 (np. biblioteka NokiaLCD – rysunek 3). Uniwersalne sterowniki mogą nie zawsze poprawnie współpracować ze sprzętowym interfejsem SPI zaimplementowanym w użytym mikrokontrolerze, bardziej sensownym i stabilnym rozwiązaniem jest samodzielne przygotowanie takiego sterownika, zapoznając się przy okazji z możliwościami jakie daje programowanie w języku C++ (dotyczy to osób, które dobrze znają język C i chcą rozpocząć programowanie w C++).
Rys. 3. Biblioteka NokiaLCD jest domyślnie dostępna w pakiecie mbed
Pierwszym krokiem w procesie przygotowania własnego sterownika wyświetlacza jest stworzenie nowego projektu lub zaimportowanie już istniejącego. Następnie należy utworzyć pliki implementacyjne (.cpp) i nagłówkowe (.h) o nazwach Graphics oraz NokiaLCD (rysunek 4). Dodatkowo będzie potrzebny jeszcze jeden plik o nazwie Fonts.c przechowujący deklaracje tablic z wzorcami znaków dla różnych czcionek.
Rys. 4. Pliki projektu o nazwie Nucleo-F334R8_NokiaLCD
W pliku nagłówkowym NokiaLCD.h znajdują się definicje stałych (komend kontrolera PCF8833 i kolorów w formacie RGB565) oraz definicja klasy NokiaLCD. Jako prywatne składowe klasy deklarujemy te pola i metody, które będą wykorzystywane tylko w jej obrębie i które nie powinny być widoczne dla użytkownika tejże klasy (tymi składowymi są m.in. zmienne typu DigitalOut przechowujące numer linii GPIO oraz funkcje z prefiksem spi_ przeznaczone do pracy z magistralą SPI):
// Philips PCF8833 LCD controller command codes #define NOP 0x00 // nop #define SWRESET 0x01 // software reset #define BSTROFF 0x02 // booster voltage OFF #define BSTRON 0x03 // booster voltage ON #define RDDIDIF 0x04 // read display identification #define RDDST 0x09 // read display status #define SLEEPIN 0x10 // sleep in #define SLEEPOUT 0x11 // sleep out #define PTLON 0x12 // partial display mode #define NORON 0x13 // display normal mode #define INVOFF 0x20 // inversion OFF #define INVON 0x21 // inversion ON #define DALO 0x22 // all pixels OFF #define DAL 0x23 // all pixels ON #define SETCON 0x25 // set contrast #define DISPOFF 0x28 // display OFF #define DISPON 0x29 // display ON #define CASET 0x2A // column address set #define PASET 0x2B // page address set #define RAMWR 0x2C // memory write #define RGBSET 0x2D // colour set #define PTLAR 0x30 // partial area #define VSCRDEF 0x33 // vertical scrolling definition #define TEOFF 0x34 // test mode #define TEON 0x35 // test mode #define MADCTL 0x36 // memory access control #define SEP 0x37 // vertical scrolling start address #define IDMOFF 0x38 // idle mode OFF #define IDMON 0x39 // idle mode ON #define COLMOD 0x3A // interface pixel format #define SETVOP 0xB0 // set Vop #define BRS 0xB4 // bottom row swap #define TRS 0xB6 // top row swap #define DISCTR 0xB9 // display control #define DOR 0xBA // data order #define DATCTL 0xBC // Data scan direction, etc. #define TCDFE 0xBD // enable/disable DF temperature compensation #define TCVOPE 0xBF // enable/disable Vop temp comp #define EC 0xC0 // internal or external oscillator #define SETMUL 0xC2 // set multiplication factor #define TCVOPAB 0xC3 // set TCVOP slopes A and B #define TCVOPCD 0xC4 // set TCVOP slopes c and d #define TCDF 0xC5 // set divider frequency #define DF8COLOR 0xC6 // set divider frequency 8-color mode #define SETBS 0xC7 // set bias system #define RDTEMP 0xC8 // temperature read back #define NLI 0xC9 // n-line inversion #define RDID1 0xDA // read ID1 #define RDID2 0xDB // read ID2 #define RDID3 0xDC // read ID3 #define LCD_RGB565_BLACK 0x0000 #define LCD_RGB565_BLUE 0x001F #define LCD_RGB565_GRAY 0x8430 #define LCD_RGB565_GREEN 0x07E0 #define LCD_RGB565_ORANGE 0xFDC5 #define LCD_RGB565_RED 0xF800 #define LCD_RGB565_WHITE 0xFFFF #define LCD_RGB565_YELLOW 0xFFF8 #include "Graphics.h" class NokiaLCD { private: DigitalOut CLK, CS, DATA, RES; unsigned int fg_color; unsigned int text_bg_color, text_fg_color; int text_x, text_y; int text_x_last, text_y_last; int text_size; // SPI-related functions void spi_write(unsigned char data); void spi_writeCommand(unsigned char cmd); void spi_writeData(unsigned char data); public: NokiaLCD(PinName clk, PinName cs, PinName data, PinName res); // Control functions void clear(unsigned int color); void setContrast(char contrast); // Graphics-related functions //[...] void drawChar(char c, int x, int y, int size, unsigned int fgColor, unsigned int bgColor); void drawPixel(int x, int y, unsigned int color); void fillRect(int x, int y, int width, int height, unsigned int color); void setFGColor(unsigned int color); // Text-related functions //[...] void gotoXY(int x, int y); void setTextBGColor(unsigned int color); void setTextFGColor(unsigned int color); void setTextSize(int size); void writeChar(char c); void writeCharAtXY(char c, int x, int y); void writeString(char *s); void writeStringAtXY(char *s, int x, int y); };