{"id":2283,"date":"2024-01-17T05:38:30","date_gmt":"2024-01-17T05:38:30","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2283"},"modified":"2024-01-17T05:38:33","modified_gmt":"2024-01-17T05:38:33","slug":"getting-started-with-lvgl-part-2-display-interface","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2283","title":{"rendered":"Getting Started with LvGL Part 2: Display interface"},"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\/01\/logo_lvgl-1.png\" alt=\"\" class=\"wp-image-2284\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/logo_lvgl-1.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/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>In the previous guide (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=2274\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=2274\" target=\"_blank\">here<\/a>), we took a look at LvGL and its feature and initialized the environment to make it work. In part two, we shall interface the TFT and display the demo.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Including LvGL into the project:<\/h2>\n\n\n\n<p>First, head to LvGL github page from <a href=\"https:\/\/github.com\/lvgl\/lvgl\" data-type=\"URL\" data-id=\"https:\/\/github.com\/lvgl\/lvgl\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Select V8.3 from here:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"410\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-1024x410.jpg\" alt=\"\" class=\"wp-image-2286\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-1024x410.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-300x120.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-768x307.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-1536x615.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-2048x819.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-1150x460.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-750x300.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-400x160.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-38-23-250x100.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next, download as zip from here:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"277\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-1024x277.jpg\" alt=\"\" class=\"wp-image-2287\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-1024x277.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-300x81.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-768x207.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-1536x415.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-2048x553.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-1150x311.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-750x203.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-400x108.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-39-50-250x68.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Extract the files and rename the folder to be LvGL and copy it to the driver folder of the project.<\/p>\n\n\n\n<p>Also, create new header within the driver folder with name of lv_conf.h<\/p>\n\n\n\n<p>Hence, the drive folder should be like this:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"488\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49-488x1024.jpg\" alt=\"\" class=\"wp-image-2288\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49-488x1024.jpg 488w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49-143x300.jpg 143w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49-400x840.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49-250x525.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-44-49.jpg 624w\" sizes=\"(max-width: 488px) 100vw, 488px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, open lv_conf.h and copy the content lv_conf_template.h from <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/lvgl\/lvgl\/blob\/release\/v8.3\/lv_conf_template.h\" data-type=\"URL\" data-id=\"https:\/\/github.com\/lvgl\/lvgl\/blob\/release\/v8.3\/lv_conf_template.h\" target=\"_blank\">here<\/a>.<\/p>\n\n\n\n<p>Now, we start modifying:<\/p>\n\n\n\n<p>At line 15 set if 0 to if 1 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;}\">#if 1<\/pre><\/div>\n\n\n\n<p>At line 27 set the color depth to 16 since the screen is RGB565.<\/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 LV_COLOR_DEPTH 16<\/pre><\/div>\n\n\n\n<p>Line 52 is for the memory of the LvGL:<\/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 LV_MEM_SIZE (48U * 1024U) <\/pre><\/div>\n\n\n\n<p>For now, keep it to default of 48KB (depending on your application).<\/p>\n\n\n\n<p>At line 752, enable the widget demo:<\/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 LV_USE_DEMO_WIDGETS 1<\/pre><\/div>\n\n\n\n<p>This will allow us to run the demo on the screen.<\/p>\n\n\n\n<p>Save the changes to the file.<\/p>\n\n\n\n<p>Now right click on the project and select properties as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"872\" height=\"1024\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-872x1024.jpg\" alt=\"\" class=\"wp-image-2289\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-872x1024.jpg 872w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-256x300.jpg 256w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-768x902.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-1308x1536.jpg 1308w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-1150x1350.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-750x880.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-400x470.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32-250x293.jpg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-56-32.jpg 1426w\" sizes=\"(max-width: 872px) 100vw, 872px\" \/><\/figure>\n\n\n\n<p>Then go to C\/C++ build,  settings, then MCU GCC Compiler include paths:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-1024x683.jpg\" alt=\"\" class=\"wp-image-2290\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-1024x683.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-300x200.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-768x512.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-1536x1024.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-2048x1365.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-1150x767.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-750x500.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-400x267.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/2024-01-17_07-59-34-250x167.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In include path:<\/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;}\">&quot;${workspace_loc:\/${ProjName}\/Drivers\/lvgl}&quot;<\/pre><\/div>\n\n\n\n<p>In include files:<\/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;}\">&quot;${workspace_loc:\/${ProjName}\/Drivers\/lvgl\/lvgl.h}&quot;<\/pre><\/div>\n\n\n\n<p>Click on apply and close. <\/p>\n\n\n\n<p>Next open the base_time.c source file:<\/p>\n\n\n\n<p>Include the lvgl.h header file 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;}\">#include &quot;lvgl.h&quot;<\/pre><\/div>\n\n\n\n<p>Within the systick interrupt handler, call lv_tick_inc(1) 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;}\">\t\/*Call LvGL tick function*\/\n\tlv_tick_inc(1);<\/pre><\/div>\n\n\n\n<p>Hence, the updated systick handler is 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;}\">\/*Interrupt handler of SysTick*\/\nvoid SysTick_Handler(void)\n{\n\t\/*Increment the counter with every interrupt*\/\n\tmil++;\n\n\t\/*Call LvGL tick function*\/\n\tlv_tick_inc(1);\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, create new source and header file with name of LCDController.c and LCDController.h<\/p>\n\n\n\n<p>Within LCDController.h:<\/p>\n\n\n\n<p>Get the content from <a href=\"https:\/\/github.com\/lvgl\/lvgl\/blob\/master\/examples\/porting\/lv_port_disp_template.h\" data-type=\"URL\" data-id=\"https:\/\/github.com\/lvgl\/lvgl\/blob\/master\/examples\/porting\/lv_port_disp_template.h\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>Modify it 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;}\">#ifndef INC_LCDCONTROLLER_H_\n#define INC_LCDCONTROLLER_H_\n\n\n#ifdef __cplusplus\nextern &quot;C&quot; {\n#endif\n\n\/*********************\n *      INCLUDES\n *********************\/\n\n#include &quot;lvgl.h&quot;\n\n\/*********************\n *      DEFINES\n *********************\/\n\n\/**********************\n *      TYPEDEFS\n **********************\/\n\n\/**********************\n * GLOBAL PROTOTYPES\n **********************\/\n\/* Initialize low level display driver *\/\nvoid lv_port_disp_init(void);\n\n\/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL\n *\/\nvoid disp_enable_update(void);\n\n\/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL\n *\/\nvoid disp_disable_update(void);\n\n\/**********************\n *      MACROS\n **********************\/\n\n#ifdef __cplusplus\n} \/*extern &quot;C&quot;*\/\n#endif\n\n\n\n#endif \/* INC_LCDCONTROLLER_H_ *\/\n<\/pre><\/div>\n\n\n\n<p>Now, open the source file:<\/p>\n\n\n\n<p>Include the following 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;}\">#include &quot;LCDController.h&quot;\n#include &lt;stdbool.h&gt;\n#include &quot;ILI_9341.h&quot;\n#include &quot;stdint.h&quot;\n#include &quot;lvgl.h&quot;\n#include &quot;LCD_Pins.h&quot;<\/pre><\/div>\n\n\n\n<p>Define the dimensions of the display:<\/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 MY_DISP_HOR_RES 240\n\n\n#define MY_DISP_VER_RES 320<\/pre><\/div>\n\n\n\n<p>Define the buffer size:<\/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 buffer_width 100<\/pre><\/div>\n\n\n\n<p>Declare these two functions:<\/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;}\">static void disp_init(void);\n\nstatic void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);<\/pre><\/div>\n\n\n\n<p>Since we are using DMA, it is good idea to use double buffer with LvGL to improve the performance of the TFT.<\/p>\n\n\n\n<p>Hence, we can declare the the two buffers 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;}\">static lv_color_t buf_1[MY_DISP_HOR_RES *buffer_width];\nstatic lv_color_t buf_2[MY_DISP_HOR_RES *buffer_width];<\/pre><\/div>\n\n\n\n<p>Width here is how many lines to be updated at with single DMA transfer. 100 means update 100 lines of the LCD with each DMA transfer. (From testing, more 100 will get some graphics glitches (due to breadboard nature)).<\/p>\n\n\n\n<p>Declare the display driver:<\/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;}\">static lv_disp_drv_t disp_drv;                         \/*Descriptor of a display driver*\/<\/pre><\/div>\n\n\n\n<p>Declare display draw driver:<\/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;}\">static lv_disp_draw_buf_t draw_buf_dsc_1;<\/pre><\/div>\n\n\n\n<p>The initialization 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;}\">void lv_port_disp_init(void)\n{\n    \/*-------------------------\n     * Initialize your display\n     * -----------------------*\/\n    disp_init();\n\n    \/*-----------------------------\n     * Create a buffer for drawing\n     *----------------------------*\/\n\n\n    \n\n    lv_disp_draw_buf_init(&amp;draw_buf_dsc_1, buf_1, buf_2, MY_DISP_HOR_RES*buffer_width);   \/*Initialize the display buffer*\/\n\n\n    \/*-----------------------------------\n     * Register the display in LVGL\n     *----------------------------------*\/\n\n\n    lv_disp_drv_init(&amp;disp_drv);                    \/*Basic initialization*\/\n\n    \/*Set up the functions to access to your display*\/\n\n    \/*Set the resolution of the display*\/\n    disp_drv.hor_res = MY_DISP_HOR_RES;\n    disp_drv.ver_res = MY_DISP_VER_RES;\n\n    \/*Used to copy the buffer's content to the display*\/\n    disp_drv.flush_cb = disp_flush;\n\n    \/*Set a display buffer*\/\n    disp_drv.draw_buf = &amp;draw_buf_dsc_1;\n\n    \/*Finally register the driver*\/\n    lv_disp_drv_register(&amp;disp_drv);\n}<\/pre><\/div>\n\n\n\n<p>Since the initailization calls disp_init funtion, this function will initialize the LCD.<\/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;}\">static void disp_init(void)\n{\n\tILI9341_Init();\n\n}<\/pre><\/div>\n\n\n\n<p>Enable display flush 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;}\">volatile bool disp_flush_enabled = true;\n\nvolatile bool disp_flush_enabled = true;\n\n\/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL\n *\/\nvoid disp_enable_update(void)\n{\n    disp_flush_enabled = true;\n}\n\n\/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL\n *\/\nvoid disp_disable_update(void)\n{\n    disp_flush_enabled = false;\n}<\/pre><\/div>\n\n\n\n<p>For the display flush 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;}\">static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)\n{\n\n\tsetAddrWindow(area-&gt;x1, area-&gt;y1, area-&gt;x2, area-&gt;y2);\n\tint height = area-&gt;y2 - area-&gt;y1 + 1;\n\tint width = area-&gt;x2 - area-&gt;x1 + 1;\n\n\tILI9341_DrawBitmap(width, height, (uint8_t *)color_p);\n\n}<\/pre><\/div>\n\n\n\n<p>SetAddrWindow will tell the embedded RAM within the TFT which area to be flushed.<\/p>\n\n\n\n<p>After the area is set in the RAM, flush the content of LvGL buffet to the TFT.<\/p>\n\n\n\n<p>Now, the LvGL is waiting for the next flush.<\/p>\n\n\n\n<p>Hence, in SPI_TX_Finished 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;}\">void SPI_TX_Finished(void)\n{\n    \/*IMPORTANT!!!\n     *Inform the graphics library that you are ready with the flushing*\/\n    lv_disp_flush_ready(&amp;disp_drv);\n\n    \/*Set CS line to High*\/\n    CS_HIGH();\n\n}<\/pre><\/div>\n\n\n\n<p>Inform the LvGL that TFT is ready for the next TFT flush.<\/p>\n\n\n\n<p>Set CS pin to high.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the TFT Integration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Main Code:<\/h2>\n\n\n\n<p>In main.c:<\/p>\n\n\n\n<p>Include the 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;}\">#include &quot;time_base.h&quot;\n#include &quot;lvgl.h&quot;\n#include &quot;demos\/lv_demos.h&quot;<\/pre><\/div>\n\n\n\n<p>In main function:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Initialize the timer base.<\/li><li>Initialize the LvGL.<\/li><li>Initialize the display.<\/li><li>Launch the demo.<\/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;}\">\tTime_Base_Init(216000000);\n\tlv_init();\n\tlv_port_disp_init();\n\tlv_demo_widgets();<\/pre><\/div>\n\n\n\n<p>In while 1 loop:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Call lv_timer_handler.<\/li><li>delay by 5 millisecond.<\/li><\/ul>\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;}\">\twhile (1)\n\t{\n\t\tlv_timer_handler();\n\t\tdelay(5);\n\n\n\t}<\/pre><\/div>\n\n\n\n<p>Hence, the entire code 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;}\">#include &quot;time_base.h&quot;\n#include &quot;lvgl.h&quot;\n#include &quot;demos\/lv_demos.h&quot;\n\nint main (void)\n{\n\tTime_Base_Init(216000000);\n\tlv_init();\n\tlv_port_disp_init();\n\tlv_demo_widgets();\n\n\n\twhile (1)\n\t{\n\t\tlv_timer_handler();\n\t\tdelay(5);\n\n\n\t}\n\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">8. Code.<\/h2>\n\n\n\n<p>You may download the project from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/LvGL-2.zip\">LvGL-2<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/LvGL-2.zip\" class=\"wp-block-file__button\" download>Download<\/a><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2024\/01\/IMG_2523.heic\" alt=\"\" class=\"wp-image-2291\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Next step, we shall include the touch driver.<\/p>\n\n\n\n<p>Stay tune.<\/p>\n\n\n\n<p>Happy coding \ud83d\ude09 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide (here), we took a look at LvGL and its feature and initialized the environment to make it work. In part two, we shall interface the TFT and display the demo. 6. Including LvGL into the project: First, head to LvGL github page from here. Select V8.3 from here: Next, download as [&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-2283","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\/2283"}],"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=2283"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2283\/revisions"}],"predecessor-version":[{"id":2293,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2283\/revisions\/2293"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2283"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2283"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2283"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}