wtorek, 24 października 2017

[35] Arduino - Wyświetlacz TFT

Ten post chciałbym poświęcić na opisanie sposobu sterowania wyświetlaczem TFT 1.8 cala za pomocą interfejsu SPI. 

[Źródło: https://nettigo.pl/products/wyswietlacz-lcd-tft-1-8-spi-ili9163]

Podłączenie:


Poniżej przedstawię w jaki sposób podłączyć układ do płytki Arduino:

  • LED - 3.3V
  • SCK - Arduino pin 13
  • SDA - Arduino pin 11
  • A0 - definiowany w programie
  • RESET - definiowany w programie
  • CS - definiowany w programie
  • GND - GND
  • VCC - 5V


Biblioteki:


W projekcie będą wykorzystywane dwie wbudowane biblioteki. Jedna z nich SPI.h odpowiada za komunikację z wyświetlaczem poprzez interfejs SPI. Druga czyli TFT.h jest odpowiedzialna za rysowanie oraz wypisywanie tekstu na ekranie.

Biblioteka dla wyświetlacza korzysta z plików przygotowanych przez Adafruit, które zawierają funkcje graficzne takie jak rysowanie bitmap, figur geometrycznych czy obsługi tekstu. 

Sam plik TFT zawiera inicjalizację obiektu który przekazuje wielkość wyświetlacza oraz piny sterujące dla biblioteki z Adafruit.

Jedyna funkcja jaka znajduje się w pliku TFT odpowiada za uruchomienie sterownika wyświetlacza (ILI9163C) oraz ustawienia orientacji ekranu:

  1. void TFT::begin() {
  2.   initG();
  3.   setRotation(1);
  4. }

Funkcja uruchamiająca sterownik wyświetlacza oraz ustawiająca SPI:

  1. // Initialization for ST7735B screens
  2. void Adafruit_ST7735::initG(void) {
  3.   commonInit(Gcmd);
  4. }
  5. // Initialization code common to both 'B' and 'R' type displays
  6. void Adafruit_ST7735::commonInit(const uint8_t *cmdList)
  7. {
  8.   colstart  = rowstart = 0; // May be overridden in init func
  9.   pinMode(_rs, OUTPUT);
  10.   pinMode(_cs, OUTPUT);
  11.   csport    = portOutputRegister(digitalPinToPort(_cs));
  12.   cspinmask = digitalPinToBitMask(_cs);
  13.   rsport    = portOutputRegister(digitalPinToPort(_rs));
  14.   rspinmask = digitalPinToBitMask(_rs);
  15.   if(hwSPI) { // Using hardware SPI
  16.     SPI.begin();
  17. #ifdef SPI_HAS_TRANSACTION
  18.     spisettings = SPISettings(4000000L, MSBFIRST, SPI_MODE0);
  19. #else
  20. #if defined(ARDUINO_ARCH_SAM)
  21.     SPI.setClockDivider(24); // 4 MHz (half speed)
  22. #else
  23.     SPI.setClockDivider(SPI_CLOCK_DIV4); // 4 MHz (half speed)
  24. #endif
  25.     SPI.setBitOrder(MSBFIRST);
  26.     SPI.setDataMode(SPI_MODE0);
  27. #endif // SPI_HAS_TRANSACTION
  28.   } else {
  29.     pinMode(_sclk, OUTPUT);
  30.     pinMode(_sid , OUTPUT);
  31.     clkport     = portOutputRegister(digitalPinToPort(_sclk));
  32.     clkpinmask  = digitalPinToBitMask(_sclk);
  33.     dataport    = portOutputRegister(digitalPinToPort(_sid));
  34.     datapinmask = digitalPinToBitMask(_sid);
  35.     *clkport   &= ~clkpinmask;
  36.     *dataport  &= ~datapinmask;
  37.   }
  38.   // toggle RST low to reset; CS low so it'll listen to us
  39.   *csport &= ~cspinmask;
  40.   if (_rst) {
  41.     pinMode(_rst, OUTPUT);
  42.     digitalWrite(_rst, HIGH);
  43.     delay(500);
  44.     digitalWrite(_rst, LOW);
  45.     delay(500);
  46.     digitalWrite(_rst, HIGH);
  47.     delay(500);
  48.   }
  49.   if(cmdList) commandList(cmdList);
  50. }

Z funkcji korzysta się poprzez wywołanie zdefiniowanego typu z biblioteki TFT i podanie funkcji z jakiej chce się dla wyświetlacza korzystać. Lista dostępnych publicznych funkcji wygląda następująco:

  1.   Adafruit_ST7735(uint8_t CS, uint8_t RS, uint8_t SID, uint8_t SCLK,
  2.     uint8_t RST);
  3.   Adafruit_ST7735(uint8_t CS, uint8_t RS, uint8_t RST);
  4.   void     initB(void),                             // for ST7735B displays
  5.            initG(void),                             // for ILI9163C displays
  6.            initR(uint8_t options = INITR_GREENTAB), // for ST7735R
  7.            setAddrWindow(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1),
  8.            pushColor(uint16_t color),
  9.            fillScreen(uint16_t color),
  10.            drawPixel(int16_t x, int16_t y, uint16_t color),
  11.            drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
  12.            drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
  13.            fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  14.              uint16_t color),
  15.            setRotation(uint8_t r),
  16.            invertDisplay(boolean i);
  17.   uint16_t Color565(uint8_t r, uint8_t g, uint8_t b) { return newColor(r, g, b);}

Dodatkowo dostępne są funkcje:

  1. public:
  2.   Adafruit_GFX(int16_t w, int16_t h); // Constructor
  3.   // This MUST be defined by the subclass
  4.   virtual void drawPixel(int16_t x, int16_t y, uint16_t color) = 0;
  5.   // These MAY be overridden by the subclass to provide device-specific
  6.   // optimized code.  Otherwise 'generic' versions are used.
  7.   virtual void
  8.     drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
  9.         uint16_t color),
  10.     drawFastVLine(int16_t x, int16_t y, int16_t h, uint16_t color),
  11.     drawFastHLine(int16_t x, int16_t y, int16_t w, uint16_t color),
  12.     drawRect(int16_t x, int16_t y, int16_t w, int16_t h,
  13.         uint16_t color),
  14.     fillRect(int16_t x, int16_t y, int16_t w, int16_t h,
  15.         uint16_t color),
  16.     fillScreen(uint16_t color),
  17.     invertDisplay(boolean i);
  18. // These exist only with Adafruit_GFX (no subclass overrides)
  19.   void
  20.     drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
  21.     drawCircleHelper(int16_t x0, int16_t y0,
  22.             int16_t r, uint8_t cornername, uint16_t color),
  23.     fillCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color),
  24.     fillCircleHelper(int16_t x0, int16_t y0, int16_t r,
  25.               uint8_t cornername, int16_t delta, uint16_t color),
  26.     drawTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
  27.             int16_t x2, int16_t y2, uint16_t color),
  28.     fillTriangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,
  29.             int16_t x2, int16_t y2, uint16_t color),
  30.     drawRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
  31.              int16_t radius, uint16_t color),
  32.     fillRoundRect(int16_t x0, int16_t y0, int16_t w, int16_t h,
  33.              int16_t radius, uint16_t color),
  34.     drawBitmap(int16_t x, int16_t y,
  35.           const uint8_t *bitmap, int16_t w, int16_t h,
  36.           uint16_t color),
  37.     drawChar(int16_t x, int16_t y, unsigned char c,
  38.         uint16_t color, uint16_t bg, uint8_t size),
  39.     setCursor(int16_t x, int16_t y),
  40.     setTextColor(uint16_t c),
  41.     setTextColor(uint16_t c, uint16_t bg),
  42.     setTextSize(uint8_t s),
  43.     setTextWrap(boolean w),
  44.     setRotation(uint8_t r);
  45. #if ARDUINO >= 100
  46.   virtual size_t write(uint8_t);
  47. #else
  48.   virtual void   write(uint8_t);
  49. #endif
  50.   int16_t
  51.     height(void),
  52.     width(void);
  53.   uint8_t getRotation(void);
  54.   /*
  55.    * Processing-like graphics primitives
  56.    */
  57.   /// transforms a color in 16-bit form given the RGB components.
  58.   /// The default implementation makes a 5-bit red, a 6-bit
  59.   /// green and a 5-bit blue (MSB to LSB). Devices that use
  60.   /// different scheme should override this.
  61.   virtual uint16_t newColor(uint8_t red, uint8_t green, uint8_t blue);
  62.   void
  63.     // http://processing.org/reference/background_.html
  64.     background(uint8_t red, uint8_t green, uint8_t blue),
  65.     background(color c),
  66.     // http://processing.org/reference/fill_.html
  67.     fill(uint8_t red, uint8_t green, uint8_t blue),
  68.     fill(color c),
  69.     // http://processing.org/reference/noFill_.html
  70.     noFill(),
  71.     // http://processing.org/reference/stroke_.html
  72.     stroke(uint8_t red, uint8_t green, uint8_t blue),
  73.     stroke(color c),
  74.     // http://processing.org/reference/noStroke_.html
  75.     noStroke(),
  76.     text(const char * text, int16_t x, int16_t y),
  77.     textWrap(const char * text, int16_t x, int16_t y),
  78.     textSize(uint8_t size),
  79.     // similar to ellipse() in Processing, but with
  80.     // a single radius.
  81.     // http://processing.org/reference/ellipse_.html
  82.     circle(int16_t x, int16_t y, int16_t r),
  83.     point(int16_t x, int16_t y),
  84.     line(int16_t x1, int16_t y1, int16_t x2, int16_t y2),
  85.     quad(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3, int16_t x4, int16_t y4),
  86. rect(int16_t x, int16_t y, int16_t width, int16_t height),
  87.     rect(int16_t x, int16_t y, int16_t width, int16_t height, int16_t radius),
  88.     triangle(int16_t x1, int16_t y1, int16_t x2, int16_t y2, int16_t x3, int16_t y3);

Programowanie:


Poniżej przedstawię prostą aplikacje wypisującą tekst na ekranie oraz zmieniającą jego kolor:

  1. #include <TFT.h>  
  2. #include <SPI.h>
  3. /* Pin definitions*/
  4. #define CS_Pin   10
  5. #define A0_Pin   9
  6. #define RST_Pin  8
  7. /* Create library instance, pass pin numbers */
  8. TFT TFTDisplay = TFT(CS_Pin, A0_Pin, RST_Pin);
  9. void setup() {
  10.   /* Initialize library */
  11.   TFTDisplay.begin();
  12.   /* Clear screen, set background color */
  13.   TFTDisplay.background(000);
  14.   /* set the font color to white */
  15.   TFTDisplay.stroke(255255255);
  16.   /* Set text size */
  17.   TFTDisplay.setTextSize(4);
  18.   TFTDisplay.text("Napis :\n "00);
  19.   /* Select font color */
  20.   TFTDisplay.stroke(50100100);
  21. }
  22. void loop()
  23. {
  24.   int redColor = 0;
  25.   int greenColor = 0;
  26.   int blueColor = 0;
  27.   TFTDisplay.stroke(redColor, greenColor, blueColor);
  28.   /* Print text */
  29.   TFTDisplay.text("Hello, World!"2024);
  30.   if(redColor == 255)
  31.   {
  32.     redColor=0;
  33.     greenColor=0;
  34.     blueColor=0;
  35.   }
  36.   redColor++;
  37.   greenColor++;
  38.   blueColor++;
  39.   /* Small delay */
  40.   delay(100);
  41. }