{"id":1215,"date":"2022-09-21T13:40:37","date_gmt":"2022-09-21T13:40:37","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1215"},"modified":"2022-09-21T13:40:41","modified_gmt":"2022-09-21T13:40:41","slug":"working-with-stm32f4-and-spi-tft-st7789-ips-240x240-lcd","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1215","title":{"rendered":"Working with STM32F4 and SPI-TFT: ST7789 IPS 240&#215;240 LCD"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"427\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/st7789-ips-tft-no-cs-pin.png\" alt=\"\" class=\"wp-image-1216\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/st7789-ips-tft-no-cs-pin.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/st7789-ips-tft-no-cs-pin-211x300.png 211w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/st7789-ips-tft-no-cs-pin-250x356.png 250w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>This guide shows how to interface the STM32F4 board with ST7789 TFT display.<br>The ST7789 TFT module contains a display controller with the same name: ST7789. It\u2019s a color display that uses SPI interface protocol and requires 3, 4 or 5 control pins, it\u2019s low cost and easy to use. This display is an IPS display, it comes in different sizes (1.3\u2033, 1.54\u2033 \u2026) but all of them should have the same resolution of 240\u00d7240 pixel, this means it has 57600 pixels.\u00a0<\/p>\n\n\n\n<p>TFT: Thin-Film Transistor.<br>SPI: Serial Peripheral Interface.<br>IPS: In-Plane Switching.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In this guide, we shall cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>ST7789 connection with STM32F411 Nucleo-64<\/li><li>SPI setup.<\/li><li>Macros of DC and RST pin.<\/li><li>Write data and command functions.<\/li><li>LCD initializing.<\/li><li>Support functions.<\/li><li>Code.<\/li><li>Demo<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. ST7789 Connection with STM32F411 Nucleo-64:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The connection as following:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table><tbody><tr><td>ST7789 TFT<\/td><td>STM32F411 Nucloe<\/td><\/tr><tr><td>5V<\/td><td>Vcc<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>SCL<\/td><td>PA5 (SCK)<\/td><\/tr><tr><td>SDA<\/td><td>PA7 (MOSI)<\/td><\/tr><tr><td>RES<\/td><td>PA0<\/td><\/tr><tr><td>DC<\/td><td>PA1<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence the connection as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"695\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-1024x695.png\" alt=\"\" class=\"wp-image-1217\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-1024x695.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-300x204.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-768x521.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-1536x1043.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-1150x781.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-750x509.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-400x272.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789-250x170.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789.png 1569w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Notice that this TFT has no CS (Chip select) pin which is internally connected to ground.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. SPI Setup:<\/h2>\n\n\n\n<p>Since this TFT has no CS pin, instead MODE0 of SPI, the module uses MODE3 of SPI:<\/p>\n\n\n\n<p>For detailed operation and how to initialize the SPI, check this guide from <a href=\"https:\/\/blog.embeddedexpert.io\/?p=466\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=466\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img decoding=\"async\" src=\"https:\/\/www.digikey.be\/-\/media\/Images\/Article%20Library\/TechZone%20Articles\/2019\/February\/Why%20How%20to%20Use%20Serial%20Peripheral%20Interface%20Simplify%20Connections%20Between%20Multiple%20Devices\/article-2019february-why-and-how-to-use-fig3.jpg?ts=2b333ef4-e5e4-4618-bbb7-686b1d13922e&amp;la=nl-BE\" alt=\"\" \/><\/figure>\n\n\n\n<p>From the connection, PA5 and PA7 are used by SPI1 of STM32F411. Hence we start of by enabling clock access and set PA5, PA6 and PA7 to AF5, set PA0 and PA1 to GPIO output mode:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define AF05 0x05\n\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\t\/*SPI pins*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1;\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\tGPIOA-&gt;AFR[0]|=(AF05&lt;&lt;GPIO_AFRL_AFSEL5_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFSEL6_Pos)|(AF05&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n\n\t\/*DC and RST pins*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0|GPIO_MODER_MODE1_0;\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE0_1|GPIO_MODER_MODE1_1);\n<\/pre><\/div>\n\n\n\n<p>For SPI setup:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>CPOL and CPHA is set to 1.<\/li><li>Divide the clock by 4 (Max of 25MHz for this module and the MCU is running at 100MHz).<\/li><li>Set the mode to master.<\/li><li>Software slave management. <\/li><li>Enable SPI module<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"274\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-1024x274.png\" alt=\"\" class=\"wp-image-1218\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-1024x274.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-300x80.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-768x206.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-1536x412.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-2048x549.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-1150x308.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-750x201.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-400x107.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/Screen-Shot-2022-09-21-at-4.21.31-PM-1-250x67.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SPI1EN;\n\tSPI1-&gt;CR1|=SPI_CR1_CPHA|SPI_CR1_CPOL|SPI_CR1_SSM|SPI_CR1_BR_0|SPI_CR1_SSI|SPI_CR1_MSTR|SPI_CR1_SPE;<\/pre><\/div>\n\n\n\n<p>Since we need to write multiple bytes of data, we need the following function:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\nvoid st7789_spi_transmit(uint8_t *data,uint32_t size)\n{\n\tuint32_t i=0;\n\tuint8_t temp;\n\n\twhile(i&lt;size)\n\t{\n\t\t\/*Wait until TXE is set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\t\/*Write the data to the data register*\/\n\t\tSPI1-&gt;DR=data[i];\n\t\t\/\/*spidr = data[i];\n\t\ti++;\n\t}\n\t\/*Wait until TXE is set*\/\n\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\/*Wait for BUSY flag to reset*\/\n\twhile((SPI1-&gt;SR &amp; (SPI_SR_BSY))){}\n\n\t\/*Clear OVR flag*\/\n\ttemp = SPI1-&gt;DR;\n\ttemp = SPI1-&gt;SR;\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Macros of CS and RST:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>We shall use the following to control the RST(PA0) and DC(PA1) pins:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define LCD_RST1 GPIOA-&gt;BSRR=GPIO_BSRR_BS0\n#define LCD_RST0 GPIOA-&gt;BSRR=GPIO_BSRR_BR0\n\n#define\tLCD_DC1\tGPIOA-&gt;BSRR=GPIO_BSRR_BS1\n#define\tLCD_DC0 GPIOA-&gt;BSRR=GPIO_BSRR_BR1\n<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">4. Write Command and data to the LCD:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>In order to send command, we need to set the DC to low and write the data over SPI as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\/**\n * @brief Write command to ST7789 controller\n * @param cmd -&gt; command to write\n * @return none\n *\/\n\n\n\nstatic void ST7789_WriteCommand(uint8_t cmd)\n{\n\n\tLCD_DC0;\n\tst7789_spi_transmit(&amp;cmd,1);\n}\n<\/pre><\/div>\n\n\n\n<p>And we have 2 function to write the data as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Small data which is 1 byte<\/li><li>Data which takes an argument for how bytes to be written.<\/li><\/ul>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\n\/**\n * @brief Write data to ST7789 controller\n * @param buff -&gt; pointer of data buffer\n * @param buff_size -&gt; size of the data buffer\n * @return none\n *\/\nstatic void ST7789_WriteData(uint8_t *buff, uint32_t buff_size)\n{\n\tLCD_DC1;\n\tst7789_spi_transmit(buff,buff_size);\n\n}\n\/**\n * @brief Write data to ST7789 controller, simplify for 8bit data.\n * data -&gt; data to write\n * @return none\n *\/\nstatic void ST7789_WriteSmallData(uint8_t data)\n{\n\n\tLCD_DC1;\n\tst7789_spi_transmit(&amp;data,1);\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. LCD Initializing: <\/h2>\n\n\n\n<p>In order to initialize the LCD, the following commands and data shall be sent:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\n\/**\n * @brief Initialize ST7789 controller\n * @param none\n * @return none\n *\/\nvoid ST7789_Init(void)\n{\n\tst7789_spi_init();\n\tdelay(25);\n\tLCD_RST0;\n\tdelay(50);\n    LCD_RST1;\n    delay(50);\n    ST7789_WriteCommand(ST7789_SWRESET);\n    delay(100);\n    ST7789_WriteCommand(ST7789_COLMOD);\t\t\/\/\tSet color mode\n    ST7789_WriteSmallData(ST7789_COLOR_MODE_16bit);\n  \tST7789_WriteCommand(0xB2);\t\t\t\t\/\/\tPorch control\n\tuint8_t data[] = {0x0C, 0x0C, 0x00, 0x33, 0x33};\n\tST7789_WriteData(data, sizeof(data));\n\n\t\/* Internal LCD Voltage generator settings *\/\n    ST7789_WriteCommand(0XB7);\t\t\t\t\/\/\tGate Control\n    ST7789_WriteSmallData(0x35);\t\t\t\/\/\tDefault value\n    ST7789_WriteCommand(0xBB);\t\t\t\t\/\/\tVCOM setting\n    ST7789_WriteSmallData(0x20);\t\t\t\/\/\t0.725v (default 0.75v for 0x20)\n    ST7789_WriteCommand(0xC0);\t\t\t\t\/\/\tLCMCTRL\n    ST7789_WriteSmallData (0x2C);\t\t\t\/\/\tDefault value\n    ST7789_WriteCommand (0xC2);\t\t\t\t\/\/\tVDV and VRH command Enable\n    ST7789_WriteSmallData (0x01);\t\t\t\/\/\tDefault value\n    ST7789_WriteCommand (0xC3);\t\t\t\t\/\/\tVRH set\n    ST7789_WriteSmallData (0x0b);\t\t\t\/\/\t+-4.45v (defalut +-4.1v for 0x0B)\n    ST7789_WriteCommand (0xC4);\t\t\t\t\/\/\tVDV set\n    ST7789_WriteSmallData (0x20);\t\t\t\/\/\tDefault value\n    ST7789_WriteCommand (0xC6);\t\t\t\t\/\/\tFrame rate control in normal mode\n    ST7789_WriteSmallData (0x0F);\t\t\t\/\/\tDefault value (60HZ)\n    ST7789_WriteCommand (0xD0);\t\t\t\t\/\/\tPower control\n    ST7789_WriteSmallData (0xA4);\t\t\t\/\/\tDefault value\n    ST7789_WriteSmallData (0xA1);\t\t\t\/\/\tDefault value\n\t\/**************** Division line ****************\/\n\n\tST7789_WriteCommand(0xE0);\n\t{\n\t\tuint8_t data[] = {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23};\n\t\tST7789_WriteData(data, sizeof(data));\n\t}\n\n    ST7789_WriteCommand(0xE1);\n\t{\n\t\tuint8_t data[] = {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23};\n\t\tST7789_WriteData(data, sizeof(data));\n\t}\n    ST7789_WriteCommand (ST7789_INVON);\t\t\/\/\tInversion ON\n\tST7789_WriteCommand (ST7789_SLPOUT);\t\/\/\tOut of sleep mode\n  \tST7789_WriteCommand (ST7789_NORON);\t\t\/\/\tNormal Display on\n  \tST7789_WriteCommand (ST7789_DISPON);\t\/\/\tMain screen turned on\n\n  \tdelay(50);\n\tST7789_Fill_Color(BLACK);\t\t\t\t\/\/\tFill with Black.\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Supporting function:<\/h2>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">\n\/**\n * @brief Set the rotation direction of the display\n * @param m -&gt; rotation parameter(please refer it in st7789.h)\n * @return none\n *\/\nvoid ST7789_SetRotation(uint8_t m)\n{\n\tST7789_WriteCommand(ST7789_MADCTL);\t\/\/ MADCTL\n\tswitch (m) {\n\tcase 0:\n\t\tST7789_WriteSmallData(ST7789_MADCTL_MX | ST7789_MADCTL_MY | ST7789_MADCTL_RGB);\n\t\tbreak;\n\tcase 1:\n\t\tST7789_WriteSmallData(ST7789_MADCTL_MY | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);\n\t\tbreak;\n\tcase 2:\n\t\tST7789_WriteSmallData(ST7789_MADCTL_RGB);\n\t\tbreak;\n\tcase 3:\n\t\tST7789_WriteSmallData(ST7789_MADCTL_MX | ST7789_MADCTL_MV | ST7789_MADCTL_RGB);\n\t\tbreak;\n\tdefault:\n\t\tbreak;\n\t}\n}\n\n\/**\n * @brief Set address of DisplayWindow\n * @param xi&amp;yi -&gt; coordinates of window\n * @return none\n *\/\nstatic void ST7789_SetAddressWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1)\n{\n\tuint16_t x_start = x0 + X_SHIFT, x_end = x1 + X_SHIFT;\n\tuint16_t y_start = y0 + Y_SHIFT, y_end = y1 + Y_SHIFT;\n\n\t\/* Column Address set *\/\n\tST7789_WriteCommand(ST7789_CASET);\n\t{\n\t\tuint8_t data[] = {x_start &gt;&gt; 8, x_start &amp; 0xFF, x_end &gt;&gt; 8, x_end &amp; 0xFF};\n\t\tST7789_WriteData(data, sizeof(data));\n\t}\n\n\t\/* Row Address set *\/\n\tST7789_WriteCommand(ST7789_RASET);\n\t{\n\t\tuint8_t data[] = {y_start &gt;&gt; 8, y_start &amp; 0xFF, y_end &gt;&gt; 8, y_end &amp; 0xFF};\n\t\tST7789_WriteData(data, sizeof(data));\n\t}\n\t\/* Write to RAM *\/\n\tST7789_WriteCommand(ST7789_RAMWR);\n}\n\n\/**\n * @brief Fill the DisplayWindow with single color\n * @param color -&gt; color to Fill with\n * @return none\n *\/\nvoid ST7789_Fill_Color(uint16_t color)\n{\n\tuint16_t i;\n\tST7789_SetAddressWindow(0, 0, ST7789_WIDTH - 1, ST7789_HEIGHT - 1);\n\n\t\tuint16_t j;\n\t\tfor (i = 0; i &lt; ST7789_WIDTH; i++)\n\t\t\t\tfor (j = 0; j &lt; ST7789_HEIGHT; j++) {\n\t\t\t\t\tuint8_t data[] = {color &gt;&gt; 8, color &amp; 0xFF};\n\t\t\t\t\tST7789_WriteData(data, sizeof(data));\n\t\t\t\t}\n\n}\n\n\/**\n * @brief Draw a Pixel\n * @param x&amp;y -&gt; coordinate to Draw\n * @param color -&gt; color of the Pixel\n * @return none\n *\/\nvoid ST7789_DrawPixel(uint16_t x, uint16_t y, uint16_t color)\n{\n\tif ((x &lt; 0) || (x &gt;= ST7789_WIDTH) ||\n\t\t (y &lt; 0) || (y &gt;= ST7789_HEIGHT))\treturn;\n\n\tST7789_SetAddressWindow(x, y, x, y);\n\tuint8_t data[] = {color &gt;&gt; 8, color &amp; 0xFF};\n\tST7789_WriteData(data, sizeof(data));\n}\n\n\/**\n * @brief Fill an Area with single color\n * @param xSta&amp;ySta -&gt; coordinate of the start point\n * @param xEnd&amp;yEnd -&gt; coordinate of the end point\n * @param color -&gt; color to Fill with\n * @return none\n *\/\nvoid ST7789_Fill(uint16_t xSta, uint16_t ySta, uint16_t xEnd, uint16_t yEnd, uint16_t color)\n{\n\tif ((xEnd &lt; 0) || (xEnd &gt;= ST7789_WIDTH) ||\n\t\t (yEnd &lt; 0) || (yEnd &gt;= ST7789_HEIGHT))\treturn;\n\tuint16_t i, j;\n\tST7789_SetAddressWindow(xSta, ySta, xEnd, yEnd);\n\tfor (i = ySta; i &lt;= yEnd; i++)\n\t\tfor (j = xSta; j &lt;= xEnd; j++) {\n\t\t\tuint8_t data[] = {color &gt;&gt; 8, color &amp; 0xFF};\n\t\t\tST7789_WriteData(data, sizeof(data));\n\t\t}\n}\n\n\/**\n * @brief Draw a big Pixel at a point\n * @param x&amp;y -&gt; coordinate of the point\n * @param color -&gt; color of the Pixel\n * @return none\n *\/\nvoid ST7789_DrawPixel_4px(uint16_t x, uint16_t y, uint16_t color)\n{\n\tif ((x &lt;= 0) || (x &gt; ST7789_WIDTH) ||\n\t\t (y &lt;= 0) || (y &gt; ST7789_HEIGHT))\treturn;\n\n\tST7789_Fill(x - 1, y - 1, x + 1, y + 1, color);\n\n}\n\n\/**\n * @brief Draw a line with single color\n * @param x1&amp;y1 -&gt; coordinate of the start point\n * @param x2&amp;y2 -&gt; coordinate of the end point\n * @param color -&gt; color of the line to Draw\n * @return none\n *\/\nvoid ST7789_DrawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1,\n        uint16_t color) {\n\tuint16_t swap;\n    uint16_t steep = ABS(y1 - y0) &gt; ABS(x1 - x0);\n    if (steep) {\n\t\tswap = x0;\n\t\tx0 = y0;\n\t\ty0 = swap;\n\n\t\tswap = x1;\n\t\tx1 = y1;\n\t\ty1 = swap;\n        \/\/_swap_int16_t(x0, y0);\n        \/\/_swap_int16_t(x1, y1);\n    }\n\n    if (x0 &gt; x1) {\n\t\tswap = x0;\n\t\tx0 = x1;\n\t\tx1 = swap;\n\n\t\tswap = y0;\n\t\ty0 = y1;\n\t\ty1 = swap;\n        \/\/_swap_int16_t(x0, x1);\n        \/\/_swap_int16_t(y0, y1);\n    }\n\n    int16_t dx, dy;\n    dx = x1 - x0;\n    dy = ABS(y1 - y0);\n\n    int16_t err = dx \/ 2;\n    int16_t ystep;\n\n    if (y0 &lt; y1) {\n        ystep = 1;\n    } else {\n        ystep = -1;\n    }\n\n    for (; x0&lt;=x1; x0++) {\n        if (steep) {\n            ST7789_DrawPixel(y0, x0, color);\n        } else {\n            ST7789_DrawPixel(x0, y0, color);\n        }\n        err -= dy;\n        if (err &lt; 0) {\n            y0 += ystep;\n            err += dx;\n        }\n    }\n}\n\n\/**\n * @brief Draw a Rectangle with single color\n * @param xi&amp;yi -&gt; 2 coordinates of 2 top points.\n * @param color -&gt; color of the Rectangle line\n * @return none\n *\/\nvoid ST7789_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)\n{\n\n\tST7789_DrawLine(x1, y1, x2, y1, color);\n\tST7789_DrawLine(x1, y1, x1, y2, color);\n\tST7789_DrawLine(x1, y2, x2, y2, color);\n\tST7789_DrawLine(x2, y1, x2, y2, color);\n\n}\n\n\/**\n * @brief Draw a circle with single color\n * @param x0&amp;y0 -&gt; coordinate of circle center\n * @param r -&gt; radius of circle\n * @param color -&gt; color of circle line\n * @return  none\n *\/\nvoid ST7789_DrawCircle(uint16_t x0, uint16_t y0, uint8_t r, uint16_t color)\n{\n\tint16_t f = 1 - r;\n\tint16_t ddF_x = 1;\n\tint16_t ddF_y = -2 * r;\n\tint16_t x = 0;\n\tint16_t y = r;\n\n\n\tST7789_DrawPixel(x0, y0 + r, color);\n\tST7789_DrawPixel(x0, y0 - r, color);\n\tST7789_DrawPixel(x0 + r, y0, color);\n\tST7789_DrawPixel(x0 - r, y0, color);\n\n\twhile (x &lt; y) {\n\t\tif (f &gt;= 0) {\n\t\t\ty--;\n\t\t\tddF_y += 2;\n\t\t\tf += ddF_y;\n\t\t}\n\t\tx++;\n\t\tddF_x += 2;\n\t\tf += ddF_x;\n\n\t\tST7789_DrawPixel(x0 + x, y0 + y, color);\n\t\tST7789_DrawPixel(x0 - x, y0 + y, color);\n\t\tST7789_DrawPixel(x0 + x, y0 - y, color);\n\t\tST7789_DrawPixel(x0 - x, y0 - y, color);\n\n\t\tST7789_DrawPixel(x0 + y, y0 + x, color);\n\t\tST7789_DrawPixel(x0 - y, y0 + x, color);\n\t\tST7789_DrawPixel(x0 + y, y0 - x, color);\n\t\tST7789_DrawPixel(x0 - y, y0 - x, color);\n\t}\n\n}\n\n\/**\n * @brief Draw an Image on the screen\n * @param x&amp;y -&gt; start point of the Image\n * @param w&amp;h -&gt; width &amp; height of the Image to Draw\n * @param data -&gt; pointer of the Image array\n * @return none\n *\/\nvoid ST7789_DrawImage(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t *data)\n{\n\tif ((x &gt;= ST7789_WIDTH) || (y &gt;= ST7789_HEIGHT))\n\t\treturn;\n\tif ((x + w - 1) &gt;= ST7789_WIDTH)\n\t\treturn;\n\tif ((y + h - 1) &gt;= ST7789_HEIGHT)\n\t\treturn;\n\n\n\tST7789_SetAddressWindow(x, y, x + w - 1, y + h - 1);\n\tST7789_WriteData((uint8_t *)data, sizeof(uint16_t) * w * h);\n\n}\n\n\/**\n * @brief Invert Fullscreen color\n * @param invert -&gt; Whether to invert\n * @return none\n *\/\nvoid ST7789_InvertColors(uint8_t invert)\n{\n\n\tST7789_WriteCommand(invert ? 0x21 \/* INVON *\/ : 0x20 \/* INVOFF *\/);\n\n}\n\n\/**\n * @brief Write a char\n * @param  x&amp;y -&gt; cursor of the start point.\n * @param ch -&gt; char to write\n * @param font -&gt; fontstyle of the string\n * @param color -&gt; color of the char\n * @param bgcolor -&gt; background color of the char\n * @return  none\n *\/\nvoid ST7789_WriteChar(uint16_t x, uint16_t y, char ch, FontDef font, uint16_t color, uint16_t bgcolor)\n{\n\tuint32_t i, b, j;\n\n\tST7789_SetAddressWindow(x, y, x + font.width - 1, y + font.height - 1);\n\n\tfor (i = 0; i &lt; font.height; i++) {\n\t\tb = font.data[(ch - 32) * font.height + i];\n\t\tfor (j = 0; j &lt; font.width; j++) {\n\t\t\tif ((b &lt;&lt; j) &amp; 0x8000) {\n\t\t\t\tuint8_t data[] = {color &gt;&gt; 8, color &amp; 0xFF};\n\t\t\t\tST7789_WriteData(data, sizeof(data));\n\t\t\t}\n\t\t\telse {\n\t\t\t\tuint8_t data[] = {bgcolor &gt;&gt; 8, bgcolor &amp; 0xFF};\n\t\t\t\tST7789_WriteData(data, sizeof(data));\n\t\t\t}\n\t\t}\n\t}\n\n}\n\n\/**\n * @brief Write a string\n * @param  x&amp;y -&gt; cursor of the start point.\n * @param str -&gt; string to write\n * @param font -&gt; fontstyle of the string\n * @param color -&gt; color of the string\n * @param bgcolor -&gt; background color of the string\n * @return  none\n *\/\nvoid ST7789_WriteString(uint16_t x, uint16_t y, const char *str, FontDef font, uint16_t color, uint16_t bgcolor)\n{\n\n\twhile (*str) {\n\t\tif (x + font.width &gt;= ST7789_WIDTH) {\n\t\t\tx = 0;\n\t\t\ty += font.height;\n\t\t\tif (y + font.height &gt;= ST7789_HEIGHT) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (*str == ' ') {\n\t\t\t\t\/\/ skip spaces in the beginning of the new line\n\t\t\t\tstr++;\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\tST7789_WriteChar(x, y, *str, font, color, bgcolor);\n\t\tx += font.width;\n\t\tstr++;\n\t}\n\n}\n\n\/**\n * @brief Draw a filled Rectangle with single color\n * @param  x&amp;y -&gt; coordinates of the starting point\n * @param w&amp;h -&gt; width &amp; height of the Rectangle\n * @param color -&gt; color of the Rectangle\n * @return  none\n *\/\nvoid ST7789_DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t color)\n{\n\n\tuint8_t i;\n\n\t\/* Check input parameters *\/\n\tif (x &gt;= ST7789_WIDTH ||\n\t\ty &gt;= ST7789_HEIGHT) {\n\t\t\/* Return error *\/\n\t\treturn;\n\t}\n\n\t\/* Check width and height *\/\n\tif ((x + w) &gt;= ST7789_WIDTH) {\n\t\tw = ST7789_WIDTH - x;\n\t}\n\tif ((y + h) &gt;= ST7789_HEIGHT) {\n\t\th = ST7789_HEIGHT - y;\n\t}\n\n\t\/* Draw lines *\/\n\tfor (i = 0; i &lt;= h; i++) {\n\t\t\/* Draw lines *\/\n\t\tST7789_DrawLine(x, y + i, x + w, y + i, color);\n\t}\n\n}\n\n\/**\n * @brief Draw a Triangle with single color\n * @param  xi&amp;yi -&gt; 3 coordinates of 3 top points.\n * @param color -&gt;color of the lines\n * @return  none\n *\/\nvoid ST7789_DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)\n{\n\n\t\/* Draw lines *\/\n\tST7789_DrawLine(x1, y1, x2, y2, color);\n\tST7789_DrawLine(x2, y2, x3, y3, color);\n\tST7789_DrawLine(x3, y3, x1, y1, color);\n\n}\n\n\/**\n * @brief Draw a filled Triangle with single color\n * @param  xi&amp;yi -&gt; 3 coordinates of 3 top points.\n * @param color -&gt;color of the triangle\n * @return  none\n *\/\nvoid ST7789_DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3, uint16_t color)\n{\n\n\tint16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,\n\t\t\tyinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,\n\t\t\tcurpixel = 0;\n\n\tdeltax = ABS(x2 - x1);\n\tdeltay = ABS(y2 - y1);\n\tx = x1;\n\ty = y1;\n\n\tif (x2 &gt;= x1) {\n\t\txinc1 = 1;\n\t\txinc2 = 1;\n\t}\n\telse {\n\t\txinc1 = -1;\n\t\txinc2 = -1;\n\t}\n\n\tif (y2 &gt;= y1) {\n\t\tyinc1 = 1;\n\t\tyinc2 = 1;\n\t}\n\telse {\n\t\tyinc1 = -1;\n\t\tyinc2 = -1;\n\t}\n\n\tif (deltax &gt;= deltay) {\n\t\txinc1 = 0;\n\t\tyinc2 = 0;\n\t\tden = deltax;\n\t\tnum = deltax \/ 2;\n\t\tnumadd = deltay;\n\t\tnumpixels = deltax;\n\t}\n\telse {\n\t\txinc2 = 0;\n\t\tyinc1 = 0;\n\t\tden = deltay;\n\t\tnum = deltay \/ 2;\n\t\tnumadd = deltax;\n\t\tnumpixels = deltay;\n\t}\n\n\tfor (curpixel = 0; curpixel &lt;= numpixels; curpixel++) {\n\t\tST7789_DrawLine(x, y, x3, y3, color);\n\n\t\tnum += numadd;\n\t\tif (num &gt;= den) {\n\t\t\tnum -= den;\n\t\t\tx += xinc1;\n\t\t\ty += yinc1;\n\t\t}\n\t\tx += xinc2;\n\t\ty += yinc2;\n\t}\n\n}\n\n\/**\n * @brief Draw a Filled circle with single color\n * @param x0&amp;y0 -&gt; coordinate of circle center\n * @param r -&gt; radius of circle\n * @param color -&gt; color of circle\n * @return  none\n *\/\nvoid ST7789_DrawFilledCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color)\n{\n\n\tint16_t f = 1 - r;\n\tint16_t ddF_x = 1;\n\tint16_t ddF_y = -2 * r;\n\tint16_t x = 0;\n\tint16_t y = r;\n\n\tST7789_DrawPixel(x0, y0 + r, color);\n\tST7789_DrawPixel(x0, y0 - r, color);\n\tST7789_DrawPixel(x0 + r, y0, color);\n\tST7789_DrawPixel(x0 - r, y0, color);\n\tST7789_DrawLine(x0 - r, y0, x0 + r, y0, color);\n\n\twhile (x &lt; y) {\n\t\tif (f &gt;= 0) {\n\t\t\ty--;\n\t\t\tddF_y += 2;\n\t\t\tf += ddF_y;\n\t\t}\n\t\tx++;\n\t\tddF_x += 2;\n\t\tf += ddF_x;\n\n\t\tST7789_DrawLine(x0 - x, y0 + y, x0 + x, y0 + y, color);\n\t\tST7789_DrawLine(x0 + x, y0 - y, x0 - x, y0 - y, color);\n\n\t\tST7789_DrawLine(x0 + y, y0 + x, x0 - y, y0 + x, color);\n\t\tST7789_DrawLine(x0 + y, y0 - x, x0 - y, y0 - x, color);\n\t}\n\n}\n\n\n\/**\n * @brief Open\/Close tearing effect line\n * @param tear -&gt; Whether to tear\n * @return none\n *\/\nvoid ST7789_TearEffect(uint8_t tear)\n{\n\n\tST7789_WriteCommand(tear ? 0x35 \/* TEON *\/ : 0x34 \/* TEOFF *\/);\n\n}\n\n\n\/**\n * @brief A Simple test function for ST7789\n * @param  none\n * @return  none\n *\/\nvoid ST7789_Test(void)\n{\n\tST7789_Fill_Color(WHITE);\n\tdelay(1000);\n\tST7789_WriteString(10, 20, &quot;Speed Test&quot;, Font_11x18, RED, WHITE);\n\tdelay(1000);\n\tST7789_Fill_Color(CYAN);\n    delay(500);\n\tST7789_Fill_Color(RED);\n    delay(500);\n\tST7789_Fill_Color(BLUE);\n    delay(500);\n\tST7789_Fill_Color(GREEN);\n    delay(500);\n\tST7789_Fill_Color(YELLOW);\n    delay(500);\n\tST7789_Fill_Color(BROWN);\n    delay(500);\n\tST7789_Fill_Color(DARKBLUE);\n    delay(500);\n\tST7789_Fill_Color(MAGENTA);\n    delay(500);\n\tST7789_Fill_Color(LIGHTGREEN);\n    delay(500);\n\tST7789_Fill_Color(LGRAY);\n    delay(500);\n\tST7789_Fill_Color(LBBLUE);\n    delay(500);\n\tST7789_Fill_Color(WHITE);\n\tdelay(500);\n\n\tST7789_WriteString(10, 10, &quot;Font test.&quot;, Font_16x26, GBLUE, WHITE);\n\tST7789_WriteString(10, 50, &quot;Hello Steve!&quot;, Font_7x10, RED, WHITE);\n\tST7789_WriteString(10, 75, &quot;Hello Steve!&quot;, Font_11x18, YELLOW, WHITE);\n\tST7789_WriteString(10, 100, &quot;Hello Steve!&quot;, Font_16x26, MAGENTA, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Rect.\/Line.&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawRectangle(30, 30, 100, 100, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Filled Rect.&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawFilledRectangle(30, 30, 50, 50, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Circle.&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawCircle(60, 60, 25, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Filled Cir.&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawFilledCircle(60, 60, 25, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Triangle&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawTriangle(30, 30, 30, 70, 60, 40, WHITE);\n\tdelay(1000);\n\n\tST7789_Fill_Color(RED);\n\tST7789_WriteString(10, 10, &quot;Filled Tri&quot;, Font_11x18, YELLOW, BLACK);\n\tST7789_DrawFilledTriangle(30, 30, 30, 70, 60, 40, WHITE);\n\tdelay(1000);\n\n\t\/\/\tIf FLASH cannot storage anymore datas, please delete codes below.\n\tST7789_Fill_Color(WHITE);\n\tST7789_DrawImage(0, 0, 128, 128, (uint16_t *)saber);\n\tdelay(3000);\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Code:<\/h2>\n\n\n\n<p>You may download the code from here<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789_IPS_TFT.zip\">ST7789_IPS_TFT<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/09\/ST7789_IPS_TFT.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Demo:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"ST7789 with STM32\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/TLigjD8iREo?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This guide shows how to interface the STM32F4 board with ST7789 TFT display.The ST7789 TFT module contains a display controller with the same name: ST7789. It\u2019s a color display that uses SPI interface protocol and requires 3, 4 or 5 control pins, it\u2019s low cost and easy to use. This display is an IPS display, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,19,11,12],"tags":[],"class_list":["post-1215","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-lcd","category-peripheral-drivers","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1215"}],"collection":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1215"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1215\/revisions"}],"predecessor-version":[{"id":1220,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1215\/revisions\/1220"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1215"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1215"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1215"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}