LinkedIn YouTube Facebook
Szukaj

Newsletter

Proszę czekać.

Dziękujemy za zgłoszenie!

Wstecz
Artykuły

[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

Autor: Jan Szemiet