sobota, 19 listopada 2016

[1] STM32F429l - Wyświetlacz LCD

W tym poście chiałbym przedstawić sposób obsługi wyświetlacza zamontowanego na płytce STM32F429l Discovery za pomocą CubeMx oraz bibliotek standardowych.

Opis wyświetlacza:


Na płytkach discovery z  mikrokontrolerm STM32F429l znajduje się wyświetlacz LCD wyposarzony w sterownik ILI9341. Rodzielczość to 2,41", QVGA 240x320 pikseli. Głębia kolorów to 16(65536) bądź 18 bitów (262144). Co daje całkiem pokaźną liczbę kolorów.

Kontroler może być operowany z napięciem 2.8V +/- 0.3V.

Mikrokontroler został wyposarzony w sterownik LTDC do sterowania wyświetlaczem. Można nim sterować za pomocą wspomnianego sterownika lub za pomocą interfejsu SPI.

Rys. 1. Podłączenie wyświetlacza

Podłączenie 

Poniżej schemat oraz sposób podłączenia do poszczególnych pinów na płytce Discovery:

  • MISO - PF8
  • Podświetlenie(LED) - 3.3V
  • Clock - PF7
  • MOSI - PF9
  • WRX - PD13 - Rejest Data/Command
  • CS - PC2
  • Reset - PD12
  • GND - GND
  • VCC - 3.3V
Piny od SPI podłaczone są pod SPI5.

Programowanie CubeMx:


W celu przygotowania projektu należy posłużyć się środowiskiem CubeMx, które w graficzny sposób przedstawi sposób inicjalizacji głównych elementów.

Na samym początku dobrze pobrać paczkę z przykładami oraz sterownikami do STM32F4 z tego linku.

W pierwszej kolejności należy włączyć SDRam w konfiguracji przedstawionej na rysunku 1.

Rys. 2. Ustawienie projektu

Kolejnym elementem jest sterownik wyświetlacza LTDC z głębią kolorów ustawioną na 18 bitów, zegar na zewętrzny HSE, oraz SPI5 do których jest podłączony wyświetlacz.

Rys. 3. Ustawienie projektu

Kolejny etap dotyczy konfiguracji zegara. Wybrałem maksymane taktowanie z zegara zewnętrznego. Dodatkowo należy ustawić zegar dla wyświetlacza (na samym dole obrazka).

Rys. 4. Ustawienie projektu - taktowanie

Po przygotowaniu projektu zgodnie ze wskazówkami powyżej należy dołożyć elementy biblioteki, które ułatwią proces programowania.

BSP: Do programu należy dodać następujące pliki:
stm32f429i_discovery.c - Lokalizacja: Drivers\BSP\STM32F429I-Discovery
stm32f429i_discovery_lcd.c - Lokalizacja: Drivers\BSP\STM32F429I-Discovery
stm32f429i_discovery_sdram.c - Lokalizacja: Drivers\BSP\STM32F429I-Discovery
ili9341.c - Lokalizacji: Drivers\BSP\Components\ili9341

Dalej w zależnosci od wersji oprogramowania bądź bibliotek mogą występować błędy, ja spotkałem się z błędami dotyczącymi braku zdefiniowanej funkcji. Należy podstawić do projektu plik stm32f4xx_hal_ltdc z lokalizacji Drivers\STM32F4xx_HAL_Driver\Inc. Dodatkowo należy umieścić deklaracje funkcji np. w linii 133:

  1. /* Private function prototypes -----------------------------------------------*/
  2. static void LTDC_SetConfig(LTDC_HandleTypeDef *hltdc, LTDC_LayerCfgTypeDef *pLayerCfg, uint32_t LayerIdx);
  3. __weak void HAL_LTDC_ReloadEventCallback(LTDC_HandleTypeDef *hltdc);
  4. /* Private functions ---------------------------------------------------------*/

Po takich operacjach projekt powinien się poprawnie skompilować. To teraz przejdę do głównej części projektu.

Na samym początku należy oczywiście dołożyć bibliotekę zawierającą wykrozystywane funkje:

  1. /* USER CODE BEGIN Includes */
  2. #include "stm32f429i_discovery_lcd.h"
  3. /* USER CODE END Includes */

Następnie w funkcji main należy:

  1.   /* USER CODE BEGIN 2 */
  2.     BSP_LCD_Init();                                                     //Wlaczenie biblioteki
  3.     BSP_LCD_LayerDefaultInit(LCD_BACKGROUND_LAYER, LCD_FRAME_BUFFER);   //Wlaczenie pierwszej warstw
  4.     BSP_LCD_LayerDefaultInit(LCD_FOREGROUND_LAYER, LCD_FRAME_BUFFER);   //Wlaczenie drugiej warstwy
  5.     BSP_LCD_SelectLayer(LCD_FOREGROUND_LAYER);                          //Wybranie warstwy aktywnej
  6.     BSP_LCD_DisplayOn();                                                //Wlaczenie podswietlania
  7.     BSP_LCD_Clear(LCD_COLOR_BLACK);                                     //Kolor Tla
  8.   /* USER CODE END 2 */

Po powyższych operacjach kolor tła jest ustawiony na czarny. Aby wpisać na ekran czy narysować coś należy wykonać:

  1.     BSP_LCD_SetTextColor(LCD_COLOR_RED);
  2.     BSP_LCD_DisplayStringAtLine(0,(uint8_t*)"Naglowek 1");
  3.     BSP_LCD_DisplayStringAt(10, 40, (uint8_t*)"Linia", LEFT_MODE);
  4.     BSP_LCD_FillRect(10, 100, 100, 50);

Dodatkowo przygotowałem funkcję, jak poniżej która pozwala na ustawianie parametrów dla każdej linii tekstu. Nie jest ona zbytnio skomplikowana. Podaje się do niej większą ilość parametrów po czym ona wchodzi do funkcji zdefiniowanych w bibliotece.

  1. void DisplayText(uint16_t X, uint16_t Y, uint8_t *pText, uint32_t Color,Text_AlignModeTypdef mode)
  2. {
  3.     BSP_LCD_SetTextColor(Color);
  4.     BSP_LCD_DisplayStringAt(X, Y, (uint8_t*)pText, mode);
  5. }

Dane liczbowe można przedstawić na ekranie poprzez wprowadzenie ich do bufora, oraz zamianę przy użyciu finkcji strcpy().

Programowanie biblioteki standardowe:


W tym poście przejdę przez procedurę odpalenia wyświetlacza za pomocą standardowych bibliotek.

Na samym początku należy zdefiniować potrzebne rejestry, można je pobrać bezpośrednio z biblioteki od HAL'a.

  1. #define LCD_SWRESET             0x01   /* Software Reset */
  2. #define LCD_READ_DISPLAY_ID     0x04   /* Read display identification information */
  3. #define LCD_RDDST               0x09   /* Read Display Status */
  4. #define LCD_RDDPM               0x0A   /* Read Display Power Mode */
  5. #define LCD_RDDMADCTL           0x0B   /* Read Display MADCTL */
  6. #define LCD_RDDCOLMOD           0x0C   /* Read Display Pixel Format */
  7. #define LCD_RDDIM               0x0D   /* Read Display Image Format */
  8. #define LCD_RDDSM               0x0E   /* Read Display Signal Mode */
  9. #define LCD_RDDSDR              0x0F   /* Read Display Self-Diagnostic Result */
  10. #define LCD_SPLIN               0x10   /* Enter Sleep Mode */
  11. #define LCD_SLEEP_OUT           0x11   /* Sleep out register */
  12. #define LCD_PTLON               0x12   /* Partial Mode ON */
  13. #define LCD_NORMAL_MODE_ON      0x13   /* Normal Display Mode ON */
  14. #define LCD_DINVOFF             0x20   /* Display Inversion OFF */
  15. #define LCD_DINVON              0x21   /* Display Inversion ON */
  16. #define LCD_GAMMA               0x26   /* Gamma register */
  17. #define LCD_DISPLAY_OFF         0x28   /* Display off register */
  18. #define LCD_DISPLAY_ON          0x29   /* Display on register */
  19. #define LCD_COLUMN_ADDR         0x2A   /* Colomn address register */
  20. #define LCD_PAGE_ADDR           0x2B   /* Page address register */
  21. #define LCD_GRAM                0x2C   /* GRAM register */  
  22. #define LCD_RGBSET              0x2D   /* Color SET */  
  23. #define LCD_RAMRD               0x2E   /* Memory Read */  
  24. #define LCD_PLTAR               0x30   /* Partial Area */  
  25. #define LCD_VSCRDEF             0x33   /* Vertical Scrolling Definition */  
  26. #define LCD_TEOFF               0x34   /* Tearing Effect Line OFF */  
  27. #define LCD_TEON                0x35   /* Tearing Effect Line ON */  
  28. #define LCD_MAC                 0x36   /* Memory Access Control register*/
  29. #define LCD_VSCRSADD            0x37   /* Vertical Scrolling Start Address */  
  30. #define LCD_IDMOFF              0x38   /* Idle Mode OFF */  
  31. #define LCD_IDMON               0x39   /* Idle Mode ON */  
  32. #define LCD_PIXEL_FORMAT        0x3A   /* Pixel Format register */
  33. #define LCD_WRITE_MEM_CONTINUE  0x3C   /* Write Memory Continue */  
  34. #define LCD_READ_MEM_CONTINUE   0x3E   /* Read Memory Continue */  
  35. #define LCD_SET_TEAR_SCANLINE   0x44   /* Set Tear Scanline */  
  36. #define LCD_GET_SCANLINE        0x45   /* Get Scanline */  
  37. #define LCD_WDB                 0x51   /* Write Brightness Display register */
  38. #define LCD_RDDISBV             0x52   /* Read Display Brightness */  
  39. #define LCD_WCD                 0x53   /* Write Control Display register*/
  40. #define LCD_RDCTRLD             0x54   /* Read CTRL Display */  
  41. #define LCD_WRCABC              0x55   /* Write Content Adaptive Brightness Control */  
  42. #define LCD_RDCABC              0x56   /* Read Content Adaptive Brightness Control */  
  43. #define LCD_WRITE_CABC          0x5E   /* Write CABC Minimum Brightness */  
  44. #define LCD_READ_CABC           0x5F   /* Read CABC Minimum Brightness */  
  45. #define LCD_READ_ID1            0xDA   /* Read ID1 */
  46. #define LCD_READ_ID2            0xDB   /* Read ID2 */
  47. #define LCD_READ_ID3            0xDC   /* Read ID3 */
  48. /* Level 2 Commands */
  49. #define LCD_RGB_INTERFACE       0xB0   /* RGB Interface Signal Control */
  50. #define LCD_FRMCTR1             0xB1   /* Frame Rate Control (In Normal Mode) */
  51. #define LCD_FRMCTR2             0xB2   /* Frame Rate Control (In Idle Mode) */
  52. #define LCD_FRMCTR3             0xB3   /* Frame Rate Control (In Partial Mode) */
  53. #define LCD_INVTR               0xB4   /* Display Inversion Control */
  54. #define LCD_BPC                 0xB5   /* Blanking Porch Control register */
  55. #define LCD_DFC                 0xB6   /* Display Function Control register */
  56. #define LCD_ETMOD               0xB7   /* Entry Mode Set */
  57. #define LCD_BACKLIGHT1          0xB8   /* Backlight Control 1 */
  58. #define LCD_BACKLIGHT2          0xB9   /* Backlight Control 2 */
  59. #define LCD_BACKLIGHT3          0xBA   /* Backlight Control 3 */
  60. #define LCD_BACKLIGHT4          0xBB   /* Backlight Control 4 */
  61. #define LCD_BACKLIGHT5          0xBC   /* Backlight Control 5 */
  62. #define LCD_BACKLIGHT7          0xBE   /* Backlight Control 7 */
  63. #define LCD_BACKLIGHT8          0xBF   /* Backlight Control 8 */
  64. #define LCD_POWER1              0xC0   /* Power Control 1 register */
  65. #define LCD_POWER2              0xC1   /* Power Control 2 register */
  66. #define LCD_VCOM1               0xC5   /* VCOM Control 1 register */
  67. #define LCD_VCOM2               0xC7   /* VCOM Control 2 register */
  68. #define LCD_NVMWR               0xD0   /* NV Memory Write */
  69. #define LCD_NVMPKEY             0xD1   /* NV Memory Protection Key */
  70. #define LCD_RDNVM               0xD2   /* NV Memory Status Read */
  71. #define LCD_READ_ID4            0xD3   /* Read ID4 */
  72. #define LCD_PGAMMA              0xE0   /* Positive Gamma Correction register */
  73. #define LCD_NGAMMA              0xE1   /* Negative Gamma Correction register */
  74. #define LCD_DGAMCTRL1           0xE2   /* Digital Gamma Control 1 */
  75. #define LCD_DGAMCTRL2           0xE3   /* Digital Gamma Control 2 */
  76. #define LCD_INTERFACE           0xF6   /* Interface control register */
  77. /* Extend register commands */
  78. #define LCD_POWERA               0xCB   /* Power control A register */
  79. #define LCD_POWERB               0xCF   /* Power control B register */
  80. #define LCD_DTCA                 0xE8   /* Driver timing control A */
  81. #define LCD_DTCB                 0xEA   /* Driver timing control B */
  82. #define LCD_POWER_SEQ            0xED   /* Power on sequence register */
  83. #define LCD_3GAMMA_EN            0xF2   /* 3 Gamma enable register */
  84. #define LCD_PRC                  0xF7   /* Pump ratio control register */

Pierwsza funkcja będzie odpowiadała za włączenie i wstępną inicjalizację całego wyświetlacza. Oprócz pinów odpowiedzialnych za transmisję między po SPI należy włączyć także pin CS, WRX oraz Reset. 

  1. void Init_GPIO_For_Display(void)
  2. {
  3.     GPIO_InitTypeDef GPIO_InitDef;
  4.     SPI_InitTypeDef SPIINITSTRUCT;
  5.     Clock_Init(); //Wlaczenie potrzebnych zegarow
  6.     //WRX
  7.     GPIO_InitDef.GPIO_Pin = WRX_Pin
  8.     GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
  9.     GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
  10.     GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
  11.     GPIO_InitDef.GPIO_Speed = GPIO_Speed_25MHz;
  12.     GPIO_Init(WRX_Port, &GPIO_InitDef);
  13.     //CS
  14.     GPIO_InitDef.GPIO_Pin = CS_Pin
  15.     GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
  16.     GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
  17.     GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
  18.     GPIO_InitDef.GPIO_Speed = GPIO_Speed_25MHz;
  19.     GPIO_Init(CS_Port, &GPIO_InitDef);
  20.     CS_SET_HIGH();
  21.     //RST
  22.     GPIO_InitDef.GPIO_Pin = RST_Pin
  23.     GPIO_InitDef.GPIO_OType = GPIO_OType_PP;
  24.     GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT;
  25.     GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL;
  26.     GPIO_InitDef.GPIO_Speed = GPIO_Speed_25MHz;
  27.     GPIO_Init(RST_Port, &GPIO_InitDef);
  28.    
  29.     //Wlaczenie SPI
  30.     SPI_I2S_DeInit(LCD_SPI);
  31.      
  32.     SPIINITSTRUCT.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  33.     SPIINITSTRUCT.SPI_Mode = SPI_Mode_Master;    
  34.     SPIINITSTRUCT.SPI_DataSize = SPI_DataSize_8b;
  35.     SPIINITSTRUCT.SPI_CPOL = SPI_CPOL_Low;        
  36.     SPIINITSTRUCT.SPI_CPHA = SPI_CPHA_1Edge;      
  37.     SPIINITSTRUCT.SPI_NSS = SPI_NSS_Soft;                  
  38.     SPIINITSTRUCT.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
  39.     SPIINITSTRUCT.SPI_FirstBit = SPI_FirstBit_MSB;
  40.     SPI_Init(SPI5, &SPIINITSTRUCT);
  41.     SPI_Cmd(SPI5, ENABLE);
  42.    
  43.     //SCK MISO MOSI
  44.     GPIOINITSTRUCT.GPIO_Pin = ( LCD_SCK | LCD_MISO | LCD_MOSI );
  45.     GPIOINITSTRUCT.GPIO_Mode = GPIO_Mode_AF;
  46.     GPIOINITSTRUCT.GPIO_OType = GPIO_OType_PP;
  47.     GPIOINITSTRUCT.GPIO_Speed = GPIO_Speed_50MHz;
  48.     GPIOINITSTRUCT.GPIO_PuPd = GPIO_PuPd_UP;
  49.     GPIO_Init(SPI_LCD_PORT, &GPIOINITSTRUCT);
  50.    
  51.     //Piny SPI5 jako alternatywne
  52.     GPIO_PinAFConfig(GPIOB, LCD_SCK_PIN_SOURCE, GPIO_AF_SPI5);
  53.     GPIO_PinAFConfig(GPIOB, LCD_MISO_PIN_, GPIO_AF_SPI5);
  54.     GPIO_PinAFConfig(GPIOB, LCD_MOSI_PIN, GPIO_AF_SPI5);
  55.    
  56.     Init_LCD(); //Inicjaliza wyswietlacza prawie tak jak w cubie
  57. }

Kolejnym elementem przesłanie odpowiednich komend pod odpowiednie adresy do wyświetlacza. Ta druga została wzięta z lekką modyfikacją z przykładowego projektu dla STM32F4.

  1. void LCD_INIT_FUNCTION(void)
  2. {
  3.     CS_SET_LOW();
  4.     SEND_REGISTER_DATA(LCD_POWERB);
  5.     SEND_RAW_DATA(0x00);
  6.     SEND_RAW_DATA(0xC1);
  7.     SEND_RAW_DATA(0x30);
  8.     SEND_REGISTER_DATA(LCD_DTCA);
  9.     SEND_RAW_DATA(0x85);
  10.     SEND_RAW_DATA(0x00);
  11.     SEND_RAW_DATA(0x78);
  12.     SEND_REGISTER_DATA(LCD_DTCB);
  13.     SEND_RAW_DATA(0x00);
  14.     SEND_RAW_DATA(0x00);
  15.     SEND_REGISTER_DATA(LCD_POWER_SEQ);
  16.     SEND_RAW_DATA(0x64);
  17.     SEND_RAW_DATA(0x03);
  18.     SEND_RAW_DATA(0x12);
  19.     SEND_RAW_DATA(0x81);
  20.     SEND_REGISTER_DATA(LCD_PRC);
  21.     SEND_RAW_DATA(0x20);
  22.     SEND_REGISTER_DATA(LCD_POWER1);
  23.     SEND_RAW_DATA(0x23);
  24.     SEND_REGISTER_DATA(LCD_POWER2);
  25.     SEND_RAW_DATA(0x10);
  26.     SEND_REGISTER_DATA(LCD_VCOM1);
  27.     SEND_RAW_DATA(0x3E);
  28.     SEND_RAW_DATA(0x28);
  29.     SEND_REGISTER_DATA(LCD_VCOM2);
  30.     SEND_RAW_DATA(0x86);
  31.     SEND_REGISTER_DATA(LCD_MAC);
  32.     SEND_RAW_DATA(0x48);
  33.     SEND_REGISTER_DATA(LCD_PIXEL_FORMAT);
  34.     SEND_RAW_DATA(0x55);
  35.     SEND_REGISTER_DATA(LCD_FRC);
  36.     SEND_RAW_DATA(0x00);
  37.     SEND_RAW_DATA(0x18);
  38.     SEND_REGISTER_DATA(LCD_DFC);
  39.     SEND_RAW_DATA(0x08);
  40.     SEND_RAW_DATA(0x82);
  41.     SEND_RAW_DATA(0x27);
  42.     SEND_REGISTER_DATA(LCD_3GAMMA_EN);
  43.     SEND_RAW_DATA(0x00);
  44.     SEND_REGISTER_DATA(ILI9341_COLUMN_ADDR);
  45.     SEND_RAW_DATA(0x00);
  46.     SEND_RAW_DATA(0x00);
  47.     SEND_RAW_DATA(0x00);
  48.     SEND_RAW_DATA(0xEF);
  49.     SEND_REGISTER_DATA(ILI9341_PAGE_ADDR);
  50.     SEND_RAW_DATA(0x00);
  51.     SEND_RAW_DATA(0x00);
  52.     SEND_RAW_DATA(0x01);
  53.     SEND_RAW_DATA(0x3F);
  54.     SEND_REGISTER_DATA(ILI9341_GAMMA);
  55.     SEND_RAW_DATA(0x01);
  56.     SEND_REGISTER_DATA(ILI9341_PGAMMA);
  57.     SEND_RAW_DATA(0x0F);
  58.     SEND_RAW_DATA(0x31);
  59.     SEND_RAW_DATA(0x2B);
  60.     SEND_RAW_DATA(0x0C);
  61.     SEND_RAW_DATA(0x0E);
  62.     SEND_RAW_DATA(0x08);
  63.     SEND_RAW_DATA(0x4E);
  64.     SEND_RAW_DATA(0xF1);
  65.     SEND_RAW_DATA(0x37);
  66.     SEND_RAW_DATA(0x07);
  67.     SEND_RAW_DATA(0x10);
  68.     SEND_RAW_DATA(0x03);
  69.     SEND_RAW_DATA(0x0E);
  70.     SEND_RAW_DATA(0x09);
  71.     SEND_RAW_DATA(0x00);
  72.     SEND_REGISTER_DATA(LCD_NGAMMA);
  73.     SEND_RAW_DATA(0x00);
  74.     SEND_RAW_DATA(0x0E);
  75.     SEND_RAW_DATA(0x14);
  76.     SEND_RAW_DATA(0x03);
  77.     SEND_RAW_DATA(0x11);
  78.     SEND_RAW_DATA(0x07);
  79.     SEND_RAW_DATA(0x31);
  80.     SEND_RAW_DATA(0xC1);
  81.     SEND_RAW_DATA(0x48);
  82.     SEND_RAW_DATA(0x08);
  83.     SEND_RAW_DATA(0x0F);
  84.     SEND_RAW_DATA(0x0C);
  85.     SEND_RAW_DATA(0x31);
  86.     SEND_RAW_DATA(0x36);
  87.     SEND_RAW_DATA(0x0F);
  88.     SEND_REGISTER_DATA(LCD_SLEEP_OUT);
  89.     Delay(10000);
  90.     SEND_REGISTER_DATA(LCD_DISPLAY_ON);
  91.     SEND_REGISTER_DATA(LCD_GRAM);
  92. }

Tak więc wysłanie danych bądź rozkazów jest rozróżniane stanem na pinie WRX. Pin CS musi być w stanie niskim. Po wysłaniu przestawiany jest na wysoki.

  1. void SEND_REGISTER_DATA(uint8_t data)
  2. {
  3.     WRX_SET_LOW;
  4.     CS_SET_LOW;
  5.     SPI_SEND_DATA(LCD_SPI, data);
  6.     CS_SET_HIGH;
  7. }
  8. void SEND_RAW_DATA(uint8_t data)
  9. {
  10.     WRX_SET_HIGH;
  11.     CS_SET_LOW;
  12.     SPI_SEND_DATA(LCD_SPI, data);
  13.     CS_SET_HIGH;
  14. }

Poniżej funkcje do ustawiania potrzebnych parametrów wyświetlacza. W pierwszej kolejności orientacja. Czyli czy obraz ma być wyświetlony pionowo czy poziomo. Dodatkowo można wybrać która z dwóch warstw ma być ustawiona.

  1. void SET_ORIENTATION(uint8_t orientation)
  2. {
  3.     //orientation = 0 Pionowo1
  4.     //orientation = 1 Pionowo2
  5.     //orientation = 2 Poziomo1
  6.     //orientation = 3 Poziomo2
  7.     SEND_REGISTER_DATA(LCD_MAC);
  8.     if (0 == orientation) { SEND_RAW_DATA(0x58); }
  9.     else if (1 == orientation) { SEND_RAW_DATA(0x88); }
  10.     else if (2 == orientation) { SEND_RAW_DATA(0x28); }
  11.     else if (3 == orientation) { SEND_RAW_DATA(0xE8); }
  12. }

Jeśli chodzi o główną funckję programu to całość należy rozpocząć oczywiście od włączenia biblioteki. Kolejny krok będzie ustawienie tła wyświetlacza. Dalej można już wprowadzać znaki czy rysować po ekranie.

Włączenie bądź wyłączenie wyświetlacza można uzyskać poprzez przesłanie komendy DISPLAY_OFF czy DISPLAY_ON.

Kolejną rzeczą jest ustawienie pozycji x oraz y. Do tego należy skorzystać z następującej funkcji.

  1. void Set_Cursor(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
  2. {
  3.     SEND_REGISTER_DATA(LCD_COLUMN_ADDR);
  4.     SEND_RAW_DATA(x1 >> 8);     //Przeslanie 8 bitow z przesunieciem
  5.     SEND_RAW_DATA(x1 & 0xFF);
  6.     SEND_RAW_DATA(x2 >> 8); //Przeslanie 8 bitow
  7.     SEND_RAW_DATA(x2 & 0xFF);
  8.     SEND_REGISTER_DATA(LCD_PAGE_ADDR);
  9.     SEND_RAW_DATA(y1 >> 8);   //Przeslanie 8 bitow gornych
  10.     SEND_RAW_DATA(y1 & 0xFF);
  11.     SEND_RAW_DATA(y2 >> 8);   //Przeslanie 8 bitow
  12.     SEND_RAW_DATA(y2 & 0xFF);
  13. }

Następnie aby wyświetlić piksel na ekranie wykonuje się to poprzez:

  1. void Put_Pixel(uint16_t x, uint16_t y, uint32_t color)
  2. {
  3.     Set_Cursor(x, y, x, y);
  4.     SEND_REGISTER_DATA(LCD_GRAM);
  5.     SEND_RAW_DATA(color >> 8); // przeslanie koloru 8 bitow
  6.     SEND_RAW_DATA(color & 0xFF); //Przeslanie drugiej czesci koloru
  7. }

Teraz przykładowa funkcja zapełniająca cały ekran określonym kolorem:

  1. void Fill_Whole_LCD(uint32_t set_color)
  2. {
  3.     uint32_t n = 0;
  4.     uint32_t h_bit = 0;
  5.     uint32_t l_bit = 0;
  6.     h_bit = set_color >> 8;
  7.     l_bit = set_color & 0xFF;
  8.     Set_Cursor(0, 0, SZEROKOSC_LCD - 1, WYSOKOSC_LCD - 1);
  9.     SEND_REGISTER_DATA(LCD_GRAM);
  10.     for (= 0; n < LCD_PIXEL; n++)
  11.     {
  12.         SEND_RAW_DATA(i);
  13.         SEND_RAW_DATA(j);
  14.     }
  15. }

Do rysowania linii wykorzystałem funkcje z biblioteki Hala z niewielką modyfikacją:

  1. #define ABS(X)  ((X) > 0 ? (X) : -(X))
  2. void LCD_DrawLine(uint16_t X1, uint16_t Y1, uint16_t X2, uint16_t Y2, uint32_t color)
  3. {
  4.   int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
  5.   yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
  6.   curpixel = 0;
  7.   deltax = ABS(X2 - X1);        //Roznica pomiedzy X
  8.   deltay = ABS(Y2 - Y1);        //Roznice pomiedzy Y
  9.   x = X1;                       //Rozpoczecie od 1 pixela
  10.   y = Y1;                       //Rozpoczecie od 1 pixela
  11.   if (X2 >= X1)                 //X rosnie
  12.   {
  13.     xinc1 = 1;
  14.     xinc2 = 1;
  15.   }
  16.   else                          //X maleje
  17.   {
  18.     xinc1 = -1;
  19.     xinc2 = -1;
  20.   }
  21.   if (Y2 >= Y1)                 //Y rosnie
  22.   {
  23.     yinc1 = 1;
  24.     yinc2 = 1;
  25.   }
  26.   else                          //Y maleje
  27.   {
  28.     yinc1 = -1;
  29.     yinc2 = -1;
  30.   }
  31.   if (deltax >= deltay)         //Przynajmniej jedna wartosc X dla kazdego Y
  32.   {
  33.     xinc1 = 0;                  //Nie zmienia x kiedy numer jest wiekszy od wartosci zmniejszanej
  34.     yinc2 = 0;                  //Nie zmienia y dla kazdej iteracji
  35.     den = deltax;
  36.     num = deltax / 2;
  37.     numadd = deltay;
  38.     numpixels = deltax;         //Jest wiecej wartosci x niz y
  39.   }
  40.   else                          //Jest przynajmniej jeden y dla kazdego x
  41.   {
  42.     xinc2 = 0;                  //Nie zmieniaj x dla kazdej iteracji
  43.     yinc1 = 0;                  //Nie zmieniaj y gdy numer jest wiekszy od wartosci zmniejszanej
  44.     den = deltay;
  45.     num = deltay / 2;
  46.     numadd = deltax;
  47.     numpixels = deltay;         //Jest wiecej wartosci y niz x
  48.   }
  49.   for (curpixel = 0; curpixel <= numpixels; curpixel++)
  50.   {
  51.     Put_Pixel(x, y, color);                                     //Wyswietl piksel
  52.     num += numadd;                            //Zwieksz wartosc
  53.     if (num >= den)                           //Sprawdzenie czy wartosci zwiekszana jest rózwna zmniejszanej
  54.     {
  55.       num -= den;                             // Oblicz wartosc numeru
  56.       x += xinc1;                             //Zmien X
  57.       y += yinc1;                             //Zmien Y
  58.     }
  59.     x += xinc2;                               //Zmien X
  60.     y += yinc2;                               //Zmien Y
  61.   }
  62. }

Bibliografia

[1] STM32F429