{"id":794,"date":"2022-03-01T15:39:48","date_gmt":"2022-03-01T15:39:48","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=794"},"modified":"2022-03-01T15:39:53","modified_gmt":"2022-03-01T15:39:53","slug":"working-with-stm32-and-graphics-lcd-glcd-128x64-st7920","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=794","title":{"rendered":"Working with STM32 and Graphics LCD: GLCD 128\u00d764 ST7920"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.winstar.com.tw\/uploads\/photos\/graphic-lcd-display-module\/WG12864D-01.JPG\" alt=\"\" width=\"638\" height=\"638\" \/><\/figure><\/div>\n\n\n\n<p>In this guide, we shall interface STM32 with GLCD12864 using serial method. We shall display some texts, shapes and graphics.<\/p>\n\n\n\n<p>In the guide, we will cover the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>GLCD 12864.<\/li><li>Interface with STM32.<\/li><li>Code.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. GLCD 12864:<\/h2>\n\n\n\n<p>Ordinary LCDs can only display simple text or numbers within a fixed size. But in 128\u00d764 graphical LCD display, there is 128\u00d764 = 8192 dots, which is equivalent to 8242\/8 = 1024 pixels. So, it can display not only simple text or numbers within a fixed size but also simple graphics.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">128&#215;64 Graphical LCD Display Pinout<\/h2>\n\n\n\n<p>This module has 20 pins:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>GND<\/strong>: Ground<\/li><li><strong>VCC<\/strong>: Module power supply \u2013 5 V<\/li><li><strong>VO<\/strong>: LCD Contrast<\/li><li><strong>RS<\/strong>: Register Select Pin<\/li><li><strong>R\/W:&nbsp;<\/strong>Write\/ Read selection<\/li><li><strong>E:&nbsp;<\/strong>Enable Signal<\/li><li><strong>D0-7:&nbsp;<\/strong>Data Bus<\/li><li><strong>PSB:&nbsp;<\/strong>Interface selection (0 for serial communication, 1 for 8-bit parallel communication)<\/li><li><strong>NC:&nbsp;<\/strong>Not Connected<\/li><li><strong>RST:&nbsp;<\/strong>Reset<\/li><li><strong>Vout:&nbsp;<\/strong>LCD Voltage Output (Vout &lt; 7V)<\/li><li><strong>BLA:&nbsp;<\/strong>Power Supply for Backlight+<\/li><li><strong>BLK:&nbsp;<\/strong>Power Supply for Backlight-<\/li><\/ul>\n\n\n\n<p>You can see the pinout of this module in the image below.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"640\" height=\"517\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Untitled.png\" alt=\"\" class=\"wp-image-795\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Untitled.png 640w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Untitled-300x242.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Untitled-400x323.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Untitled-250x202.png 250w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Interface with STM32:<\/h2>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"706\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-1024x706.png\" alt=\"\" class=\"wp-image-796\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-1024x706.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-300x207.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-768x529.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-1536x1059.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-2048x1412.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-1150x793.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-750x517.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-400x276.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/Screen-Shot-2022-03-01-at-6.21.27-PM-250x172.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><strong>setup below is as follows<br><\/strong>PA0 &#8212;&#8212;&#8212;&gt; SCLK (EN)<br>PA1 &#8212;&#8212;&#8212;&gt; CS (RS)<br>PA4 &#8212;&#8212;&#8212;&gt; SID (RW)<br>PA8 &#8212;&#8212;&#8212;&gt; RST (RST)<br><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Code: <\/h2>\n\n\n\n<p>We start of by defining some marcos fpr SCLK, CS, SID and RST 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#define SCK_LOW \t(GPIOA-&gt;BSRR=GPIO_BSRR_BR0)\n#define SCK_HIGH \t(GPIOA-&gt;BSRR=GPIO_BSRR_BS0)\n\n#define CS_LOW \t\t(GPIOA-&gt;BSRR=GPIO_BSRR_BR1)\n#define CS_HIGH \t(GPIOA-&gt;BSRR=GPIO_BSRR_BS1)\n\n#define SID_LOW \t(GPIOA-&gt;BSRR=GPIO_BSRR_BR4)\n#define SID_HIGH \t(GPIOA-&gt;BSRR=GPIO_BSRR_BS4)\n\n#define RST_LOW \t(GPIOA-&gt;BSRR=GPIO_BSRR_BR8)\n#define RST_HIGH \t(GPIOA-&gt;BSRR=GPIO_BSRR_BS8)<\/pre><\/div>\n\n\n\n<p>Now we can need some variables 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;}\">uint8_t startRow, startCol, endRow, endCol; \/\/ coordinates of the dirty rectangle\nuint8_t numRows = 64;\nuint8_t numCols = 128;\nuint8_t Graphic_Check = 0;\nuint8_t image[(128 * 64)\/8];\n<\/pre><\/div>\n\n\n\n<p>For initializing 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;}\">\nvoid ST7920_Init (void)\n{\n\t\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\tGPIOA-&gt;MODER|=(GPIO_MODER_MODE0_0|GPIO_MODER_MODE1_0|GPIO_MODER_MODE4_0|GPIO_MODER_MODE8_0);\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE0_1|GPIO_MODER_MODE1_1|GPIO_MODER_MODE4_1|GPIO_MODER_MODE8_1);\n\tGPIOA-&gt;OSPEEDR|=GPIO_OSPEEDER_OSPEEDR0|GPIO_OSPEEDER_OSPEEDR1|GPIO_OSPEEDER_OSPEEDR4|GPIO_OSPEEDER_OSPEEDR8;\n\t\n\tRST_LOW; \t\t\t\t\t\/\/ RESET=0\n\tdelay(10);   \/\/ wait for 10ms\n\tRST_HIGH;\n\n\tdelay(50);   \/\/wait for &gt;40 ms\n\n\n\tST7920_SendCmd(0x30);  \/\/ 8bit mode\n\tdelayUs(110);  \/\/  &gt;100us delay\n\n\tST7920_SendCmd(0x30);  \/\/ 8bit mode\n\tdelayUs(40);  \/\/ &gt;37us delay\n\n\tST7920_SendCmd(0x08);  \/\/ D=0, C=0, B=0\n\tdelayUs(110);  \/\/ &gt;100us delay\n\n\tST7920_SendCmd(0x01);  \/\/ clear screen\n\tdelay(12);  \/\/ &gt;10 ms delay\n\n\n\tST7920_SendCmd(0x06);  \/\/ cursor increment right no shift\n\tdelay(1);  \/\/ 1ms delay\n\n\tST7920_SendCmd(0x0C);  \/\/ D=1, C=0, B=0\n    delay(1);  \/\/ 1ms delay\n\n\tST7920_SendCmd(0x02);  \/\/ return to home\n\tdelay(1);  \/\/ 1ms delay\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Since we are using serial mode, we need to use software SPI to send data to the LCD 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;}\">\nstatic void SendByteSPI(uint8_t byte)\n{\n\tfor(int i=0;i&lt;8;i++)\n\t{\n\t\tif((byte&lt;&lt;i)&amp;0x80)\n\t\t\t{\n\t\t\t\tSID_HIGH;  \/\/ SID=1  OR MOSI\n\t\t\t}\n\n\t\telse {SID_LOW;}  \/\/ SID=0\n\n\t\tSCK_LOW;  \/\/ SCLK =0  OR SCK\n\t\tSCK_HIGH;  \/\/ SCLK=1\n}\n}\n<\/pre><\/div>\n\n\n\n<p>For sending data and command 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\nstatic void ST7920_SendCmd (uint8_t cmd)\n{\n\n\tCS_HIGH;  \/\/ PUll the CS high\n\n\tSendByteSPI(0xf8+(0&lt;&lt;1));  \/\/ send the SYNC + RS(0)\n\tSendByteSPI(cmd&amp;0xf0);  \/\/ send the higher nibble first\n\tSendByteSPI((cmd&lt;&lt;4)&amp;0xf0);  \/\/ send the lower nibble\n\tdelayUs(50);\n\n\tCS_LOW;  \/\/ PUll the CS LOW\n\n}\n\nstatic void ST7920_SendData (uint8_t data)\n{\n\n\tCS_HIGH;\n\n\tSendByteSPI(0xf8+(1&lt;&lt;1));  \/\/ send the SYNC + RS(1)\n\tSendByteSPI(data&amp;0xf0);  \/\/ send the higher nibble first\n\tSendByteSPI((data&lt;&lt;4)&amp;0xf0);  \/\/ send the lower nibble\n\tdelayUs(50);\n\tCS_LOW;  \/\/ PUll the CS LOW\n}\n<\/pre><\/div>\n\n\n\n<p>For displaying text 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;}\">\nvoid ST7920_SendString(int row, int col, char* string)\n{\n    switch (row)\n    {\n        case 0:\n            col |= 0x80;\n            break;\n        case 1:\n            col |= 0x90;\n            break;\n        case 2:\n            col |= 0x88;\n            break;\n        case 3:\n            col |= 0x98;\n            break;\n        default:\n            col |= 0x80;\n            break;\n    }\n\n    ST7920_SendCmd(col);\n\n    while (*string)\n    \t{\n    \t\tST7920_SendData(*string++);\n    \t}\n}\n<\/pre><\/div>\n\n\n\n<p>Switch to graphic 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;}\">\nvoid ST7920_GraphicMode (int enable)   \/\/ 1-enable, 0-disable\n{\n\tif (enable == 1)\n\t{\n\t\tST7920_SendCmd(0x30);  \/\/ 8 bit mode\n\t\tdelay (1);\n\t\tST7920_SendCmd(0x34);  \/\/ switch to Extended instructions\n\t\tdelay (1);\n\t\tST7920_SendCmd(0x36);  \/\/ enable graphics\n\t\tdelay (1);\n\t\tGraphic_Check = 1;  \/\/ update the variable\n\t}\n\n\telse if (enable == 0)\n\t{\n\t\tST7920_SendCmd(0x30);  \/\/ 8 bit mode\n\t\tdelay (1);\n\t\tGraphic_Check = 0;  \/\/ update the variable\n\t}\n}<\/pre><\/div>\n\n\n\n<p>For drawing some graphics:<\/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 ST7920_DrawBitmap(const unsigned char* graphic)\n{\n\tuint8_t x, y;\n\tfor(y = 0; y &lt; 64; y++)\n\t{\n\t\tif(y &lt; 32)\n\t\t{\n\t\t\tfor(x = 0; x &lt; 8; x++)\t\t\t\t\t\t\t\/\/ Draws top half of the screen.\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\/\/ In extended instruction mode, vertical and horizontal coordinates must be specified before sending data in.\n\t\t\t\tST7920_SendCmd(0x80 | y);\t\t\t\t\/\/ Vertical coordinate of the screen is specified first. (0-31)\n\t\t\t\tST7920_SendCmd(0x80 | x);\t\t\t\t\/\/ Then horizontal coordinate of the screen is specified. (0-8)\n\t\t\t\tST7920_SendData(graphic[2*x + 16*y]);\t\t\/\/ Data to the upper byte is sent to the coordinate.\n\t\t\t\tST7920_SendData(graphic[2*x+1 + 16*y]);\t\/\/ Data to the lower byte is sent to the coordinate.\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n\t\t\tfor(x = 0; x &lt; 8; x++)\t\t\t\t\t\t\t\/\/ Draws bottom half of the screen.\n\t\t\t{\t\t\t\t\t\t\t\t\t\t\t\t\/\/ Actions performed as same as the upper half screen.\n\t\t\t\tST7920_SendCmd(0x80 | (y-32));\t\t\t\/\/ Vertical coordinate must be scaled back to 0-31 as it is dealing with another half of the screen.\n\t\t\t\tST7920_SendCmd(0x88 | x);\n\t\t\t\tST7920_SendData(graphic[2*x + 16*y]);\n\t\t\t\tST7920_SendData(graphic[2*x+1 + 16*y]);\n\t\t\t}\n\t\t}\n\n\t}\n}\n\n\n\/\/ Update the display with the selected graphics\nvoid ST7920_Update(void)\n{\n\tST7920_DrawBitmap(image);\n}\n<\/pre><\/div>\n\n\n\n<p>Clearing 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;}\">\n\nvoid ST7920_Clear()\n{\n\tif (Graphic_Check == 1)  \/\/ if the graphic mode is set\n\t{\n\t\tuint8_t x, y;\n\t\tfor(y = 0; y &lt; 64; y++)\n\t\t{\n\t\t\tif(y &lt; 32)\n\t\t\t{\n\t\t\t\tST7920_SendCmd(0x80 | y);\n\t\t\t\tST7920_SendCmd(0x80);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tST7920_SendCmd(0x80 | (y-32));\n\t\t\t\tST7920_SendCmd(0x88);\n\t\t\t}\n\t\t\tfor(x = 0; x &lt; 8; x++)\n\t\t\t{\n\t\t\t\tST7920_SendData(0);\n\t\t\t\tST7920_SendData(0);\n\t\t\t}\n\t\t}\n\t}\n\n\telse\n\t{\n\t\tST7920_SendCmd(0x01);   \/\/ clear the display using command\n\t\t\/\/delay(2); \/\/ delay &gt;1.6 ms\n\t}\n}<\/pre><\/div>\n\n\n\n<p>Extra functions needed:<\/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\/\/ set Pixel\n\nvoid SetPixel(uint8_t x, uint8_t y)\n{\n  if (y &lt; numRows &amp;&amp; x &lt; numCols)\n  {\n    uint8_t *p = image + ((y * (numCols\/8)) + (x\/8));\n    *p |= 0x80u &gt;&gt; (x%8);\n\n    *image = *p;\n\n    \/\/ Change the dirty rectangle to account for a pixel being dirty (we assume it was changed)\n    if (startRow &gt; y) { startRow = y; }\n    if (endRow &lt;= y)  { endRow = y + 1; }\n    if (startCol &gt; x) { startCol = x; }\n    if (endCol &lt;= x)  { endCol = x + 1; }\n\n\n  }\n\n}\n\n\/* draw a line\n * start point (X0, Y0)\n * end point (X1, Y1)\n *\/\nvoid DrawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1)\n{\n  int dx = (x1 &gt;= x0) ? x1 - x0 : x0 - x1;\n  int dy = (y1 &gt;= y0) ? y1 - y0 : y0 - y1;\n  int sx = (x0 &lt; x1) ? 1 : -1;\n  int sy = (y0 &lt; y1) ? 1 : -1;\n  int err = dx - dy;\n\n  for (;;)\n  {\n    SetPixel(x0, y0);\n    if (x0 == x1 &amp;&amp; y0 == y1) break;\n    int e2 = err + err;\n    if (e2 &gt; -dy)\n    {\n      err -= dy;\n      x0 += sx;\n    }\n    if (e2 &lt; dx)\n    {\n      err += dx;\n      y0 += sy;\n    }\n  }\n}\n\n\n\n\n\/* Draw rectangle\n * start point (x,y)\n * w -&gt; width\n * h -&gt; height\n *\/\nvoid DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h)\n{\n\t\/* Check input parameters *\/\n\tif (\n\t\tx &gt;= numCols ||\n\t\ty &gt;= numRows\n\t) {\n\t\t\/* Return error *\/\n\t\treturn;\n\t}\n\n\t\/* Check width and height *\/\n\tif ((x + w) &gt;= numCols) {\n\t\tw = numCols - x;\n\t}\n\tif ((y + h) &gt;= numRows) {\n\t\th = numRows - y;\n\t}\n\n\t\/* Draw 4 lines *\/\n\tDrawLine(x, y, x + w, y);         \/* Top line *\/\n\tDrawLine(x, y + h, x + w, y + h); \/* Bottom line *\/\n\tDrawLine(x, y, x, y + h);         \/* Left line *\/\n\tDrawLine(x + w, y, x + w, y + h); \/* Right line *\/\n}\n\n\n\n\n\/* Draw filled rectangle\n * Start point (x,y)\n * w -&gt; width\n * h -&gt; height\n *\/\nvoid DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h)\n{\n\tuint8_t i;\n\n\t\/* Check input parameters *\/\n\tif (\n\t\tx &gt;= numCols ||\n\t\ty &gt;= numRows\n\t) {\n\t\t\/* Return error *\/\n\t\treturn;\n\t}\n\n\t\/* Check width and height *\/\n\tif ((x + w) &gt;= numCols) {\n\t\tw = numCols - x;\n\t}\n\tif ((y + h) &gt;= numRows) {\n\t\th = numRows - y;\n\t}\n\n\t\/* Draw lines *\/\n\tfor (i = 0; i &lt;= h; i++) {\n\t\t\/* Draw lines *\/\n\t\tDrawLine(x, y + i, x + w, y + i);\n\t}\n}\n\n\n\n\n\/* draw circle\n * centre (x0,y0)\n * radius = radius\n *\/\nvoid DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius)\n{\n  int f = 1 - (int)radius;\n  int ddF_x = 1;\n\n  int ddF_y = -2 * (int)radius;\n  int x = 0;\n\n  SetPixel(x0, y0 + radius);\n  SetPixel(x0, y0 - radius);\n  SetPixel(x0 + radius, y0);\n  SetPixel(x0 - radius, y0);\n\n  int y = radius;\n  while(x &lt; y)\n  {\n    if(f &gt;= 0)\n    {\n      y--;\n      ddF_y += 2;\n      f += ddF_y;\n    }\n    x++;\n    ddF_x += 2;\n    f += ddF_x;\n    SetPixel(x0 + x, y0 + y);\n    SetPixel(x0 - x, y0 + y);\n    SetPixel(x0 + x, y0 - y);\n    SetPixel(x0 - x, y0 - y);\n    SetPixel(x0 + y, y0 + x);\n    SetPixel(x0 - y, y0 + x);\n    SetPixel(x0 + y, y0 - x);\n    SetPixel(x0 - y, y0 - x);\n  }\n}\n\n\n\/\/ Draw Filled Circle\n\nvoid DrawFilledCircle(int16_t x0, int16_t y0, int16_t r)\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    SetPixel(x0, y0 + r);\n    SetPixel(x0, y0 - r);\n    SetPixel(x0 + r, y0);\n    SetPixel(x0 - r, y0);\n    DrawLine(x0 - r, y0, x0 + r, y0);\n\n    while (x &lt; y) {\n        if (f &gt;= 0) {\n            y--;\n            ddF_y += 2;\n            f += ddF_y;\n        }\n        x++;\n        ddF_x += 2;\n        f += ddF_x;\n\n        DrawLine(x0 - x, y0 + y, x0 + x, y0 + y);\n        DrawLine(x0 + x, y0 - y, x0 - x, y0 - y);\n\n        DrawLine(x0 + y, y0 + x, x0 - y, y0 + x);\n        DrawLine(x0 + y, y0 - x, x0 - y, y0 - x);\n    }\n}\n\n\n\n\/\/ Draw Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)\nvoid DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3)\n{\n\t\/* Draw lines *\/\n\tDrawLine(x1, y1, x2, y2);\n\tDrawLine(x2, y2, x3, y3);\n\tDrawLine(x3, y3, x1, y1);\n}\n\n\n\n\/\/ Draw Filled Traingle with coordimates (x1, y1), (x2, y2), (x3, y3)\nvoid DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3)\n{\n\tint16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,\n\tyinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,\n\tcurpixel = 0;\n\n#define ABS(x)   ((x) &gt; 0 ? (x) : -(x))\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} else {\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} else {\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} else {\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{\n\t\tDrawLine(x, y, x3, y3);\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<\/pre><\/div>\n\n\n\n<p>You may download the entire code from here: <\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/GLCD.zip\">GLCD<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/GLCD.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\">4. Demo:<\/h2>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2022\/03\/IMG_7992.mp4\"><\/video><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this guide, we shall interface STM32 with GLCD12864 using serial method. We shall display some texts, shapes and graphics. In the guide, we will cover the following: GLCD 12864. Interface with STM32. Code. Demo. 1. GLCD 12864: Ordinary LCDs can only display simple text or numbers within a fixed size. But in 128\u00d764 graphical [&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-794","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\/794"}],"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=794"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/794\/revisions"}],"predecessor-version":[{"id":799,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/794\/revisions\/799"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=794"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=794"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=794"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}