{"id":2030,"date":"2023-10-08T04:50:31","date_gmt":"2023-10-08T04:50:31","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=2030"},"modified":"2023-11-14T16:26:41","modified_gmt":"2023-11-14T16:26:41","slug":"revisedworking-with-stm32-and-graphics-lcd-glcd-128x64-st7920","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=2030","title":{"rendered":"[Revised]Working with STM32 and Graphics LCD: GLCD 128\u00d764 ST7920"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"855\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1024x855.jpeg\" alt=\"\" class=\"wp-image-2031\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1024x855.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-300x250.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-768x641.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1150x960.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-750x626.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-400x334.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-250x209.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp.jpeg 1500w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>In this revised guide, we shall see how interface GLCD 128&#215;64 with STM32 using SPI method (Serial mode).<\/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>GLCD 12864.<\/li><li>Interface with STM32.<\/li><li>Developing the driver.<\/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>At first glance, the 128\u00d764 Graphical LCD Module seems like a bigger brother to the famous 16\u00d72 LCD or 20\u00d74 LCD Modules, with their similar construction and almost similar pin layout.<\/p>\n\n\n\n<p>But there is a significant difference between those two. 16\u00d72 or 20\u00d74 LCDs are essentially character displays. They can only display alpha-numeric characters and some simple custom characters that are confined to a 5\u00d78 matrix.<\/p>\n\n\n\n<p>Coming to the 128\u00d764 Graphical LCD, as the name suggests, it is a Graphical Display consisting of 128\u00d764 i.e., 8192 individually controllable dots.<\/p>\n\n\n\n<p>By using different combinations of pixels, we can basically display characters of various sizes. But the magic doesn\u2019t end there. You can display images and graphics (small animations) as well. In a 128\u00d764 LCD Module, there are 64 rows and 128 columns.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"855\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-1024x855.jpeg\" alt=\"\" class=\"wp-image-2032\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-1024x855.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-300x250.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-768x641.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-1150x960.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-750x626.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-400x334.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1-250x209.jpeg 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/BlueColor128By64GraphicalLCD.webp-1.jpeg 1500w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">ST7920 LCD Controller<\/h3>\n\n\n\n<p>There are several versions of the Graphical LCD in the market. Even though the usage, application and implementations are almost identical, the main difference lies in the internal LCD Controller used to drive the dot matrix display.<\/p>\n\n\n\n<p>Some of the commonly used LCD Controllers are KS0108, SSD1306, ST7920, SH1106, SSD1322, etc. The pin out of the final LCD Module might vary depending on the LCD Controller used. So, please verify the LCD Controller as well as the pin out before making a purchase.<\/p>\n\n\n\n<p>The Graphical LCD Module I purchased consists of ST7920 Controller. It is manufactured by Sitronix and supports three types of bus interfaces i.e., 8-bit mode, 4-bit mode and Serial interface.<\/p>\n\n\n\n<p>If you have used 16\u00d72 LCD Display earlier, then you might be familiar with both 4-bit as well as 8-bit parallel interfaces. The serial interface is something new and we will explore this option in this project.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">128\u00d764 LCD Pinout<\/h3>\n\n\n\n<p>As I already mentioned, double-check with the manufacturer about the pinout of the Graphical LCD Module. The following table describes the pinout of the 128\u00d764 LCD Module that I have.<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>Pin Number<\/td><td>Pin Name<\/td><td>Pin Description<\/td><\/tr><tr><td>1<\/td><td>GND<\/td><td>Ground<\/td><\/tr><tr><td>2<\/td><td>VCC<\/td><td>Supply Voltage<\/td><\/tr><tr><td>3<\/td><td>VO<\/td><td>Contrast Adjust<\/td><\/tr><tr><td>4<\/td><td>RS<\/td><td>Register Select (CS in Serial)<\/td><\/tr><tr><td>5<\/td><td>RW<\/td><td>Read \/ Write Control (Serial Data In)<\/td><\/tr><tr><td>6<\/td><td>E<\/td><td>Enable (Serial CLK)<\/td><\/tr><tr><td>7 \u2013 14<\/td><td>D0 \u2013 D7<\/td><td>Data<\/td><\/tr><tr><td>15<\/td><td>PSB<\/td><td>Interface Selection (0: Serial, 1: 8-bit\/4-bit Parallel)<\/td><\/tr><tr><td>16<\/td><td>NC<\/td><td>Not Connected<\/td><\/tr><tr><td>17<\/td><td>RST<\/td><td>Reset<\/td><\/tr><tr><td>18<\/td><td>VOUT<\/td><td>LCD Voltage Doubler Output<\/td><\/tr><tr><td>19<\/td><td>BLA<\/td><td>Backlight LED Anode<\/td><\/tr><tr><td>20<\/td><td>BLK<\/td><td>Backlight LED Cathode<\/td><\/tr><\/tbody><\/table><\/figure>\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\/2023\/10\/Untitled.png\" alt=\"\" class=\"wp-image-2033\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Untitled.png 640w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Untitled-300x242.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Untitled-400x323.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/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<p>The connection as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"900\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-1024x900.png\" alt=\"\" class=\"wp-image-2036\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-1024x900.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-300x264.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-768x675.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-1536x1350.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-1150x1011.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-750x659.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-400x352.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1-250x220.png 250w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/GLCD_bb-1.png 1986w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>STM32F411 Nucleo-64<\/td><td>GLCD12864<\/td><\/tr><tr><td>5V<\/td><td>Vdd and LED+ (A)<\/td><\/tr><tr><td>GND<\/td><td>Vss, LED- (K) and PSB<\/td><\/tr><tr><td>PA0<\/td><td>RS<\/td><\/tr><tr><td>PA1<\/td><td>RST<\/td><\/tr><tr><td>PA7 (MOSI)<\/td><td>RW<\/td><\/tr><tr><td>PA5 (SCK)<\/td><td>En<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. Developing the driver:<\/h2>\n\n\n\n<p>Before we develop the driver, take a look at the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>SPI and how to use it from <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=466\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=466\" target=\"_blank\">here<\/a>.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<p>We start off by creating new spi.h header file.<\/p>\n\n\n\n<p>Within the header file, include the header guard:<\/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 SPI_H_\n#define SPI_H_\n\n\n\n\n\n#endif \/* SPI_H_ *\/<\/pre><\/div>\n\n\n\n<p>Include stdint 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;stdint.h&quot;<\/pre><\/div>\n\n\n\n<p>Declare the following 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;}\">void st7920_spi_pins_init();\nvoid st7920_spi_config();\nvoid st7920_spi_transmit(uint8_t *data,uint32_t size);<\/pre><\/div>\n\n\n\n<p>Hence, the header file as following:<\/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;}\">#ifndef SPI_H_\n#define SPI_H_\n\n#include &quot;stdint.h&quot;\n\nvoid st7920_spi_pins_init();\nvoid st7920_spi_config();\nvoid st7920_spi_transmit(uint8_t *data,uint32_t size);\n\n#endif \/* SPI_H_ *\/<\/pre><\/div>\n\n\n\n<p>Now, create spi.c source file.<\/p>\n\n\n\n<p>Within the source file, include the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Main spi header file.<\/li><li>stm32f4 main header file<\/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;}\">#include &quot;spi.h&quot;\n#include &quot;stm32f4xx.h&quot;<\/pre><\/div>\n\n\n\n<p>Fot st7920_spi_pins_init function:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable clock access to GPIOA.<\/li><li>Set PA5, PA6 and PA5 to alternate function and set AF05 (SPI1) as alternate function.<\/li><li>Set PA0 and PA1 as general output<\/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;}\">void st7920_spi_pins_init()\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE0_1;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE1_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE1_1;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE4_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE4_1;\n\n\tGPIOA-&gt;MODER |=(GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1);\n\tGPIOA-&gt;MODER &amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\n\t#define SPI1_AF 0x05\n\n\tGPIOA-&gt;AFR[0]|=(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL5_Pos)|(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL6_Pos)|(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>For st7920_spi_config function:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Enable clock access to SPI1.<\/li><li>Set SPI to master mode.<\/li><li>slave management to be software.<\/li><li>SPI mode to mode1 (CPHA1 and CPOL0)<\/li><li>Enable the module.<\/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;}\">void st7920_spi_config()\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\t\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;=~ SPI_CR1_LSBFIRST;\n\t\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_MSTR;\n\t\n\t\/*Select software slave management by\n\t * setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SSM;\n\tSPI1-&gt;CR1 |= SPI_CR1_SSI;\n\t\n\t\/*Set SPI mode to be MODE1 (CPHA1 CPOL0)*\/\n\tSPI1-&gt;CR1|=SPI_CR1_CPHA;\n\t\n\t\/*Enable SPI module*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SPE;\n}<\/pre><\/div>\n\n\n\n<p>For st7920_spi_transmit, it takes two parameters:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Pointer to uint8_t array that holds the data to be written to GLCD.<\/li><li>Size of the buffer.<\/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;}\">void st7920_spi_transmit(uint8_t *data,uint32_t size)\n{\n\tuint32_t i=0;\n\n\twhile(i&lt;size)\n\t{\n\t\t\/*Wait until TXE is set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\t\/*Write the data to the data register*\/\n\t\tSPI1-&gt;DR = data[i];\n\t\ti++;\n\t}\n\t\/*Wait until TXE is set*\/\n\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\/*Wait for BUSY flag to reset*\/\n\twhile((SPI1-&gt;SR &amp; (SPI_SR_BSY))){}\n\n\t\/*Clear OVR flag*\/\n\t(void)SPI1-&gt;DR;\n\t(void)SPI1-&gt;SR;\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the source 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;spi.h&quot;\n#include &quot;stm32f4xx.h&quot;\n\n\nvoid st7920_spi_pins_init()\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE0_1;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE1_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE1_1;\n\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE4_0;\n\tGPIOA-&gt;MODER&amp;=~GPIO_MODER_MODE4_1;\n\n\tGPIOA-&gt;MODER |=(GPIO_MODER_MODE5_1|GPIO_MODER_MODE6_1|GPIO_MODER_MODE7_1);\n\tGPIOA-&gt;MODER &amp;=~(GPIO_MODER_MODE5_0|GPIO_MODER_MODE6_0|GPIO_MODER_MODE7_0);\n\n\t#define SPI1_AF 0x05\n\n\tGPIOA-&gt;AFR[0]|=(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL5_Pos)|(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL6_Pos)|(SPI1_AF&lt;&lt;GPIO_AFRL_AFSEL7_Pos);\n}\n\nvoid st7920_spi_config()\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\t\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;=~ SPI_CR1_LSBFIRST;\n\t\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_MSTR;\n\t\n\t\/*Select software slave management by\n\t * setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SSM;\n\tSPI1-&gt;CR1 |= SPI_CR1_SSI;\n\t\n\t\/*Set SPI mode to be MODE1 (CPHA1 CPOL0)*\/\n\tSPI1-&gt;CR1|=SPI_CR1_CPHA;\n\t\n\t\/*Enable SPI module*\/\n\tSPI1-&gt;CR1 |= SPI_CR1_SPE;\n}\n\nvoid st7920_spi_transmit(uint8_t *data,uint32_t size)\n{\n\tuint32_t i=0;\n\n\twhile(i&lt;size)\n\t{\n\t\t\/*Wait until TXE is set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\t\/*Write the data to the data register*\/\n\t\tSPI1-&gt;DR = data[i];\n\t\ti++;\n\t}\n\t\/*Wait until TXE is set*\/\n\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_TXE))){}\n\n\t\/*Wait for BUSY flag to reset*\/\n\twhile((SPI1-&gt;SR &amp; (SPI_SR_BSY))){}\n\n\t\/*Clear OVR flag*\/\n\t(void)SPI1-&gt;DR;\n\t(void)SPI1-&gt;SR;\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the SPI section.<\/p>\n\n\n\n<p>Now create new header file with name of ST7920.h .<\/p>\n\n\n\n<p>With the header file, 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;stdint.h&quot;<\/pre><\/div>\n\n\n\n<p>Declare the following 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;}\">void ST7920_SendString(int row, int col, char* string);\nvoid ST7920_GraphicMode (int enable) ;\nvoid ST7920_DrawBitmap(const unsigned char* graphic);\nvoid ST7920_Update(void);\nvoid ST7920_Clear();\nvoid ST7920_init();\nvoid DrawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);\nvoid DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h);\nvoid DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h);\nvoid DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius);\nvoid DrawFilledCircle(int16_t x0, int16_t y0, int16_t r);\nvoid DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3);\nvoid DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3);\n<\/pre><\/div>\n\n\n\n<p>Hence the entire 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;}\">#ifndef ST7920_H_\n#define ST7920_H_\n\n#include &quot;stdint.h&quot;\n\nvoid ST7920_SendString(int row, int col, char* string);\nvoid ST7920_GraphicMode (int enable) ;\nvoid ST7920_DrawBitmap(const unsigned char* graphic);\nvoid ST7920_Update(void);\nvoid ST7920_Clear();\nvoid ST7920_init();\nvoid DrawLine(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1);\nvoid DrawRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h);\nvoid DrawFilledRectangle(uint16_t x, uint16_t y, uint16_t w, uint16_t h);\nvoid DrawCircle(uint8_t x0, uint8_t y0, uint8_t radius);\nvoid DrawFilledCircle(int16_t x0, int16_t y0, int16_t r);\nvoid DrawTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3);\nvoid DrawFilledTriangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t x3, uint16_t y3);\n\n\n#endif \/* ST7920_H_ *\/<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Now, create new source file with name of ST7920.c.<\/p>\n\n\n\n<p>Within the source, 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;ST7920.h&quot;\n#include &quot;spi.h&quot;\n#include &quot;delay.h&quot;<\/pre><\/div>\n\n\n\n<p>Then define some macros for CS and RST pins 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;}\">#define CS_LOW \t\tGPIOA-&gt;BSRR=GPIO_BSRR_BR0\n#define CS_HIGH\t\tGPIOA-&gt;BSRR=GPIO_BSRR_BS0\n\n#define RST_LOW \tGPIOA-&gt;BSRR=GPIO_BSRR_BR1\n#define RST_HIGH\tGPIOA-&gt;BSRR=GPIO_BSRR_BS1<\/pre><\/div>\n\n\n\n<p>Array to hold the data to be sent out to 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;}\">uint8_t lcd_data[3];<\/pre><\/div>\n\n\n\n<p>Variables to hold the display control:<\/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];<\/pre><\/div>\n\n\n\n<p>Some functions required for the operation:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#define LCD_CLS         0x01\n#define LCD_HOME        0x02\n#define LCD_ADDRINC     0x06\n#define LCD_DISPLAYON   0x0C\n#define LCD_DISPLAYOFF  0x08\n#define LCD_CURSORON    0x0E\n#define LCD_CURSORBLINK 0x0F\n#define LCD_BASIC       0x30\n#define LCD_EXTEND      0x34\n#define LCD_GFXMODE     0x36\n#define LCD_TXTMODE     0x34\n#define LCD_STANDBY     0x01\n#define LCD_SCROLL      0x03\n#define LCD_SCROLLADDR  0x40\n#define LCD_ADDR        0x80\n#define LCD_LINE0       0x80\n#define LCD_LINE1       0x90\n#define LCD_LINE2       0x88\n#define LCD_LINE3       0x98<\/pre><\/div>\n\n\n\n<p>In order to send data\/command, the datasheet clearly states the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Set CS pin to high.<\/li><li>Send 5bits of 1 to sync the display.<\/li><li>Send RW and RS state.<\/li><li>Followed by zero.<\/li><li>Then send data\/command as two byte as shown in figure below:<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"989\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-1024x989.png\" alt=\"\" class=\"wp-image-2037\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-1024x989.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-300x290.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-768x742.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-1536x1483.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-2048x1978.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-1150x1111.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-750x724.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-400x386.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/Screenshot-2023-10-08-at-7.37.35-AM-250x241.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Hence, the send data command functions as following which have been defined as static:<\/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 ST7920_SendCmd (uint8_t cmd)\n{\n\tCS_HIGH;  \/\/ PUll the CS high\n\n\tlcd_data[0]=0xF8;\n\tlcd_data[1]=(cmd&amp;0xf0);\n\tlcd_data[2]=((cmd&lt;&lt;4)&amp;0xf0);\n\n\tst7920_spi_transmit(lcd_data,3);\n\n\tdelayuS(30);\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\tlcd_data[0]=0xFA;\n\tlcd_data[1]=(data&amp;0xf0);\n\tlcd_data[2]=((data&lt;&lt;4)&amp;0xf0);\n\n\tst7920_spi_transmit(lcd_data,3);\n\n\tdelayuS(30);\n\n\tCS_LOW;  \/\/ PUll the CS LOW\n}<\/pre><\/div>\n\n\n\n<p>The delay will allow the GLCD to process the data since it doesn&#8217;t have internal buffer to store the data.<\/p>\n\n\n\n<p>For the GLCD initializing sequence:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Wait at least 40ms to ensure that GLCD is powered up<\/li><li>Reset the GLCD by setting the reset pin low for 40 ms, then high.<\/li><li>Send the initializing command.<\/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;}\">void ST7920_init()\n{\n\tdelay(100);\n\tst7920_spi_pins_init();\n\tst7920_spi_config();\n\n\tRST_LOW;\n\tdelay(50);\n\tRST_HIGH;\n\tdelay(100);\n\tST7920_SendCmd(0x30);  \t\t\/\/ 8bit mode\n\tdelayuS(110);  \t\t\t\t\/\/  &gt;100us delay\n\n\tST7920_SendCmd(0x30);  \t\t\/\/ 8bit mode\n\tdelayuS(40);  \t\t\t\t\/\/ &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\tdelay(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>Functions that allow us to display shapes, text pictures etc:<\/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 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\n\n\n\/\/ switch to graphic mode or normal mode::: enable = 1 -&gt; graphic mode enable = 0 -&gt; normal mode\n\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}\n\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\n\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\tdelay(20); \/\/ delay &gt;1.6 ms\n\t}\n}\n\n\n\n\nstatic void 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<\/pre><\/div>\n\n\n\n<p>In main.c:<\/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;delay.h&quot;\n#include &quot;bitmap.h&quot;\n#include &quot;stdio.h&quot;\n#include &quot;horse.h&quot;\n#include &quot;ST7920.h&quot;\n\n\nint main(void)\n{\n\n\tST7920_init();\n\n\tST7920_SendString(0,0, &quot;HELLO WORLD&quot;);\n\tST7920_SendString(1,0, &quot;FROM&quot;);\n\tST7920_SendString(2,0, &quot;EmbeddedExpertIO&quot;);\n\tST7920_SendString(3,0, &quot;1234567890!@#$%^&quot;);\n\tdelay(2000);\n\tST7920_Clear();\n\tST7920_GraphicMode(1);\n\tST7920_DrawBitmap(logo);\n\tdelay(2000);\n\tST7920_Clear();\n\tDrawCircle(110, 31, 12);\n\n\tDrawCircle(110, 31, 16);\n\n\tDrawLine(3, 60, 127, 33);\n\n\tST7920_Update();\n\n\tdelay(2000);\n\n\tDrawRectangle (100, 12, 20, 14);\n\n\tST7920_Update();\n\n\tdelay(2000);\n\n\tDrawFilledRectangle(30, 20, 30, 10);\n\n\tST7920_Update();\n\n\tdelay(2000);\n\n\tDrawFilledCircle(15, 30, 6);\n\n\tST7920_Update();\n\n\tDrawFilledTriangle(1,5,10,5,6,15);\n\n\tST7920_Update();\n\n\tdelay(2000);\n\n\tST7920_Clear();\n\n\n\twhile(1)\n\t{\n\t\tST7920_DrawBitmap(horse1);\n\t\tST7920_DrawBitmap(horse2);\n\t\tST7920_DrawBitmap(horse3);\n\t\tST7920_DrawBitmap(horse4);\n\t\tST7920_DrawBitmap(horse5);\n\t\tST7920_DrawBitmap(horse6);\n\t\tST7920_DrawBitmap(horse7);\n\t\tST7920_DrawBitmap(horse8);\n\t\tST7920_DrawBitmap(horse9);\n\t\tST7920_DrawBitmap(horse10);\n\t}\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Code:<\/h2>\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\/2023\/10\/ST7920_in_SPI.zip\">ST7920_in_SPI<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/10\/ST7920_in_SPI.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\">5. Results:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"GLCD 12864 ST7920 with STM32\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/jdUlT9nwKhQ?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this revised guide, we shall see how interface GLCD 128&#215;64 with STM32 using SPI method (Serial mode). In this guide, we shall cover the following: GLCD 12864. Interface with STM32. Developing the driver. Code Demo. 1. GLCD 12864: At first glance, the 128\u00d764 Graphical LCD Module seems like a bigger brother to the famous [&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-2030","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\/2030"}],"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=2030"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2030\/revisions"}],"predecessor-version":[{"id":2039,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/2030\/revisions\/2039"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}