{"id":2521,"date":"2024-05-15T13:41:00","date_gmt":"2024-05-15T13:41:00","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2521"},"modified":"2024-05-15T13:41:02","modified_gmt":"2024-05-15T13:41:02","slug":"getting-started-with-lvgl-v9-with-stm32f429-disco-part2-lcd-and-touch-initialization","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2521","title":{"rendered":"Getting Started with LvGL V9 with STM32F429-disco Part2: LCD and Touch Initialization"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"95\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/logo_lvgl-1.png\" alt=\"\" class=\"wp-image-2522\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/logo_lvgl-1.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/logo_lvgl-1-250x79.png 250w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=2509\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=2509\" target=\"_blank\">here<\/a>), we took a look what is LvGL setup the environment. In this guide, we shall initialize the LCD and the touch.<\/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>Display initialization.<\/li><li>Touch Initialization.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Display Initialization:<\/h2>\n\n\n\n<p>Before we initialize the LCD and the touch, we need to find which pins are connected to the LCD and touch driver.<\/p>\n\n\n\n<p>From the STM32F429-disco schematic, we can find the following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"578\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-1024x578.jpg\" alt=\"\" class=\"wp-image-2524\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-1024x578.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-300x169.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-768x434.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-1536x867.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-2048x1156.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-1150x649.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-750x422.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-400x225.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_16-09-55-250x141.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"360\" height=\"388\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_15-46-53.jpg\" alt=\"\" class=\"wp-image-2525\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_15-46-53.jpg 360w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_15-46-53-278x300.jpg 278w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/05\/2024-05-15_15-46-53-250x269.jpg 250w\" sizes=\"(max-width: 360px) 100vw, 360px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>We can find that the LCD data and clock line are connected to SPI5 of STM32F429 as following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>PF7 as SPI5 SCK.<\/li><li>PF9 as SPI5 MOSI. <\/li><\/ul>\n\n\n\n<p>Also,<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>PC2 as Chip select.<\/li><li>PD13 as Data Command selection.<\/li><\/ul>\n\n\n\n<p>For the touch interface, we can see that it is connected to I2C3 bus with the following pins:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>PA8 as SCL.<\/li><li>PC9 as SDA.<\/li><\/ul>\n\n\n\n<p>After obtaining all the required pins, we shall develop the following drivers:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>SPI to transmit data to the LCD using DMA.<\/li><li>I2C to get the touch values.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>Before starting developing the drive, please take a look at the following guides:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>SPI DMA from <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=2207\" target=\"_blank\">here<\/a>.<\/li><li>I2C-&gt; <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=503\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=503\" target=\"_blank\">here<\/a>, <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=524\" target=\"_blank\">here<\/a>, <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=549\" target=\"_blank\">here<\/a> and <a href=\"https:\/\/blog.embeddedexpert.io\/?p=576\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a><\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>We start off by creatine new source and header file with name of <strong><em>LCD_Pins<\/em><\/strong>.c and <strong><em>LCD_Pins<\/em><\/strong>.h respectively.<\/p>\n\n\n\n<p>Within the header file:<\/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;}\">#ifndef LCD_PINS_H_\n#define LCD_PINS_H_\n\n#include &quot;delay.h&quot;\n#include &quot;stm32f4xx.h&quot;\n\n#define LCD_RES_HIGH(void)\t\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BS7\n#define LCD_RES_LOW(void)\t\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BR7\n\n#define LCD_CS_HIGH(void)\t\t\tGPIOC-&gt;BSRR=GPIO_BSRR_BS2\n#define LCD_CS_LOW(void)\t\t\tGPIOC-&gt;BSRR=GPIO_BSRR_BR2\n\n#define LCD_DC_HIGH(void)\t\t\tGPIOD-&gt;BSRR=GPIO_BSRR_BS13\n#define LCD_DC_LOW(void)\t\t\tGPIOD-&gt;BSRR=GPIO_BSRR_BR13\n\n\n\/*SPI *\/\nvoid LCD_Pin_Init(void);\nvoid LCD_SPI_Init(void);\n\n\/*LCD*\/\nvoid LCD_RST(void);\nvoid LCD_Write_Cmd(uint8_t cmd);\nvoid LCD_Write_Data (uint8_t data);\nvoid spi5_transmit(uint8_t *data,uint32_t size);\nvoid SPI5_Transmit_DMA(uint8_t *data,uint16_t size);\n\n#endif \/* LCD_PINS_H_ *\/\n<\/pre><\/div>\n\n\n\n<p>Within the source file:<\/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;}\">#include &quot;stm32f4xx.h&quot;\n#include &quot;LCD_Pins.h&quot;\n\n#define AF05\t\t\t\t\t\t0x05\n\n\n\n\n\n\nvoid LCD_Pin_Init(void)\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIOCEN|RCC_AHB1ENR_GPIODEN|RCC_AHB1ENR_GPIOFEN;\n\n\t\/*PA7*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE7_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE7_1;\n\tGPIOA-&gt;OSPEEDR|=GPIO_OSPEEDR_OSPEED7;\n\tGPIOA-&gt;ODR|=GPIO_ODR_OD7;\n\n\t\/*PC2*\/\n\tGPIOC-&gt;MODER|=GPIO_MODER_MODE2_0;\n\tGPIOC-&gt;MODER&amp;=~GPIO_MODER_MODE2_1;\n\tGPIOC-&gt;OSPEEDR|=GPIO_OSPEEDR_OSPEED2;\n\tGPIOC-&gt;ODR|=GPIO_ODR_OD2;\n\n\n\n\t\/*PD13*\/\n\tGPIOD-&gt;MODER|=GPIO_MODER_MODE13_0;\n\tGPIOD-&gt;MODER&amp;=~GPIO_MODER_MODE13_1;\n\tGPIOD-&gt;OSPEEDR|=GPIO_OSPEEDR_OSPEED13;\n\tGPIOD-&gt;ODR|=GPIO_ODR_OD13;\n\n\t\/*PF7 and PF9 for SPI5*\/\n\n\tGPIOF-&gt;MODER|=GPIO_MODER_MODE7_1|GPIO_MODER_MODE9_1;\n\tGPIOF-&gt;MODER&amp;=~(GPIO_MODER_MODE7_0|GPIO_MODER_MODE9_0);\n\n\tGPIOF-&gt;OSPEEDR|=GPIO_OSPEEDR_OSPEED7|GPIO_OSPEEDR_OSPEED9;\n\n\tGPIOF-&gt;AFR[0]|=(AF05&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n\tGPIOF-&gt;AFR[1]|=(AF05&lt;&lt;GPIO_AFRH_AFSEL9_Pos);\n\n\n}\n\n\nvoid LCD_SPI_Init(void)\n{\n\tRCC-&gt;APB2ENR|=RCC_APB2ENR_SPI5EN;\n\tSPI5-&gt;CR1|=SPI_CR1_MSTR|SPI_CR1_SSM|SPI_CR1_SSI|SPI_CR1_BR_0;\n\n\tSPI5-&gt;CR2|=SPI_CR2_TXDMAEN;\n\n\tNVIC_EnableIRQ(SPI5_IRQn);\n\n\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_DMA2EN;\n\n\tDMA2_Stream4-&gt;CR&amp;=~(DMA_SxCR_EN);\n\n\twhile((DMA2_Stream4-&gt;CR &amp;DMA_SxCR_EN)==DMA_SxCR_EN);\n\n\tDMA2_Stream4-&gt;CR|=(0x02&lt;&lt;DMA_SxCR_CHSEL_Pos)|(DMA_SxCR_MINC)|\n\t\t\t(DMA_SxCR_DIR_0)|(DMA_SxCR_TCIE);\n\n\tNVIC_EnableIRQ(DMA2_Stream4_IRQn);\n\n\n\tSPI5-&gt;CR1|=SPI_CR1_SPE;\n\n}\n\n\nvoid spi5_transmit(uint8_t *data,uint32_t size)\n{\n\tuint32_t i=0;\n\n\n\twhile(i&lt;size)\n\t{\n\t\t\/*Wait until TXE is set*\/\n\t\twhile(!(SPI5-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\t\/*Write the data to the data register*\/\n\t\tSPI5-&gt;DR = data[i];\n\t\ti++;\n\t}\n\t\/*Wait until TXE is set*\/\n\twhile(!(SPI5-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\/*Wait for BUSY flag to reset*\/\n\twhile((SPI5-&gt;SR &amp; (SPI_SR_BSY))){}\n\n\t\/*Clear OVR flag*\/\n\t(void) SPI5-&gt;DR;\n\t(void) SPI5-&gt;SR;\n}\n\n\n\nvoid SPI5_Transmit_DMA(uint8_t *data,uint16_t size)\n{\n\tDMA2_Stream4-&gt;M0AR= (uint32_t)data;\n\tDMA2_Stream4-&gt;NDTR=size;\n\tDMA2_Stream4-&gt;PAR=(uint32_t)&amp;SPI5-&gt;DR;\n\n\tDMA2_Stream4-&gt;CR|=DMA_SxCR_EN;\n\n\n}\n\n\n\nvoid DMA2_Stream4_IRQHandler(void)\n{\n\tif(DMA2-&gt;HISR&amp;(DMA_HISR_TCIF4))\n\t{\n\t\t\/*Enable SPI Tx buffer empty interrupt *\/\n\n\t\tSPI5-&gt;CR2|=SPI_CR2_TXEIE;\n\n\t\t\/*Clear pending flag*\/\n\t\tDMA2-&gt;HIFCR |=DMA_HIFCR_CTCIF4;\n\t}\n}\n\n__WEAK void SPI5_TX_Finished(void)\n{\n\t\/*Override with user code*\/\n}\n\nvoid SPI5_IRQHandler(void)\n{\n\tif ((SPI5-&gt;SR &amp; SPI_SR_TXE) &amp;&amp; ((SPI5-&gt;SR &amp; SPI_SR_BSY)==0))\n\t{\n\t\t\/*Set finished to 1*\/\n\t\tSPI5_TX_Finished();\n\n\t\t\/*Disable SPI Tx Buffer empty interrupt*\/\n\t\tSPI5-&gt;CR2&amp;=~SPI_CR2_TXEIE;\n\n\n\n\n\t}\n}\n\n\nvoid LCD_RST(void)\n{\n\tLCD_RES_LOW();\n\tdelay(50);\n\tLCD_RES_HIGH();\n\tdelay(20);\n\n}\n\n\n\n\n\nvoid LCD_Write_Cmd(uint8_t cmd)\n{\n\tLCD_CS_LOW();\n\tLCD_DC_LOW();\n\tspi5_transmit(&amp;cmd,1);\n\tLCD_CS_HIGH();\n}\n\n\nvoid LCD_Write_Data (uint8_t data)\n{\n\tLCD_CS_LOW();\n\tLCD_DC_HIGH();\n\tspi5_transmit (&amp;data,1);\n\tLCD_CS_HIGH();\n}\n<\/pre><\/div>\n\n\n\n<p>Create new source and header file with name of<strong><em> ILI9341<\/em><\/strong>.c and ILI9341.h respectively.<\/p>\n\n\n\n<p>Within the header file:<\/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;}\">#ifndef ILI9341_H_\n#define ILI9341_H_\n\n\/\/List of includes\n#include &lt;stdbool.h&gt;\n#include &quot;delay.h&quot;\n#include &lt;stdint.h&gt;\n#include &lt;math.h&gt;\n\n\n\/\/LCD dimensions defines\n#define ILI9341_WIDTH       \t\t\t\t320\n#define ILI9341_HEIGHT      \t\t\t\t240\n\n\n#define ILI9341_PIXEL_COUNT\t\t\t\t\tILI9341_WIDTH * ILI9341_HEIGHT\n\n\n\/\/ILI9341 LCD commands\n#define ILI9341_RESET\t\t\t \t\t    0x01\n#define ILI9341_SLEEP_OUT\t\t  \t\t\t0x11\n#define ILI9341_GAMMA\t\t\t    \t\t0x26\n#define ILI9341_DISPLAY_OFF\t\t\t\t\t0x28\n#define ILI9341_DISPLAY_ON\t\t\t\t\t0x29\n#define ILI9341_COLUMN_ADDR\t\t\t\t\t0x2A\n#define ILI9341_PAGE_ADDR\t\t\t  \t\t0x2B\n#define ILI9341_GRAM\t\t\t\t    \t0x2C\n#define ILI9341_TEARING_OFF\t\t\t\t\t0x34\n#define ILI9341_TEARING_ON\t\t\t\t\t0x35\n#define ILI9341_DISPLAY_INVERSION\t\t\t0xb4\n#define ILI9341_MAC\t\t\t        \t\t0x36\n#define ILI9341_PIXEL_FORMAT    \t\t\t0x3A\n#define ILI9341_WDB\t\t\t    \t  \t\t0x51\n#define ILI9341_WCD\t\t\t\t      \t\t0x53\n#define ILI9341_RGB_INTERFACE   \t\t\t0xB0\n#define ILI9341_FRC\t\t\t\t\t    \t0xB1\n#define ILI9341_BPC\t\t\t\t\t    \t0xB5\n#define ILI9341_DFC\t\t\t\t \t    \t0xB6\n#define ILI9341_Entry_Mode_Set\t\t\t\t0xB7\n#define ILI9341_POWER1\t\t\t\t\t\t0xC0\n#define ILI9341_POWER2\t\t\t\t\t\t0xC1\n#define ILI9341_VCOM1\t\t\t\t\t\t0xC5\n#define ILI9341_VCOM2\t\t\t\t\t\t0xC7\n#define ILI9341_POWERA\t\t\t\t\t\t0xCB\n#define ILI9341_POWERB\t\t\t\t\t\t0xCF\n#define ILI9341_PGAMMA\t\t\t\t\t\t0xE0\n#define ILI9341_NGAMMA\t\t\t\t\t\t0xE1\n#define ILI9341_DTCA\t\t\t\t\t\t0xE8\n#define ILI9341_DTCB\t\t\t\t\t\t0xEA\n#define ILI9341_POWER_SEQ\t\t\t\t\t0xED\n#define ILI9341_3GAMMA_EN\t\t\t\t\t0xF2\n#define ILI9341_INTERFACE\t\t\t\t\t0xF6\n#define ILI9341_PRC\t\t\t\t   \t  \t\t0xF7\n#define ILI9341_VERTICAL_SCROLL \t\t\t0x33\n\n#define ILI9341_MEMCONTROL         \t\t\t0x36\n#define ILI9341_MADCTL_MY  \t\t\t\t\t0x80\n#define ILI9341_MADCTL_MX  \t\t\t\t\t0x40\n#define ILI9341_MADCTL_MV  \t\t\t\t\t0x20\n#define ILI9341_MADCTL_ML  \t\t\t\t\t0x10\n#define ILI9341_MADCTL_RGB \t\t\t\t\t0x00\n#define ILI9341_MADCTL_BGR \t\t\t\t\t0x08\n#define ILI9341_MADCTL_MH  \t\t\t\t\t0x04\n\n\n\n\/\/4. Initialise function\nvoid ILI9341_Init();\n\nvoid setAddrWindow(uint16_t X1, uint16_t Y1, uint16_t X2, uint16_t Y2);\n\nvoid ILI9341_DrawBitmap(uint16_t w, uint16_t h, uint8_t *s);\n\nvoid ILI9341_setRotation(uint8_t rotate);\n\n#endif\n<\/pre><\/div>\n\n\n\n<p>Within the source file:<\/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;}\">\/\/most of the functions has been documented in the interface file (ILI9341.h)\n#include &quot;ILI9341.h&quot;\n#include &quot;LCD_Pins.h&quot;\n#include &quot;stdlib.h&quot;\n\nstatic uint8_t rotationNum=1;\n\n\n\/\/initialize the tft\nvoid ILI9341_Init(void)\n{\n\n\n\tLCD_Write_Cmd (ILI9341_DISPLAY_OFF); \/\/ display off\n\t\/\/------------power control------------------------------\n\tLCD_Write_Cmd (ILI9341_POWER1); \/\/ power control\n\tLCD_Write_Data   (0x26); \/\/ GVDD = 4.75v\n\tLCD_Write_Cmd (ILI9341_POWER2); \/\/ power control\n\tLCD_Write_Data   (0x11); \/\/ AVDD=VCIx2, VGH=VCIx7, VGL=-VCIx3\n\t\/\/--------------VCOM-------------------------------------\n\tLCD_Write_Cmd (ILI9341_VCOM1); \/\/ vcom control\n\tLCD_Write_Data   (0x35); \/\/ Set the VCOMH voltage (0x35 = 4.025v)\n\tLCD_Write_Data   (0x3e); \/\/ Set the VCOML voltage (0x3E = -0.950v)\n\tLCD_Write_Cmd (ILI9341_VCOM2); \/\/ vcom control\n\tLCD_Write_Data   (0xbe);\n\n\t\/\/------------memory access control------------------------\n\tLCD_Write_Cmd (ILI9341_MAC); \/\/ memory access control\n\tLCD_Write_Data(0x48);\n\n\tLCD_Write_Cmd (ILI9341_PIXEL_FORMAT); \/\/ pixel format set\n\tLCD_Write_Data   (0x55); \/\/ 16bit \/pixel\n\n\tLCD_Write_Cmd(ILI9341_FRC);\n\tLCD_Write_Data(0);\n\tLCD_Write_Data(0x1F);\n\t\/\/-------------ddram ----------------------------\n\tLCD_Write_Cmd (ILI9341_COLUMN_ADDR); \/\/ column set\n\tLCD_Write_Data   (0x00); \/\/ x0_HIGH---0\n\tLCD_Write_Data   (0x00); \/\/ x0_LOW----0\n\tLCD_Write_Data   (0x00); \/\/ x1_HIGH---240\n\tLCD_Write_Data   (0x1D); \/\/ x1_LOW----240\n\tLCD_Write_Cmd (ILI9341_PAGE_ADDR); \/\/ page address set\n\tLCD_Write_Data   (0x00); \/\/ y0_HIGH---0\n\tLCD_Write_Data   (0x00); \/\/ y0_LOW----0\n\tLCD_Write_Data   (0x00); \/\/ y1_HIGH---320\n\tLCD_Write_Data   (0x27); \/\/ y1_LOW----320\n\n\tLCD_Write_Cmd (ILI9341_TEARING_OFF); \/\/ tearing effect off\n\t\/\/LCD_write_cmd(ILI9341_TEARING_ON); \/\/ tearing effect on\n\t\/\/LCD_write_cmd(ILI9341_DISPLAY_INVERSION); \/\/ display inversion\n\tLCD_Write_Cmd (ILI9341_Entry_Mode_Set); \/\/ entry mode set\n\t\/\/ Deep Standby Mode: OFF\n\t\/\/ Set the output level of gate driver G1-G320: Normal display\n\t\/\/ Low voltage detection: Disable\n\tLCD_Write_Data   (0x07);\n\t\/\/-----------------display------------------------\n\tLCD_Write_Cmd (ILI9341_DFC); \/\/ display function control\n\t\/\/Set the scan mode in non-display area\n\t\/\/Determine source\/VCOM output in a non-display area in the partial display mode\n\tLCD_Write_Data   (0x0a);\n\t\/\/Select whether the liquid crystal type is normally white type or normally black type\n\t\/\/Sets the direction of scan by the gate driver in the range determined by SCN and NL\n\t\/\/Select the shift direction of outputs from the source driver\n\t\/\/Sets the gate driver pin arrangement in combination with the GS bit to select the optimal scan mode for the module\n\t\/\/Specify the scan cycle interval of gate driver in non-display area when PTG to select interval scan\n\tLCD_Write_Data   (0x82);\n\t\/\/ Sets the number of lines to drive the LCD at an interval of 8 lines\n\tLCD_Write_Data   (0x27);\n\tLCD_Write_Data   (0x00); \/\/ clock divisor\n\n\tLCD_Write_Cmd (ILI9341_SLEEP_OUT); \/\/ sleep out\n\tdelay(100);\n\tLCD_Write_Cmd (ILI9341_DISPLAY_ON); \/\/ display on\n\tdelay(100);\n\tLCD_Write_Cmd (ILI9341_GRAM); \/\/ memory write\n\tdelay(5);\n\n}\n\n\/\/set the address of the pixel in the memory \nvoid setAddrWindow(uint16_t X1, uint16_t Y1, uint16_t X2, uint16_t Y2)\n{\n\n\tLCD_Write_Cmd(0x2A); \/\/ Column addr set\n\tLCD_Write_Data(X1&gt;&gt;8);\n\tLCD_Write_Data(X1);     \/\/ XSTART\n\tLCD_Write_Data(X2&gt;&gt;8);\n\tLCD_Write_Data(X2);     \/\/ XEND\n\n\tLCD_Write_Cmd(0x2B); \/\/ Row addr set\n\tLCD_Write_Data(Y1&gt;&gt;8);\n\tLCD_Write_Data(Y1);     \/\/ YSTART\n\tLCD_Write_Data(Y2&gt;&gt;8);\n\tLCD_Write_Data(Y2);     \/\/ YEND\n\n\tLCD_Write_Cmd(0x2C); \/\/ write to RAM\n}\n\n\nvoid ILI9341_setRotation(uint8_t rotate)\n{\n\tswitch(rotate)\n\t{\n\tcase 1:\n\trotationNum = 1;\n\tLCD_Write_Cmd(ILI9341_MEMCONTROL);\n\tLCD_Write_Data(ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR);\n\tbreak;\n\tcase 2:\n\trotationNum = 2;\n\tLCD_Write_Cmd(ILI9341_MEMCONTROL);\n\tLCD_Write_Data(ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR);\n\tbreak;\n\tcase 3:\n\trotationNum = 3;\n\tLCD_Write_Cmd(ILI9341_MEMCONTROL);\n\tLCD_Write_Data(ILI9341_MADCTL_MX | ILI9341_MADCTL_BGR);\n\tbreak;\n\tcase 4:\n\trotationNum = 4;\n\tLCD_Write_Cmd(ILI9341_MEMCONTROL);\n\tLCD_Write_Data(ILI9341_MADCTL_MX | ILI9341_MADCTL_MY | ILI9341_MADCTL_MV | ILI9341_MADCTL_BGR);\n\tbreak;\n\tdefault:\n\trotationNum = 1;\n\tLCD_Write_Cmd(ILI9341_MEMCONTROL);\n\tLCD_Write_Data(ILI9341_MADCTL_MY | ILI9341_MADCTL_BGR);\n\tbreak;\n\t}\n}\n\n\n\nstatic void ConvHL(uint8_t *s, int32_t l)\n{\n\tuint8_t v;\n\twhile (l &gt; 0) {\n\t\tv = *(s+1);\n\t\t*(s+1) = *s;\n\t\t*s = v;\n\t\ts += 2;\n\t\tl -= 2;\n\t}\n}\n\n\nvoid ILI9341_DrawBitmap(uint16_t w, uint16_t h, uint8_t *s)\n{\n\tLCD_Write_Cmd(0x2c);\n\tLCD_DC_HIGH();\n\tLCD_CS_LOW();\n\tConvHL(s, (int32_t)w*h*2);\n\tSPI5_Transmit_DMA((uint8_t*)s, w*h*2);\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, the LCD is ready for LvGL integration.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Touch Initialization:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Since the touch driver is connected to I2C3, we shall initialize the bus first.<\/p>\n\n\n\n<p>Create new source and header file with name i2c3.c and i2c.h respectively.<\/p>\n\n\n\n<p>Within the header file:<\/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;}\">#ifndef I2C3_H_\n#define I2C3_H_\n\n#include &quot;stdint.h&quot;\n\nvoid i2c3_init(void);\nvoid I2C3_WriteByte(uint8_t saddr,uint8_t maddr, uint8_t data);\nvoid I2C3_ReadMultiByte(uint8_t saddr,uint8_t maddr, uint8_t* data, uint16_t n);\nvoid i2c3_WriteMulti(uint8_t saddr,uint8_t maddr,uint8_t *buffer, uint8_t length);\nvoid i2c3_readByte(uint8_t saddr,uint8_t maddr, uint8_t *data);\nvoid i2c3_bus_scan(void);\n\n#endif \/* I2C3_H_ *\/<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Within the source file file:<\/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;}\">#include &quot;STM32F4xx.h&quot;\n\n#include &quot;i2c3.h&quot;\n#include &quot;stdio.h&quot;\n\n#define AF04 0x04\n\nvoid i2c3_init(void)\n{\n\t\/*GPIO Configuration*\/\n\n\t\/*Enable Clock access to GPIOA and GPIOC*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN|RCC_AHB1ENR_GPIOCEN;\n\n\t\/*GPIOA configuration*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE8_1;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE8_0;\n\n\tGPIOA-&gt;OTYPER|=GPIO_OTYPER_OT8;\n\n\tGPIOA-&gt;AFR[1]|=(AF04&lt;&lt;GPIO_AFRH_AFSEL8_Pos);\n\n\t\/*GPIOC configuration*\/\n\tGPIOC-&gt;MODER|=GPIO_MODER_MODE9_1;\n\tGPIOC-&gt;MODER&amp;=~GPIO_MODER_MODE9_0;\n\n\tGPIOC-&gt;OTYPER|=GPIO_OTYPER_OT9;\n\n\tGPIOC-&gt;AFR[1]|=(AF04&lt;&lt;GPIO_AFRH_AFSEL9_Pos);\n\n\n\t\/*I2C3 Init*\/\n\n\tRCC-&gt;APB1ENR|=RCC_APB1ENR_I2C3EN;\n\n\tI2C3-&gt;CR1=I2C_CR1_SWRST;\/\/reset i2c\n\tI2C3-&gt;CR1&amp;=~I2C_CR1_SWRST;\/\/ release reset i2c\n\tI2C3-&gt;CR2|=0x2d;\/\/set clock source to 42MHz\n\tI2C3-&gt;CCR=0xe1 ;  \/\/based on calculation\n\tI2C3-&gt;TRISE=0x2e; \/\/output max rise\n\tI2C3-&gt;CR1|=I2C_CR1_PE; \/\/enable I2C\n\n}\n\nvoid I2C3_WriteByte(uint8_t saddr,uint8_t maddr, uint8_t data)\n{\n\twhile(I2C3-&gt;SR2&amp;I2C_SR2_BUSY){;}          \/*wait until bus not busy*\/\n\tI2C3-&gt;CR1|=I2C_CR1_START;                 \/*generate start*\/\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_SB)){;}         \/*wait until start bit is set*\/\n\tI2C3-&gt;DR = saddr&lt;&lt; 1;                 \t \/* Send slave address*\/\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_ADDR)){;}      \/*wait until address flag is set*\/\n\t(void)I2C3-&gt;SR2; \t\t\t\t\t\t\t\/*clear SR2 by reading it *\/\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}       \/*Wait until Data register empty*\/\n\tI2C3-&gt;DR = maddr;                        \/* send memory address*\/\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}       \/*wait until data register empty*\/\n\tI2C3-&gt;DR = data;\n\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_BTF));      \/*wait until transfer finished*\/\n\tI2C3-&gt;CR1 |=I2C_CR1_STOP;\n}\n\nvoid I2C3_ReadMultiByte(uint8_t saddr,uint8_t maddr, uint8_t* data, uint16_t n)\n{\n\twhile (I2C3-&gt;SR2 &amp; I2C_SR2_BUSY){;}\n\tI2C3-&gt;CR1|=I2C_CR1_START;\n\twhile(!(I2C3-&gt;SR1 &amp; I2C_SR1_SB)){;}\n\tI2C3-&gt;DR=saddr&lt;&lt;1;\n\twhile(!(I2C3-&gt;SR1 &amp; I2C_SR1_ADDR)){;}\n\t(void)I2C3-&gt;SR2;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}\n\tI2C3-&gt;DR = maddr;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}\n\tI2C3-&gt;CR1|=I2C_CR1_START;\n\twhile(!(I2C3-&gt;SR1 &amp; I2C_SR1_SB)){;}\n\tI2C3-&gt;DR=saddr&lt;&lt;1|1;\n\twhile(!(I2C3-&gt;SR1 &amp; I2C_SR1_ADDR)){;}\n\t(void)I2C3-&gt;SR2;\n\tI2C3-&gt;CR1|=I2C_CR1_ACK;\n\twhile(n&gt;0U)\n\t{\n\t\tif(n==1U)\n\t\t{\n\t\t\tI2C3-&gt;CR1&amp;=~I2C_CR1_ACK;\n\t\t\tI2C3-&gt;CR1|=I2C_CR1_STOP;\n\t\t\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_RXNE)){;}\n\t\t\t*data++=I2C3-&gt;DR;\n\t\t\tbreak;\n\t\t}\n\t\telse\n\t\t{\n\t\t\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_RXNE)){;}\n\t\t\t(*data++)=I2C3-&gt;DR;\n\t\t\tn--;\n\n\t\t}\n\t}\n}\n\n\nvoid i2c3_WriteMulti(uint8_t saddr,uint8_t maddr,uint8_t *buffer, uint8_t length)\n{\n\twhile (I2C3-&gt;SR2 &amp; I2C_SR2_BUSY);           \/\/wait until bus not busy\n\tI2C3-&gt;CR1 |= I2C_CR1_START;                 \/\/generate start\n\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_SB)){;}\t\t\/\/wait until start is generated\n\n\tI2C3-&gt;DR = saddr&lt;&lt; 1;                 \t \t\/\/ Send slave address\n\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_ADDR)){;}      \/\/wait until address flag is set\n\t(void)I2C3-&gt;SR2; \t\t\t\t\t\t    \/\/Clear SR2\n\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_TXE));         \/\/Wait until Data register empty\n\tI2C3-&gt;DR = maddr;                      \t\t\/\/ send memory address\n\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_TXE));         \/\/wait until data register empty\n\t\/\/sending the data\n\tfor (uint8_t i=0;i&lt;length;i++)\n\t {\n\t\tI2C3-&gt;DR=buffer[i]; \t\t\t\t\t\/\/filling buffer with command or data\n\t\twhile (!(I2C3-&gt;SR1 &amp; I2C_SR1_BTF));\n\t }\n\n\tI2C3-&gt;CR1 |= I2C_CR1_STOP;\t\t\t\t\t\/\/wait until transfer finished\n\n}\n\n\nvoid i2c3_readByte(uint8_t saddr,uint8_t maddr, uint8_t *data)\n{\n\n\twhile(I2C3-&gt;SR2&amp;I2C_SR2_BUSY){;}\n\tI2C3-&gt;CR1|=I2C_CR1_START;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_SB)){;}\n\tI2C3-&gt;DR=saddr&lt;&lt;1;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_ADDR)){;}\n\t(void)I2C3-&gt;SR2;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}\n\tI2C3-&gt;DR=maddr;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_TXE)){;}\n\tI2C3-&gt;CR1|=I2C_CR1_START;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_SB)){;}\n\tI2C3-&gt;DR=saddr&lt;&lt;1|1;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_ADDR)){;}\n\tI2C3-&gt;CR1&amp;=~I2C_CR1_ACK;\n\t(void)I2C3-&gt;SR2;\n\tI2C3-&gt;CR1|=I2C_CR1_STOP;\n\twhile(!(I2C3-&gt;SR1&amp;I2C_SR1_RXNE)){;}\n\t*data=I2C3-&gt;DR;\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, the I2C3 is ready to communicate with i2c slave devices.<\/p>\n\n\n\n<p>For the touch controller, create new source and header file with name of <strong><em>STMPE811<\/em><\/strong>.c and <strong><em>STMPE811<\/em><\/strong>.h respectively.<\/p>\n\n\n\n<p>Within the header file:<\/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;}\">#ifndef STMPE811_H_\n#define STMPE811_H_\n\n#include &quot;stdint.h&quot;\n\n#define deviceAddress 0x41\n\n\ntypedef enum TouchDetect\n{\n\ttouched =1,\n\tno_touch=0\n\n}TouchDetect_t;\n\n\n\n#define STMPE811_REG_SYS_CTRL2 \t\t\t0x04 \/*Clock control*\/\n#define STMPE811_REG_SYS_CTRL1 \t\t\t0x03 \/*Reset control*\/\n#define STMPE811_REG_IO_AF              0x17 \/*Alternate function register*\/\n#define STMPE811_REG_ADC_CTRL1          0x20 \/*ADC control*\/\n#define STMPE811_REG_ADC_CTRL2          0x21 \/*ADC control*\/\n#define STMPE811_REG_TSC_CFG            0x41 \/*Touch Configuration*\/\n#define STMPE811_REG_FIFO_TH            0x4A \/*FIFO threshold*\/\n#define STMPE811_REG_FIFO_STA           0x4B \/*FIFO status*\/\n#define STMPE811_REG_TSC_FRACT_XYZ      0x56 \/*Touchscreen controller FRACTION_Z*\/\n#define STMPE811_REG_TSC_I_DRIVE        0x58 \/*Touchscreen controller drive*\/\n#define STMPE811_REG_TSC_CTRL           0x40 \/*touchscreen controller control register*\/\n#define STMPE811_REG_INT_CTRL\t\t\t0x09 \/*Interrupt control register*\/\n#define STMPE811_REG_INT_EN\t\t\t\t0x0A \/*Interrupt enable register*\/\n#define STMPE811_REG_INT_STA            0x0B \/*Interrupt status register*\/\n#define STMPE811_REG_TSC_DATA_INC       0x57 \/*Touchscreen controller DATA Incremental*\/\n#define STMPE811_REG_TSC_DATA_NON_INC   0xD7 \/*Touchscreen controller DATA Non-Incremental*\/\n#define STMPE811_REG_FIFO_SIZE          0x4C \/*FIFO size*\/\n\n\/*IO expander facilities*\/\n#define STMPE811_ADC_FCT                0x01\n#define STMPE811_TS_FCT                 0x02\n#define STMPE811_IO_FCT                 0x04\n#define STMPE811_TEMPSENS_FCT           0x08\n\n\n\n\/* Touch Screen Pins definition *\/\n#define STMPE811_TOUCH_YD               STMPE811_PIN_7\n#define STMPE811_TOUCH_XD               STMPE811_PIN_6\n#define STMPE811_TOUCH_YU               STMPE811_PIN_5\n#define STMPE811_TOUCH_XU               STMPE811_PIN_4\n#define STMPE811_TOUCH_IO_ALL           0x00\n\n\/* IO Pins definition *\/\n#define STMPE811_PIN_0                  0x01\n#define STMPE811_PIN_1                  0x02\n#define STMPE811_PIN_2                  0x04\n#define STMPE811_PIN_3                  0x08\n#define STMPE811_PIN_4                  0x10\n#define STMPE811_PIN_5                  0x20\n#define STMPE811_PIN_6                  0x40\n#define STMPE811_PIN_7                  0x80\n#define STMPE811_PIN_ALL                0xFF\n\n#define STMPE811_TS_CTRL_ENABLE         0x01\n#define STMPE811_TS_CTRL_STATUS         0x80\n\n\n#define Touch_XMIN \t\t\t\t\t\t390\n#define Touch_YMIN \t\t\t\t\t\t359\n#define Touch_XMAX \t\t\t\t\t\t3830\n#define Touch_YMAX \t\t\t\t\t\t3895\n#define Touch_WIDTH \t\t\t\t\t(Touch_XMAX - Touch_XMIN)\n#define Touch_HEIGHT \t\t\t\t\t(Touch_YMAX - Touch_YMIN)\n\n\n\nvoid STMPE811_Touch_Enable(void);\nTouchDetect_t isToched(void);\nvoid getTouchValue(uint16_t *X, uint16_t *Y);\nuint16_t getID(void);\n\n\n\n\n\n#endif \/* STMPE811_H_ *\/\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Within the source file:<\/p>\n\n\n\n<p><\/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;}\">#include &quot;i2c3.h&quot;\n#include &quot;STMPE811.h&quot;\n#include &quot;delay.h&quot;\n#include &quot;STM32F4xx.h&quot;\n\n\nvoid STMPE811_Touch_Enable(void)\n{\n\n\tuint8_t mode;\n\n\t\/* Power Down the stmpe811 *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_SYS_CTRL1, 2);\n\n\t\/* Wait for a delay to ensure registers erasing *\/\n\tdelay(10);\n\n\t\/* Power On the Codec after the power off =&gt; all registers are reinitialized *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_SYS_CTRL1, 0);\n\n\t\/* Wait for a delay to ensure registers erasing *\/\n\tdelay(2);\n\n\t\/*Disable clock access to GPIO*\/\n\n\ti2c3_readByte(deviceAddress, STMPE811_REG_SYS_CTRL2, &amp;mode);\n\n\tmode &amp;= ~(STMPE811_IO_FCT);\n\n\t\/* Write the new register value *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_SYS_CTRL2, mode);\n\n\n\t\/*Select TSC pins in TSC alternate mode *\/\n\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_IO_AF, STMPE811_TOUCH_IO_ALL);\n\n\n\tmode&amp;= ~(STMPE811_TS_FCT | STMPE811_ADC_FCT);\n\n\t\/* Write the new register value *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_SYS_CTRL2, mode);\n\n\n\n\t\/* Select Sample Time, bit number and ADC Reference *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_ADC_CTRL1, 0x49);\n\n\t\/* Wait for 2 ms *\/\n\tdelay(2);\n\n\t\/* Select the ADC clock speed: 3.25 MHz *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_ADC_CTRL2, 0x01);\n\n\n\n\t\/* Select 2 nF filter capacitor *\/\n\t\/* Configuration:\n\t- Touch average control    : 8 samples\n\t- Touch delay time         : 500 uS\n\t- Panel driver setting time: 500 uS\n\t*\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_TSC_CFG, 0xDA);\n\n\t\/* Configure the Touch FIFO threshold: single point reading *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_TH, 0x01);\n\n\t\/* Clear the FIFO memory content. *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, 0x01);\n\n\t\/* Put the FIFO back into operation mode  *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, 0x00);\n\n\t\/* Set the range and accuracy pf the pressure measurement (Z) :\n\t- Fractional part :7a\n\t- Whole part      :1\n\t*\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_TSC_FRACT_XYZ, 0x07);\n\n\t\/* Set the driving capability (limit) of the device for TSC pins: 50mA *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_TSC_I_DRIVE, 0x01);\n\n\t\/* Touch screen control configuration (enable TSC):\n\t- No window tracking index\n\t- XYZ acquisition mode\n\t*\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_TSC_CTRL, 0x01);\n\n\t\/*  Clear all the status pending bits if any *\/\n\tI2C3_WriteByte(deviceAddress, STMPE811_REG_INT_STA, 0xFF);\n\n\n\t\/*Delay for 5ms*\/\n\n\tdelay(5);\n\n}\n\n\n\nTouchDetect_t isToched(void)\n{\n\n\tuint8_t state=0;\n\tuint8_t value=0;\n\n\ti2c3_readByte(deviceAddress, STMPE811_REG_TSC_CTRL, &amp;value);\n\n\tvalue&amp;=STMPE811_TS_CTRL_STATUS;\n\n\tstate=(value&amp;STMPE811_TS_CTRL_STATUS)==0x80;\n\n\tif(value==STMPE811_TS_CTRL_STATUS)\n\t{\n\t\ti2c3_readByte(deviceAddress,STMPE811_REG_FIFO_SIZE, &amp;value);\n\t\tif(value&gt;0)\n\t\t{\n\t\t\treturn touched;\n\t\t}\n\t}\n\n\telse\n\t{\n\t\t\/* Clear the FIFO memory content. *\/\n\t\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, 0x01);\n\n\t\t\/* Put the FIFO back into operation mode  *\/\n\t\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, 0x00);\n\t}\n\n\n\n\treturn no_touch;\n}\n\n\n\n\nvoid getTouchValue(uint16_t *X, uint16_t *Y)\n{\n\tuint32_t uldataXYZ;\n\tuint8_t  dataXYZ[4];\n\tuint8_t mode;\n\tuint16_t localx=0,localy =0;\n\n\n\t\tI2C3_ReadMultiByte(deviceAddress, STMPE811_REG_TSC_DATA_NON_INC, dataXYZ, 4) ;\n\n\t\t\/* Calculate positions values *\/\n\t\tuldataXYZ = (dataXYZ[0] &lt;&lt; 24)|(dataXYZ[1] &lt;&lt; 16)|(dataXYZ[2] &lt;&lt; 8)|(dataXYZ[3] &lt;&lt; 0);\n\t\t*X=(uldataXYZ &gt;&gt; 20) &amp; 0x00000FFF;\n\t\t*Y= (uldataXYZ &gt;&gt;  8) &amp; 0x00000FFF;\n\n\t\t\/* Reset FIFO *\/\n\t\tmode=0x01;\n\t\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, mode);\n\n\t\t\/* Enable the FIFO again *\/\n\t\tmode=0x00;\n\t\tI2C3_WriteByte(deviceAddress, STMPE811_REG_FIFO_STA, mode);\n\n\n}\n\n\n\nuint16_t getID(void)\n{\n\tuint8_t data[2];\n\tI2C3_ReadMultiByte(deviceAddress, 0x00, data, 2);\n\tuint16_t data_re=data[0]&lt;&lt;8|data[1];\n\treturn (data_re);\n\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, the touch is ready to read the touches on the screen.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>In part 3, we shall integrate LvGL v9 and start displaying demo.<\/p>\n\n\n\n<p>Stay tuned.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we took a look what is LvGL setup the environment. In this guide, we shall initialize the LCD and the touch. In this guide, we shall cover the following: Display initialization. Touch Initialization. 1. Display Initialization: Before we initialize the LCD and the touch, we need to find which pins [&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-2521","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\/2521"}],"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=2521"}],"version-history":[{"count":2,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2521\/revisions"}],"predecessor-version":[{"id":2527,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2521\/revisions\/2527"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2521"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2521"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2521"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}