{"id":1650,"date":"2023-03-22T04:38:48","date_gmt":"2023-03-22T04:38:48","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1650"},"modified":"2023-03-22T04:38:51","modified_gmt":"2023-03-22T04:38:51","slug":"working-with-stm32-and-displays-ssd1306-spi-oled-display","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1650","title":{"rendered":"Working with STM32 and Displays: SSD1306 SPI OLED display"},"content":{"rendered":"\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"1000\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188.png\" alt=\"\" class=\"wp-image-1653\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188.png 1000w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-300x300.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-150x150.png 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-768x768.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-750x750.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-400x400.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-250x250.png 250w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/figure><\/div>\n\n\n\n<p>In the previous guide on OLED (<a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=613\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=613\" target=\"_blank\">here<\/a>), we took a look at how to connect SSD1306 I2C OLED with STM32F4. In this guide, we shall use the SPI version of the display to display text and picture.<\/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<p><\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>SSD1306 OLED display.<\/li><li>Interface with STM32F4.<\/li><li>SPI driver of SSD1306.<\/li><li>Write Data, Command and Multidata<\/li><li>Initializing sequence.<\/li><li>Basic function to display text.<\/li><li>Demo.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. SSD1306 OLED Display:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>Do you want to give a perfect look to your microcontroller project which traditional liquid crystal displays (<a href=\"https:\/\/blog.embeddedexpert.io\/?p=600\" target=\"_blank\" rel=\"noreferrer noopener\">LCDs<\/a>) do not promise? In this case, OLED displays will be the best choice for you. Because they offer a good view angle and pixel density which makes it the perfect choice for graphics display projects at low cost.&nbsp;<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-ssd1306-oled-types\">SSD1306 OLED Types<\/h3>\n\n\n\n<p>There are different types of\u00a0OLED<a rel=\"noreferrer noopener\" href=\"https:\/\/microcontrollerslab.com\/oled-display-pinout-interfacing-arduino-applications-features\/\" target=\"_blank\">\u00a0<\/a>displays available in the market. But the common thing in most displays is the SSD1306 CMOS OLED driver controller. The main component of OLED is an SSD1306 controller which is used to communicate with microcontrollers,\u00a0 such as TM4C123 Tiva Launchpad or STM32F4, using either SPI or I2C communication. But usually, I2C communication is preferred because it requires only two wires to communicate with STM32F411.\u00a0<\/p>\n\n\n\n<p>However, in this guide, we shall cover the SPI version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-i2c-oled-display\">I2C OLED Display\u00a0<\/h3>\n\n\n\n<p>These displays come in different colors, sizes and shapes. In this tutorial, we will use an SPI based OLED display having size of 128\u00d764 as shown in the figure below. But the good thing is programming doesn\u2019t change much with the change of OLED size and color.\u00a0<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>The following picture shows the pin wiring of the OLED display. As you can see from its pinout diagram, it consists of six pins such as Vcc, GND, CLK, MOSI,CS and DC. Vcc and GND pins are used to power OLED displays and the operating voltage range is between 3.3-5V. That means we can easily power it from the same source and connect directly with microcontrollers.<\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1000\" height=\"1000\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1.png\" alt=\"\" class=\"wp-image-1654\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1.png 1000w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-300x300.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-150x150.png 150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-768x768.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-750x750.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-400x400.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/6-pin-spi-096-inch-yellowblue-double-color-oled-display-module-12864-ssd1306-rs1188-1-250x250.png 250w\" sizes=\"(max-width: 1000px) 100vw, 1000px\" \/><\/figure><\/div>\n\n\n\n<p>The pins description as following:<\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>OLED Pins<\/td><td>Meaning<\/td><\/tr><tr><td>Vcc<\/td><td>+Ve power source (3.3 to 5V)<\/td><\/tr><tr><td>GND<\/td><td>-Ve power source<\/td><\/tr><tr><td>CLK<\/td><td>Serial Clock of the SPI<\/td><\/tr><tr><td>MOSI<\/td><td>Master Out Slave of SPI <\/td><\/tr><tr><td>CS<\/td><td>Chip Select<\/td><\/tr><tr><td>D\/C<\/td><td>Data\/Command select<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Interface With STM32F4:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The interface as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"737\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-1024x737.png\" alt=\"\" class=\"wp-image-1655\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-1024x737.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-300x216.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-768x553.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-1536x1106.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-2048x1475.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-1150x828.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-750x540.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-400x288.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/Screenshot-2023-03-22-at-6.31.24-AM-250x180.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td>SSD1306 SPI<\/td><td>STM32F411-Nucleo64<\/td><\/tr><tr><td>Vcc<\/td><td>5V<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><\/tr><tr><td>CLK <\/td><td>D13 (PA5)<\/td><\/tr><tr><td>MOSI<\/td><td>D11 (PA7)<\/td><\/tr><tr><td>CS<\/td><td>D8 (PA9)<\/td><\/tr><tr><td>DC<\/td><td>D4 (PA10)<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. SPI driver for SSD1306:<\/h2>\n\n\n\n<p>Since the display is using SPI, we shall use SPI for that purpose. For more information about SPI, please refer to this guide <a href=\"https:\/\/blog.embeddedexpert.io\/?p=466\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=466\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p>The GPIO initializing 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 OLED_SPI_Pins_Init()\n{\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN; \/\/enable clock for GPIOA\n\n\t\/\/set PA5, PA6 and PA7 to alternate function mode\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\/\/Set PA9 and PA10 as Output\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE9_0|GPIO_MODER_MODE10_0;\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE9_1|GPIO_MODER_MODE10_1);\n\n\t\/*select which AF for PA5, PA6 and PA7*\/\n\tGPIOA-&gt;AFR[0]|=(0x05&lt;&lt;20)|(0x05&lt;&lt;24)|(0x05&lt;&lt;28);\n}<\/pre><\/div>\n\n\n\n<p>SPI Initializing:<\/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 OLED_SPI_Configure()\n{\n\t\/*Enable clock access to SPI1 module*\/\n\t\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\t\/*Set clock to fPCLK\/2*\/\n\t\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;3);\n\t\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;4);\n\t\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;5);\n\n\t\t\/*Enable full duplex*\/\n\t\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;10);\n\n\t\t\/*Set MSB first*\/\n\t\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;7);\n\n\t\t\/*Set mode to MASTER*\/\n\t\tSPI1-&gt;CR1 |= (1U&lt;&lt;2);\n\n\t\t\/*Set 8 bit data mode*\/\n\t\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;11);\n\n\t\t\/*Select software slave management by\n\t\t * setting SSM=1 and SSI=1*\/\n\t\tSPI1-&gt;CR1 |= (1&lt;&lt;8);\n\t\tSPI1-&gt;CR1 |= (1&lt;&lt;9);\n\n\t\t\/*Enable SPI module*\/\n\t\tSPI1-&gt;CR1 |= (1&lt;&lt;6);\n}<\/pre><\/div>\n\n\n\n<p>SPI Write function for OLED:<\/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 OLED_SPI_Write(char *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 =(uint8_t) 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>Chip select and deselect:<\/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 OLED_Select(void)\n{\n\tGPIOA-&gt;BSRR =GPIO_BSRR_BR9;\n\n}\n\n\/*Pull high to disable*\/\nvoid OLED_Deselect(void)\n{\n\tGPIOA-&gt;BSRR =GPIO_BSRR_BS9;\n}<\/pre><\/div>\n\n\n\n<p>Data\/Command toggle:<\/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 OLED_DataMode()\n{\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BS10;\n}\n\nvoid OLED_CommMode()\n{\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BR10;\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>Thats all for the SPI section.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. <span style=\"font-size: revert;font-weight: revert\">Write Data, Command and Multidata<\/span>:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>In order to write data, we need to set D\/C pin to high, set CS pin to low, write data and then set CS high 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;}\">void SSD1306_WRITEDATA(char command)\n{\n\tOLED_DataMode();\n\tOLED_Select();\n\tOLED_SPI_Write(&amp;command,1);\n\tOLED_Deselect();\n}<\/pre><\/div>\n\n\n\n<p>To write command, same procedure as writing data. However, we need to set D\/C to low 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;}\">void SSD1306_WRITECOMMAND(char command)\n{\n\tOLED_CommMode();\n\tOLED_Select();\n\tOLED_SPI_Write(&amp;command,1);\n\tOLED_Deselect();\n}<\/pre><\/div>\n\n\n\n<p>To write multiple data when updating 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;}\">void SSD1306_Write_Multi_Data(char * data, uint16_t length)\n{\n\tOLED_DataMode();\n\tOLED_Select();\n\tOLED_SPI_Write((char*)data,length);\n\tOLED_Deselect();\n\n}<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">5. Initialization Sequence:<\/h2>\n\n\n\n<p>The initialization sequence 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 SSD1306_Init(void)\n{\n\t OLED_SPI_Pins_Init();\n\n\t OLED_SPI_Configure();\n\t\/* A little delay *\/\n\tuint32_t p = 2500;\n\twhile(p&gt;0)\n\t\tp--;\n\t\n\t\/* Init LCD *\/\n\tSSD1306_WRITECOMMAND(0xAE); \/\/display off\n\tSSD1306_WRITECOMMAND(0x20); \/\/Set Memory Addressing Mode   \n\tSSD1306_WRITECOMMAND(0x10); \/\/00,Horizontal Addressing Mode;01,Vertical Addressing Mode;10,Page Addressing Mode (RESET);11,Invalid\n\tSSD1306_WRITECOMMAND(0xB0); \/\/Set Page Start Address for Page Addressing Mode,0-7\n\tSSD1306_WRITECOMMAND(0xC8); \/\/Set COM Output Scan Direction\n\tSSD1306_WRITECOMMAND(0x00); \/\/---set low column address\n\tSSD1306_WRITECOMMAND(0x10); \/\/---set high column address\n\tSSD1306_WRITECOMMAND(0x40); \/\/--set start line address\n\tSSD1306_WRITECOMMAND(0x81); \/\/--set contrast control register\n\tSSD1306_WRITECOMMAND(0xFF);\n\tSSD1306_WRITECOMMAND(0xA1); \/\/--set segment re-map 0 to 127\n\tSSD1306_WRITECOMMAND(0xA6); \/\/--set normal display\n\tSSD1306_WRITECOMMAND(0xA8); \/\/--set multiplex ratio(1 to 64)\n\tSSD1306_WRITECOMMAND(0x3F); \/\/\n\tSSD1306_WRITECOMMAND(0xA4); \/\/0xa4,Output follows RAM content;0xa5,Output ignores RAM content\n\tSSD1306_WRITECOMMAND(0xD3); \/\/-set display offset\n\tSSD1306_WRITECOMMAND(0x00); \/\/-not offset\n\tSSD1306_WRITECOMMAND(0xD5); \/\/--set display clock divide ratio\/oscillator frequency\n\tSSD1306_WRITECOMMAND(0xF0); \/\/--set divide ratio\n\tSSD1306_WRITECOMMAND(0xD9); \/\/--set pre-charge period\n\tSSD1306_WRITECOMMAND(0x22); \/\/\n\tSSD1306_WRITECOMMAND(0xDA); \/\/--set com pins hardware configuration\n\tSSD1306_WRITECOMMAND(0x12);\n\tSSD1306_WRITECOMMAND(0xDB); \/\/--set vcomh\n\tSSD1306_WRITECOMMAND(0x20); \/\/0x20,0.77xVcc\n\tSSD1306_WRITECOMMAND(0x8D); \/\/--set DC-DC enable\n\tSSD1306_WRITECOMMAND(0x14); \/\/\n\tSSD1306_WRITECOMMAND(0xAF); \/\/--turn on SSD1306 panel\n\t\n\n\tSSD1306_WRITECOMMAND(SSD1306_DEACTIVATE_SCROLL);\n\n\t\/* Clear screen *\/\n\tSSD1306_Fill(SSD1306_COLOR_BLACK);\n\t\n\t\/* Update screen *\/\n\tSSD1306_UpdateScreen();\n\t\n\t\/* Set default values *\/\n\tSSD1306.CurrentX = 0;\n\tSSD1306.CurrentY = 0;\n\t\n\t\/* Initialized OK *\/\n\tSSD1306.Initialized = 1;\n\t\n\t\/* Return OK *\/\n\treturn 1;\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Basic function to display text:<\/h2>\n\n\n\n<p>In order to display text, we need the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Go to xy point:<\/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;}\">oid SSD1306_GotoXY(uint16_t x, uint16_t y) {\n\t\/* Set write pointers *\/\n\tSSD1306.CurrentX = x;\n\tSSD1306.CurrentY = y;\n}<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>Put character into 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;}\">char SSD1306_Puts(char* str, FontDef_t* Font, SSD1306_COLOR_t color) {\n\t\/* Write characters *\/\n\twhile (*str) {\n\t\t\/* Write character by character *\/\n\t\tif (SSD1306_Putc(*str, Font, color) != *str) {\n\t\t\t\/* Return error *\/\n\t\t\treturn *str;\n\t\t}\n\t\t\n\t\t\/* Increase string pointer *\/\n\t\tstr++;\n\t}\n\t\n\t\/* Everything OK, zero should be returned *\/\n\treturn *str;\n}<\/pre><\/div>\n\n\n\n<ul class=\"wp-block-list\"><li>Update the display:<\/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 SSD1306_UpdateScreen(void) {\n\tuint8_t m;\n\t\n\tfor (m = 0; m &lt; 8; m++) {\n\t\tSSD1306_WRITECOMMAND(0xB0 + m);\n\t\tSSD1306_WRITECOMMAND(0x00);\n\t\tSSD1306_WRITECOMMAND(0x10);\n\t\t\n\t\t\/* Write multi data *\/\n\n\t\tSSD1306_Write_Multi_Data(&amp;SSD1306_Buffer[SSD1306_WIDTH * m], SSD1306_WIDTH);\n\t}\n}<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. Code:<\/h2>\n\n\n\n<p>You may download the full source code from here:<\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/SSD1306OLED_SPI.zip\">SSD1306OLED_SPI<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/03\/SSD1306OLED_SPI.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\">8. Demo:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"SSD1306 SPI Based OLED with STM32F4\" width=\"1170\" height=\"658\" src=\"https:\/\/www.youtube.com\/embed\/Dt5YylG27h8?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><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the previous guide on OLED (here), we took a look at how to connect SSD1306 I2C OLED with STM32F4. In this guide, we shall use the SPI version of the display to display text and picture. In this guide, we shall cover the following: SSD1306 OLED display. Interface with STM32F4. SPI driver of SSD1306. [&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-1650","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\/1650"}],"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=1650"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1650\/revisions"}],"predecessor-version":[{"id":1657,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1650\/revisions\/1657"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1650"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1650"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1650"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}