[JAK OBIEKTOWO NAPISAĆ DRIVER] STM32NUCLEO + mbed.org + graficzny LCD = druga aplikacja na STM32 w sieciowym środowisku programistycznym
Możliwość przeciążania operatorów w języku C++ pozwala nie tylko na przypisanie nowych funkcji operatorom w zależności od typu przyjmowanych argumentów, ale także na skrócenie (i zwiększenie czytelności) kodu klienckiego jaki tworzy użytkownik. Tak na przykład, aby wyświetlić tekst, wartość, linię oraz prostokąt można użyć następujących komend:
lcd.gotoXY(10, 10); lcd << "Hello, World! " << 1234; lcd.setFGColor(LCD_RGB565_BLUE); lcd << line << rect;
zamiast:
lcd.gotoXY(10, 10); lcd.writeString("Hello, World!"); lcd.gotoXY(120, 10); lcd.writeString("1234"); lcd.drawLine(line, LCD_RGB565_BLUE) lcd.drawRectangle(rect, LCD_RGB565_BLUE, 0)
Przykładowe implementacje przeciążonych operatorów przedstawia następujący listing:
/* ********************************** */ /* *** Graphics-related functions *** */ /* ********************************** */ NokiaLCD NokiaLCD::operator<<(const Line& line) { drawLine(line, fg_color); return *this; } NokiaLCD NokiaLCD::operator<<(const Rect& rect) { drawRectangle(rect, fg_color, 0); return *this; } /* ****************************** */ /* *** Text-related functions *** */ /* ****************************** */ NokiaLCD NokiaLCD::operator<<(const char c) { int x_step(0); switch(text_size){ case 0:{ x_step = 6; break; } case 1: case 2:{ x_step = 8; break; } default:{ x_step = 0; break; } } drawChar(c, text_x_last, text_y_last, text_size, text_fg_color, text_bg_color); text_x_last += x_step; return *this; } NokiaLCD NokiaLCD::operator<<(const char *s) { int i(0), x_step(0); switch(text_size){ case 0:{ x_step = 6; break; } case 1: case 2:{ x_step = 8; break; } default:{ x_step = 0; break; } } while(*s){ drawChar(*s++, text_x_last + x_step*i, text_y_last, text_size, text_fg_color, text_bg_color); ++i; } text_x_last += x_step*i; return *this; } NokiaLCD NokiaLCD::operator<<(const int n) { int i(0), x_step(0); char text[16]; sprintf(text, "%d", n); switch(text_size){ case 0:{ x_step = 6; break; } case 1: case 2:{ x_step = 8; break; } default:{ x_step = 0; break; } } while(text[i]){ drawChar(text[i], text_x_last + x_step*i, text_y_last, text_size, text_fg_color, text_bg_color); ++i; } text_x_last += x_step*i; return *this; }
Uzupełnienia wymaga jeszcze plik nagłówkowy z definicją klasy NokiaLCD:
class NokiaLCD { private: //[...] public: //[...] // Graphics-related functions NokiaLCD operator<<(const Line& line); NokiaLCD operator<<(const Rect& rect); //[...] // Text-related functions NokiaLCD operator<<(const char c); NokiaLCD operator<<(const char *s); NokiaLCD operator<<(const int n); //[...] };
Oczywiście przedstawiona realizacja sterownika wyświetlacza nie jest idealnie dopracowana, jednak pokazuje z grubsza specyfikę i możliwości programowania w języku C++, zwalniając nas z tworzenia nadmiernej ilości kodu oraz posługiwania się złożonymi wskaźnikami. W ramach prostych ćwiczeń można napisać pozostałe funkcje rysujące, zmodyfikować istniejące, a także nadać nowe znaczenia niektórym operatorom.
#include "mbed.h" #include "Graphics.h" #include "NokiaLCD.h" DigitalIn button(USER_BUTTON); int main() { char c('a'); int contrast(50); int dx(0), sign(1); // Create NokiaLCD object and initialize LCD NokiaLCD lcd(D10, D13, D11, D9); // Set LCD contrast lcd.setContrast(contrast); // Clear LCD using white color lcd.clear(LCD_RGB565_WHITE); // Draw filled rectangles lcd.fillRect(5, 5, 122, 80, LCD_RGB565_YELLOW); lcd.fillRect(8, 8, 116, 28, LCD_RGB565_ORANGE); lcd.fillRect(8, 38, 116, 10, LCD_RGB565_GRAY); // Set background and foreground color for text lcd.setTextBGColor(LCD_RGB565_ORANGE); lcd.setTextFGColor(LCD_RGB565_BLACK); // Set font: 8x8 lcd.setTextSize(1); // Write text @ x=10, y=10 lcd.gotoXY(10, 10); lcd.writeString("Nucleo-F334R8"); // Write text @ x=10, y=20 lcd.gotoXY(10, 20); lcd.writeString(" + KAmodTFT2"); lcd.setFGColor(LCD_RGB565_BLACK); Line line_1(17, 67, 23, 73); Line line_2(23, 67, 17, 73); Rect rect_1(10, 65, 20, 10); lcd << line_1 << line_2 << rect_1; // Set font: 6x8 lcd.setTextSize(0); // Set background and foreground color for text lcd.setTextBGColor(LCD_RGB565_GRAY); lcd.setTextFGColor(LCD_RGB565_WHITE); // Write text @ x=10, y=40 lcd.gotoXY(10, 40); lcd << "Contrast: \0" << contrast << " "; while(1){ // Wait 200 ms wait(0.2); // If button was pressed if(!button){ // Increment contrast if(++contrast > 63) contrast = -64; lcd.setContrast(++contrast); // Write text @ x=10, y=40 lcd.gotoXY(10, 40); lcd << "Contrast: \0" << contrast << " "; } // Increment character if(++c > 'z') c = 'a'; // Write characters lcd.drawChar(c, 15, 90, 0, LCD_RGB565_RED, LCD_RGB565_WHITE); lcd.drawChar(c, 35, 90, 0, LCD_RGB565_GREEN, LCD_RGB565_WHITE); lcd.drawChar(c, 55, 90, 0, LCD_RGB565_BLUE, LCD_RGB565_WHITE); lcd.drawChar(c, 75, 90, 0, LCD_RGB565_BLACK, LCD_RGB565_WHITE); lcd.drawChar(c, 95, 90, 0, LCD_RGB565_WHITE, LCD_RGB565_BLACK); lcd.drawChar(c, 15, 100, 0, LCD_RGB565_WHITE, LCD_RGB565_RED); lcd.drawChar(c, 35, 100, 0, LCD_RGB565_WHITE, LCD_RGB565_GREEN); lcd.drawChar(c, 55, 100, 0, LCD_RGB565_WHITE, LCD_RGB565_BLUE); lcd.drawChar(c, 75, 100, 0, LCD_RGB565_WHITE, LCD_RGB565_BLACK); lcd.drawChar(c, 95, 100, 0, LCD_RGB565_BLACK, LCD_RGB565_WHITE); // Clear old objects lcd.setFGColor(LCD_RGB565_YELLOW); lcd << line_1 << line_2 << rect_1; dx += sign; if(dx >= 80) sign = -1; else if(dx <= 0) sign = 1; // Move objects line_1.move(sign, 0); line_2.move(sign, 0); rect_1.move(sign, 0); // Draw new objects lcd.setFGColor(LCD_RGB565_BLACK); lcd << line_1 << line_2 << rect_1; } }
Jan Szemiet