{"id":1750,"date":"2023-05-10T06:28:55","date_gmt":"2023-05-10T06:28:55","guid":{"rendered":"https:\/\/blog.embeddedexpert.io\/?p=1750"},"modified":"2023-05-10T06:28:57","modified_gmt":"2023-05-10T06:28:57","slug":"working-with-stm32-and-spi-dealing-with-multiple-slaves","status":"publish","type":"post","link":"https:\/\/blog.embeddedexpert.io\/?p=1750","title":{"rendered":"Working with STM32 and SPI: Dealing with multiple slaves"},"content":{"rendered":"\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-1024x683.jpeg\" alt=\"\" class=\"wp-image-1751\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-1024x683.jpeg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-300x200.jpeg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-768x512.jpeg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-1536x1024.jpeg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-2048x1365.jpeg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-1150x767.jpeg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-750x500.jpeg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-400x267.jpeg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/AdobeStock_122425803-2-2-250x167.jpeg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>In the past guides related to SPI, we worked only with single slave device. In this guide, we shall cover dealing with multiple slave devices. The slave devices in this case are:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>MPU9250.<\/li><li>SSD1306 SPI OLED Monochrom display.<\/li><\/ul>\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>SPI Configuration.<\/li><li>MPU9250 and SSD1306 connection.<\/li><li>MPU9250 and SSD1306 modification<\/li><li>Code.<\/li><li>Results.<\/li><\/ul>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. SPI configuration:<\/h2>\n\n\n\n<p>To start off we shall create new header and source file with name of spi.h and spi.c respectively.<\/p>\n\n\n\n<p>Within the header file:<\/p>\n\n\n\n<p>Put the define guard 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 SPI_H_\n#define SPI_H_\n\n\n\n#endif \/* SPI_H_ *\/<\/pre><\/div>\n\n\n\n<p>Within the guard, 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>Since we are dealing with multiple slave devices, we shall use enum 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;}\">typedef enum\n{\n\n\tMPU9250_CS=0,\n\tSSD1306_CS=1\n\n\n}SlaveSelectTypedef;<\/pre><\/div>\n\n\n\n<p>This can be passed as argument to slave select and deselect functions.<\/p>\n\n\n\n<p>Now, 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 Slave_Pins_init();\n\nvoid SPI_Pins_Init();\n\nvoid SPI_Configure();\n\nvoid SPI_Write(uint8_t *data,uint32_t size);\n\nvoid SPI_Receive(uint8_t *data,uint32_t size);\n\nvoid Slave_Select(SlaveSelectTypedef slave);\n\nvoid Slave_Deselect(SlaveSelectTypedef slave);<\/pre><\/div>\n\n\n\n<p>These are the function to be implemented within the source file.<\/p>\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 SPI_H_\n#define SPI_H_\n\n#include &quot;stdint.h&quot;\n\ntypedef enum\n{\n\n\tMPU9250_CS=0,\n\tSSD1306_CS=1\n\n\n}SlaveSelectTypedef;\n\n\nvoid Slave_Pins_init();\n\nvoid SPI_Pins_Init();\n\nvoid SPI_Configure();\n\nvoid SPI_Write(uint8_t *data,uint32_t size);\n\nvoid SPI_Receive(uint8_t *data,uint32_t size);\n\nvoid Slave_Select(SlaveSelectTypedef slave);\n\nvoid Slave_Deselect(SlaveSelectTypedef slave);\n\n#endif \/* SPI_H_ *\/\n<\/pre><\/div>\n\n\n\n<p>Moving on to the source file.<\/p>\n\n\n\n<p>We start off by including spi.h and stm32f4xx.h header file as following:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">#include &quot;spi.h&quot;\n\n#include &quot;stm32f4xx.h&quot;<\/pre><\/div>\n\n\n\n<p>For information about which pins and how configure SPI, check this guide 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>.<\/p>\n\n\n\n<p>For SPI pins initialization:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SPI_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\n\n\t\/*select which AF for PA5, PA6 and PA7 which is AF05*\/\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>Salve pins initialization:<\/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 Slave_Pins_init()\n{\n\t\/*Enable clock access to GPIOA*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\t\/*Set PA0 and PA1 to output mode*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0|GPIO_MODER_MODE1_0;\n\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE0_1|GPIO_MODER_MODE1_1);\n\n\t\/*Set PA0 to PA1 to high state*\/\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BS0|GPIO_BSRR_BS1;\n}<\/pre><\/div>\n\n\n\n<p>SPI configuration:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SPI_Configure()\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\/*Set clock to fPCLK\/2*\/\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;3);\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;4);\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;5);\n\n\t\/*Enable full duplex*\/\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;10);\n\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;7);\n\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= (1U&lt;&lt;2);\n\n\t\/*Set 8 bit data mode*\/\n\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;11);\n\n\t\/*Select software slave management by\n\t * setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= (1&lt;&lt;8);\n\tSPI1-&gt;CR1 |= (1&lt;&lt;9);\n\n\t\/*Enable SPI module*\/\n\tSPI1-&gt;CR1 |= (1&lt;&lt;6);\n}<\/pre><\/div>\n\n\n\n<p>SPI write:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-csrc&quot;,&quot;theme&quot;:&quot;dracula&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:false,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;&quot;,&quot;language&quot;:&quot;C&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;c&quot;}\">void SPI_Write(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 =(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}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>SPI Read:<\/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;}\">void SPI_Receive(uint8_t *data,uint32_t size)\n{\n\n\twhile(size)\n\t{\n\t\t\/*Send dummy data*\/\n\t\tSPI1-&gt;DR =0xFF;\n\n\t\t\/*Wait for RXNE flag to be set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_RXNE))){}\n\n\t\t\/*Read data from data register*\/\n\t\t*data++ = (SPI1-&gt;DR);\n\t\tsize--;\n\t}\n}\n<\/pre><\/div>\n\n\n\n<p>Now for slave select and deselect.<\/p>\n\n\n\n<p>Since we already created enums for the salves devices, we shall pass this enum as argument to both select and deselect functions.<\/p>\n\n\n\n<p>For select 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;}\">\nvoid Slave_Select(SlaveSelectTypedef slave)<\/pre><\/div>\n\n\n\n<p>Using switch state, we can select the slave 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;}\">\tswitch (slave)\n\t{\n\t\tcase MPU9250_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BR0; break;\n\n\t\tcase SSD1306_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BR1; break;\n\n\t\tdefault: break;<\/pre><\/div>\n\n\n\n<p>Since selecting slave requires setting the pin to low, we can use BSRR register of the GPIO to achieve this.<\/p>\n\n\n\n<p>Also, for deselecting the slave, the pin should be pulled 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 Slave_Deselect(SlaveSelectTypedef slave)\n{\n\tswitch (slave)\n\t{\n\t\tcase MPU9250_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BS0; break;\n\n\t\tcase SSD1306_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BS1; break;\n\n\t\tdefault: break;\n\t}\n}<\/pre><\/div>\n\n\n\n<p><\/p>\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\n#include &quot;stm32f4xx.h&quot;\n\n\nvoid 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\n\n\t\/*select which AF for PA5, PA6 and PA7 which is AF05*\/\n\tGPIOA-&gt;AFR[0]|=(0x05&lt;&lt;20)|(0x05&lt;&lt;24)|(0x05&lt;&lt;28);\n}\n\n\nvoid Slave_Pins_init()\n{\n\t\/*Enable clock access to GPIOA*\/\n\tRCC-&gt;AHB1ENR|=RCC_AHB1ENR_GPIOAEN;\n\n\t\/*Set PA0 and PA1 to output mode*\/\n\tGPIOA-&gt;MODER|=GPIO_MODER_MODE0_0|GPIO_MODER_MODE1_0;\n\n\tGPIOA-&gt;MODER&amp;=~(GPIO_MODER_MODE0_1|GPIO_MODER_MODE1_1);\n\n\t\/*Set PA0 to PA1 to high state*\/\n\tGPIOA-&gt;BSRR=GPIO_BSRR_BS0|GPIO_BSRR_BS1;\n}\n\nvoid SPI_Configure()\n{\n\t\/*Enable clock access to SPI1 module*\/\n\tRCC-&gt;APB2ENR |= RCC_APB2ENR_SPI1EN;\n\n\t\/*Set clock to fPCLK\/2*\/\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;3);\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;4);\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;5);\n\n\t\/*Enable full duplex*\/\n\tSPI1-&gt;CR1 &amp;=~(1U&lt;&lt;10);\n\n\t\/*Set MSB first*\/\n\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;7);\n\n\t\/*Set mode to MASTER*\/\n\tSPI1-&gt;CR1 |= (1U&lt;&lt;2);\n\n\t\/*Set 8 bit data mode*\/\n\tSPI1-&gt;CR1 &amp;= ~(1U&lt;&lt;11);\n\n\t\/*Select software slave management by\n\t * setting SSM=1 and SSI=1*\/\n\tSPI1-&gt;CR1 |= (1&lt;&lt;8);\n\tSPI1-&gt;CR1 |= (1&lt;&lt;9);\n\n\t\/*Enable SPI module*\/\n\tSPI1-&gt;CR1 |= (1&lt;&lt;6);\n}\n\nvoid SPI_Write(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 =(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}\n\n\nvoid SPI_Receive(uint8_t *data,uint32_t size)\n{\n\n\twhile(size)\n\t{\n\t\t\/*Send dummy data*\/\n\t\tSPI1-&gt;DR =0xFF;\n\n\t\t\/*Wait for RXNE flag to be set*\/\n\t\twhile(!(SPI1-&gt;SR &amp; (SPI_SR_RXNE))){}\n\n\t\t\/*Read data from data register*\/\n\t\t*data++ = (SPI1-&gt;DR);\n\t\tsize--;\n\t}\n}\n\n\nvoid Slave_Select(SlaveSelectTypedef slave)\n{\n\tswitch (slave)\n\t{\n\t\tcase MPU9250_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BR0; break;\n\n\t\tcase SSD1306_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BR1; break;\n\n\t\tdefault: break;\n\t}\n}\n\nvoid Slave_Deselect(SlaveSelectTypedef slave)\n{\n\tswitch (slave)\n\t{\n\t\tcase MPU9250_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BS0; break;\n\n\t\tcase SSD1306_CS: GPIOA-&gt;BSRR=GPIO_BSRR_BS1; break;\n\n\t\tdefault: break;\n\t}\n}\n<\/pre><\/div>\n\n\n\n<p>Thats all for the SPI driver development.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. MPU9259 and SSD1306 connection:<\/h2>\n\n\n\n<p>The connection of the two slave devices as following:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"607\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-1024x607.png\" alt=\"\" class=\"wp-image-1752\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-1024x607.png 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-300x178.png 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-768x455.png 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-1536x911.png 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-2048x1214.png 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-1150x682.png 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-750x445.png 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-400x237.png 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Screenshot-2023-05-10-at-8.21.27-AM-250x148.png 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-table is-style-regular\"><table><tbody><tr><td>STM32F411 Nucleo<\/td><td>SSD1306 SPI OLED<\/td><td>MPU9250<\/td><\/tr><tr><td>5V<\/td><td>Vcc<\/td><td>Vcc<\/td><\/tr><tr><td>GND<\/td><td>GND<\/td><td>GND<\/td><\/tr><tr><td>SCK (PA5)<\/td><td>SCL<\/td><td>SCK<\/td><\/tr><tr><td>MOSI (PA7)<\/td><td>SDA<\/td><td>SDA<\/td><\/tr><tr><td>MISO<\/td><td>&#8211;<\/td><td>ADO<\/td><\/tr><tr><td>PA0<\/td><td>CSN<\/td><td>&#8211;<\/td><\/tr><tr><td>PA1<\/td><td>&#8211;<\/td><td>CS<\/td><\/tr><tr><td>PA10<\/td><td>DC<\/td><td>&#8211;<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">3. MPU9250 and SSD1306 modification:<\/h2>\n\n\n\n<p><\/p>\n\n\n\n<p>The modification for SSD1306 SPI for write data, command and multidata 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(uint8_t command)\n{\n\tOLED_CommMode();\n\tSlave_Select(SSD1306_CS);\n\tSPI_Write(&amp;command,1);\n\tSlave_Deselect(SSD1306_CS);\n}\n\nvoid SSD1306_WRITEDATA(uint8_t command)\n{\n\tOLED_DataMode();\n\tSlave_Select(SSD1306_CS);\n\tSPI_Write(&amp;command,1);\n\tSlave_Deselect(SSD1306_CS);\n}\n\nvoid SSD1306_Write_Multi_Data(uint8_t * data, uint16_t length)\n{\n\tOLED_DataMode();\n\tSlave_Select(SSD1306_CS);\n\tSPI_Write(data,length);\n\tSlave_Deselect(SSD1306_CS);\n\n}<\/pre><\/div>\n\n\n\n<p>For SSD1306 SPI OLED code, from <a href=\"https:\/\/blog.embeddedexpert.io\/?p=1650\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1650\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>For full MPU code, please refer to the following guide <a rel=\"noreferrer noopener\" href=\"https:\/\/blog.embeddedexpert.io\/?p=1743\" data-type=\"URL\" data-id=\"https:\/\/blog.embeddedexpert.io\/?p=1743\" target=\"_blank\">here<\/a>.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>The modification as following for writing process:<\/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;}\">\tSlave_Select(MPU9250_CS);\n\tSPI_Write(data,2);\n\tSlave_Deselect(MPU9250_CS);<\/pre><\/div>\n\n\n\n<p>For reading process:<\/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;}\">\tSlave_Select(MPU9250_CS);\n\tSPI_Write(data,1);\n\tSPI_Receive((uint8_t*)(accelBuf),6);\n\tSlave_Deselect(MPU9250_CS);<\/pre><\/div>\n\n\n\n<p>The rest of the code will remain the same.<\/p>\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><\/p>\n\n\n\n<p>You may download the entire source code from here:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-file\"><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Multi_slave_spi.zip\">Multi_slave_spi<\/a><a href=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/Multi_slave_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>For testing functionality of both MPU9250 and SSD1306, the following is the implementation of 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;oled.h&quot;\n#include &quot;MPU9250.h&quot;\n#include &quot;spi.h&quot;\n#include &quot;stdio.h&quot;\n\nchar zz[30];\n\n\nextern void uart2_rxtx_init(void);\n\n\nfloat ax,ay,az;\nuint16_t count;\nint main(void)\n{\n\n\tuart2_rxtx_init();\n\tSPI_Pins_Init();\n\tSlave_Pins_init();\n\tSPI_Configure();\n\tSSD1306_Init();\n\tMPU9250_beginAccel(ACC_FULL_SCALE_2_G);\n\n\n\twhile(1)\n\t{\n\t\tMPU9250_accelUpdate();\n\n\t\tax=MPU9250_accelX();\n\t\tay=MPU9250_accelY();\n\t\taz=MPU9250_accelZ();\n\n\t\tsprintf(zz,&quot;ax=%0.2f&quot;,MPU9250_accelX());\n\t\tSSD1306_GotoXY (0,0);\n\t\tSSD1306_Puts (zz, &amp;Font_7x10, 1);\n\n\t\tsprintf(zz,&quot;ay=%0.2f&quot;,MPU9250_accelY());\n\t\tSSD1306_GotoXY (0,10);\n\t\tSSD1306_Puts (zz, &amp;Font_7x10, 1);\n\n\t\tsprintf(zz,&quot;az=%0.2f&quot;,MPU9250_accelZ());\n\t\tSSD1306_GotoXY (0,20);\n\t\tSSD1306_Puts (zz, &amp;Font_7x10, 1);\n\n\n\t\tSSD1306_GotoXY (0,30);\n\t\tsprintf(zz,&quot;%d&quot;,count++);\n\t\tSSD1306_Puts (zz, &amp;Font_7x10, 1);\n\n\t\tSSD1306_UpdateScreen();\n\n\t\tdelay(30);\n\n\t}\n\n}\n<\/pre><\/div>\n\n\n\n<p><\/p>\n\n\n\n<p>The results as following:<\/p>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-1024x768.jpg\" alt=\"\" class=\"wp-image-1756\" srcset=\"https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-1024x768.jpg 1024w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-300x225.jpg 300w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-768x576.jpg 768w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-1536x1152.jpg 1536w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-2048x1536.jpg 2048w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-1150x863.jpg 1150w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-750x563.jpg 750w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-400x300.jpg 400w, https:\/\/blog.embeddedexpert.io\/wp-content\/uploads\/2023\/05\/IMG_0760-250x188.jpg 250w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Both MPU9250 and SSD1306 are working.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Happy coding \ud83d\ude42 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>In the past guides related to SPI, we worked only with single slave device. In this guide, we shall cover dealing with multiple slave devices. The slave devices in this case are: MPU9250. SSD1306 SPI OLED Monochrom display. In this guide, we shall cover the following: SPI Configuration. MPU9250 and SSD1306 connection. MPU9250 and 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,7,12],"tags":[],"class_list":["post-1750","post","type-post","status-publish","format-standard","hentry","category-embedded-systems","category-lcd","category-peripheral-drivers","category-state-machine","category-stm32"],"_links":{"self":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1750"}],"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=1750"}],"version-history":[{"count":1,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1750\/revisions"}],"predecessor-version":[{"id":1757,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=\/wp\/v2\/posts\/1750\/revisions\/1757"}],"wp:attachment":[{"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1750"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1750"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.embeddedexpert.io\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1750"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}