{"id":113804,"date":"2022-08-18T13:56:09","date_gmt":"2022-08-18T13:56:09","guid":{"rendered":"https:\/\/randomnerdtutorials.com\/?p=113804"},"modified":"2024-10-07T14:04:55","modified_gmt":"2024-10-07T14:04:55","slug":"esp32-spi-communication-arduino","status":"publish","type":"post","link":"https:\/\/randomnerdtutorials.com\/esp32-spi-communication-arduino\/","title":{"rendered":"ESP32 SPI Communication: Set Pins, Multiple SPI Bus Interfaces, and Peripherals (Arduino IDE)"},"content":{"rendered":"\n<p>This is a simple guide about SPI communication protocol with the ESP32 using Arduino IDE. We\u2019ll take a look at the ESP32 SPI pins, how to connect SPI devices, define custom SPI pins, how to use multiple SPI devices, and much more.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" fetchpriority=\"high\" decoding=\"async\" width=\"1200\" height=\"675\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?resize=1200%2C675&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 SPI Communication Set Pins Multiple SPI Bus Interfaces and Peripherals Arduino IDE\" class=\"wp-image-113880\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?w=1280&amp;quality=100&amp;strip=all&amp;ssl=1 1280w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?resize=300%2C169&amp;quality=100&amp;strip=all&amp;ssl=1 300w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?resize=1024%2C576&amp;quality=100&amp;strip=all&amp;ssl=1 1024w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?resize=768%2C432&amp;quality=100&amp;strip=all&amp;ssl=1 768w\" sizes=\"(max-width: 1200px) 100vw, 1200px\" \/><\/figure><\/div>\n\n\n<p><strong>Table of Contents:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"#SPI-intro\">Introducing ESP32 SPI Communication Protocol<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-spi-peripherals\">ESP32 SPI Peripherals<\/a><\/li>\n\n\n\n<li><a href=\"#esp32-spi-pins\">ESP32 SPI Pins<\/a><\/li>\n\n\n\n<li><a href=\"#custom-spi-pins\">Using Custom ESP32 SPI Pins<\/a><\/li>\n\n\n\n<li><a href=\"#multiple-spi-peripherals\">ESP32 with Multiple SPI Devices<\/a>\n<ul class=\"wp-block-list\">\n<li><a href=\"#multiple-devices-same-bus\">Multiple SPI Devices (same bus, different CS pin)<\/a><\/li>\n\n\n\n<li><a href=\"#spi-multiple-bus-hspi-vspi\">Using Two SPI Bus Interfaces (use HSPI and VSPI simultaneously)<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n\n\n\n<p>This tutorial focus on programming the ESP32 using the Arduino core, so before proceeding, you should have the ESP32 add-on installed in your Arduino IDE. Follow the next tutorial to install the ESP32 on the Arduino IDE, if you haven\u2019t already.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/installing-the-esp32-board-in-arduino-ide-windows-instructions\/\">Installing the ESP32 Board in Arduino IDE (Windows, Mac OS X, and Linux instructions)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Alternatively, you can also use VS Code with the PlatformIO extension to program your boards using the Arduino core:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/vs-code-platformio-ide-esp32-esp8266-arduino\/\">Getting Started with VS Code and PlatformIO IDE for ESP32 and ESP8266 (Windows, Mac OS X, Linux Ubuntu)<\/a><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"SPI-intro\">Introducing ESP32 SPI Communication Protocol<\/h2>\n\n\n\n<p>SPI stands for <strong>S<\/strong>erial <strong>P<\/strong>eripheral <strong>I<\/strong>nterface, and it is a synchronous serial data protocol used by microcontrollers to communicate with one or more peripherals. For example, your ESP32 board communicating with a sensor that supports SPI or with another microcontroller.<\/p>\n\n\n\n<p>In an SPI communication, there is always a <strong>controller <\/strong>(also called <em>master<\/em>) that controls the <strong>peripheral <\/strong>devices (also called <em>slaves<\/em>). Data can be sent and received simultaneously. This means that the master can send data to a slave, and a slave can send data to the master at the same time.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"750\" height=\"199\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/SPI-communication.png?resize=750%2C199&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"Introducing ESP32 SPI Communication Protocol\" class=\"wp-image-113889\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/SPI-communication.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/SPI-communication.png?resize=300%2C80&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>You can have <em>only one master<\/em>, which will be a microcontroller (the ESP32), but you can have multiple slaves. A slave can be a sensor, a display, a microSD card, etc., or another microcontroller. This means you can have an ESP32 connected to multiple sensors, but the same sensor can&#8217;t be connected to multiple ESP32 boards simultaneously.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">SPI Interface<\/h3>\n\n\n\n<p>For SPI communication you need four lines:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>MISO<\/strong>: Master In Slave Out<\/li>\n\n\n\n<li><strong>MOSI<\/strong>: Master Out Slave In<\/li>\n\n\n\n<li><strong>SCK<\/strong>: Serial Clock<\/li>\n\n\n\n<li><strong>CS <\/strong>\/<strong>SS<\/strong>: Chip Select (used to select the device when multiple peripherals are used on the same SPI bus)<\/li>\n<\/ul>\n\n\n\n<p>On a slave-only device, like sensors, displays, and others, you may find a different terminology:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>MISO <\/strong>may be labeled as <strong>SDO<\/strong> (Serial Data Out)<\/li>\n\n\n\n<li><strong>MOSI <\/strong>may be labeled as <strong>SDI<\/strong> (Serial Data In)<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-spi-peripherals\">ESP32 SPI Peripherals<\/h2>\n\n\n\n<p>The ESP32 integrates 4 SPI peripherals: SPI0, SPI1, SPI2 (commonly referred to as <strong>HSPI<\/strong>), and SPI3 (commonly referred to as <strong>VSPI<\/strong>). <\/p>\n\n\n\n<p>SP0 and SP1 are used internally to communicate with the built-in flash memory, and you should not use them for other tasks.<\/p>\n\n\n\n<p>You can use <strong>HSPI <\/strong>and <strong>VSPI <\/strong>to communicate with other devices. HSPI and VSPI have independent bus signals, and each bus can drive up to three SPI slaves.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"esp32-spi-pins\">ESP32 Default SPI Pins<\/h2>\n\n\n\n<p>Many ESP32 boards come with default SPI pins pre-assigned. The pin mapping for most boards is as follows (<a href=\"https:\/\/randomnerdtutorials.com\/esp32-s3-devkitc-pinout-guide\/\" title=\"\">it is different for an ESP32-S3<\/a>):<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>SPI<\/strong><\/td><td><strong>MOSI<\/strong><\/td><td><strong>MISO<\/strong><\/td><td><strong>SCLK<\/strong><\/td><td><strong>CS<\/strong><\/td><\/tr><tr><td><strong>VSPI<\/strong><\/td><td>GPIO 23<\/td><td>GPIO 19<\/td><td>GPIO 18<\/td><td>GPIO 5<\/td><\/tr><tr><td><strong>HSPI<\/strong><\/td><td>GPIO 13<\/td><td>GPIO 12<\/td><td>GPIO 14<\/td><td>GPIO 15<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"rntbox rntcred\"><strong>Warning: <\/strong> depending on the board you&#8217;re using, the default SPI pins might be different. So, make sure you check the pinout for the board you&#8217;re using. Additionally, some boards don&#8217;t have pre-assigned SPI pins, so you need to set them on code.<\/p>\n\n\n\n<p class=\"rntbox rntclblue\"><strong>Note: <\/strong> usually, when not specified, the board will use the VSPI pins when initializing an SPI communication with the default settings.<\/p>\n\n\n\n<p>Whether your board comes with pre-assigned pins or not, you can always set them on code.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Finding your ESP32 Board&#8217;s Default SPI Pins<\/h3>\n\n\n\n<p>If you&#8217;re not sure about your board&#8217;s default SPI pins, you can upload the following code to find out.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-spi-communication-arduino\/\r\n  \r\n  Permission is hereby granted, free of charge, to any person obtaining a copy\r\n  of this software and associated documentation files.\r\n  \r\n  The above copyright notice and this permission notice shall be included in all\r\n  copies or substantial portions of the Software.\r\n*\/\r\n\r\n\/\/Find the default SPI pins for your board\r\n\/\/Make sure you have the right board selected in Tools &gt; Boards\r\nvoid setup() {\r\n  \/\/ put your setup code here, to run once:\r\n  Serial.begin(115200);\r\n  Serial.print(&quot;MOSI: &quot;);\r\n  Serial.println(MOSI);\r\n  Serial.print(&quot;MISO: &quot;);\r\n  Serial.println(MISO);\r\n  Serial.print(&quot;SCK: &quot;);\r\n  Serial.println(SCK);\r\n  Serial.print(&quot;SS: &quot;);\r\n  Serial.println(SS);  \r\n}\r\n\r\nvoid loop() {\r\n  \/\/ put your main code here, to run repeatedly:\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/SPI\/ESP32_Find_SPI_Pins.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p><strong>Important: <\/strong> make sure you select the board you&#8217;re using in <strong>Tools <\/strong>&gt; <strong>Board<\/strong>, otherwise, you may not get the right pins.<\/p>\n\n\n\n<p>After uploading the code, open the Serial Monitor, RST your board and you&#8217;ll see the SPI pins.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" decoding=\"async\" width=\"601\" height=\"381\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-Default-SPI-Pins-Serial-Monitor.jpg?resize=601%2C381&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 Finding out the Default SPI pins\" class=\"wp-image-113814\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-Default-SPI-Pins-Serial-Monitor.jpg?w=601&amp;quality=100&amp;strip=all&amp;ssl=1 601w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-Default-SPI-Pins-Serial-Monitor.jpg?resize=300%2C190&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 601px) 100vw, 601px\" \/><\/figure><\/div>\n\n\n<h2 class=\"wp-block-heading\" id=\"custom-spi-pins\">Using Custom ESP32 SPI Pins<\/h2>\n\n\n\n<p>When using libraries to interface with your SPI peripherals, it&#8217;s usually simple to use custom SPI pins because you can pass them as arguments to the library constructor.<\/p>\n\n\n\n<p>For example, take a quick look at the following example that interfaces with a <a href=\"https:\/\/randomnerdtutorials.com\/esp32-bme280-arduino-ide-pressure-temperature-humidity\/\">BME280 sensor<\/a> using the <span class=\"rnthl rntliteral\">Adafruit_BME280<\/span> library.<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\/*\r\n  Rui Santos\r\n  Complete project details at https:\/\/RandomNerdTutorials.com\/esp32-spi-communication-arduino\/\r\n  Based on the Adafruit_BME280_Library example: https:\/\/github.com\/adafruit\/Adafruit_BME280_Library\/blob\/master\/examples\/bme280test\/bme280test.ino\r\n\r\n  Permission is hereby granted, free of charge, to any person obtaining a copy\r\n  of this software and associated documentation files.\r\n  \r\n  The above copyright notice and this permission notice shall be included in all\r\n  copies or substantial portions of the Software.\r\n*\/\r\n\r\n#include &lt;Wire.h&gt;\r\n#include &lt;Adafruit_Sensor.h&gt;\r\n#include &lt;Adafruit_BME280.h&gt;\r\n\r\n#include &lt;SPI.h&gt;\r\n#define BME_SCK 25\r\n#define BME_MISO 32\r\n#define BME_MOSI 26\r\n#define BME_CS 33\r\n#define SEALEVELPRESSURE_HPA (1013.25)\r\n\r\n\/\/Adafruit_BME280 bme; \/\/ I2C\r\n\/\/Adafruit_BME280 bme(BME_CS); \/\/ hardware SPI\r\nAdafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); \/\/ software SPI\r\n\r\nunsigned long delayTime;\r\n\r\nvoid setup() {\r\n  Serial.begin(9600);\r\n  Serial.println(F(&quot;BME280 test&quot;));\r\n\r\n  bool status;\r\n\r\n  \/\/ default settings\r\n  \/\/ (you can also pass in a Wire library object like &amp;Wire2)\r\n  status = bme.begin();  \r\n  if (!status) {\r\n    Serial.println(&quot;Could not find a valid BME280 sensor, check wiring!&quot;);\r\n    while (1);\r\n  }\r\n\r\n  Serial.println(&quot;-- Default Test --&quot;);\r\n  delayTime = 1000;\r\n\r\n  Serial.println();\r\n}\r\n\r\n\r\nvoid loop() { \r\n  printValues();\r\n  delay(delayTime);\r\n}\r\n\r\nvoid printValues() {\r\n  Serial.print(&quot;Temperature = &quot;);\r\n  Serial.print(bme.readTemperature());\r\n  Serial.println(&quot; *C&quot;);\r\n  \r\n  \/\/ Convert temperature to Fahrenheit\r\n  \/*Serial.print(&quot;Temperature = &quot;);\r\n  Serial.print(1.8 * bme.readTemperature() + 32);\r\n  Serial.println(&quot; *F&quot;);*\/\r\n  \r\n  Serial.print(&quot;Pressure = &quot;);\r\n  Serial.print(bme.readPressure() \/ 100.0F);\r\n  Serial.println(&quot; hPa&quot;);\r\n\r\n  Serial.print(&quot;Approx. Altitude = &quot;);\r\n  Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA));\r\n  Serial.println(&quot; m&quot;);\r\n\r\n  Serial.print(&quot;Humidity = &quot;);\r\n  Serial.print(bme.readHumidity());\r\n  Serial.println(&quot; %&quot;);\r\n\r\n  Serial.println();\r\n}\r\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/RuiSantosdotme\/Random-Nerd-Tutorials\/raw\/master\/Projects\/ESP32\/SPI\/ESP32_BME280_Custom_SPI_Pins.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<p>You can easily pass your custom SPI pins to the library constructor.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);<\/code><\/pre>\n\n\n\n<p>In that case, I was using the following SPI pins (not default) and everything worked as expected:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#define BME_SCK 25\n#define BME_MISO 32\n#define BME_MOSI 26\n#define BME_CS 33<\/code><\/pre>\n\n\n\n<p>If you&#8217;re not using a library, or the library you&#8217;re using doesn&#8217;t accept the pins in the library constructor, you may need to initialize the SPI bus yourself. In that case, you would need to call the <span class=\"rnthl rntliteral\">SPI.begin()<\/span> method on the <span class=\"rnthl rntliteral\">setup()<\/span> and pass the SPI pins as arguments:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>SPI.begin(SCK, MISO, MOSI, SS);<\/code><\/pre>\n\n\n\n<p>You can see an example of this scenario <a href=\"https:\/\/randomnerdtutorials.com\/ttgo-lora32-sx1276-arduino-ide\/\">in this tutorial<\/a>, in which we initialize an SPI LoRa transceiver that is connected to custom SPI pins. <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/#sdcardcustompins\">Or this example<\/a> showing how to <a href=\"https:\/\/randomnerdtutorials.com\/esp32-microsd-card-arduino\/#sdcardcustompins\">use custom SPI pins with a microSD card module<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"multiple-spi-peripherals\">ESP32 with Multiple SPI Devices<\/h2>\n\n\n\n<p>As we&#8217;ve seen previously, you can use two different SPI buses on the ESP32 and each bus can connect up to three different peripherals. This means that we can connect up to six SPI devices to the ESP32. If you need to use more, you can use an SPI multiplexer.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"multiple-devices-same-bus\">Multiple SPI Devices (same bus, different CS pin)<\/h3>\n\n\n\n<p>To connect multiple SPI devices, you can use the same SPI bus as long as each peripheral uses a different CS pin.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"402\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-peripherals-same-bus.png?resize=750%2C402&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"SPI communication multiple peripherals same bus\" class=\"wp-image-113890\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-peripherals-same-bus.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-peripherals-same-bus.png?resize=300%2C161&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>To select the peripheral you want to communicate with, you should set its <span class=\"rnthl rntliteral\">CS<\/span> pin to <span class=\"rnthl rntliteral\">LOW<\/span>. For example, imagine you have peripheral 1 and peripheral 2. To read from peripheral 1, make sure its <span class=\"rnthl rntliteral\">CS<\/span> pin is set to <span class=\"rnthl rntliteral\">LOW<\/span> (here represented as <span class=\"rnthl rntliteral\">CS_1<\/span>):<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalWrite(CS_1, LOW); \/\/ enable CS pin to read from peripheral 1\n\n\/*\n use any SPI functions to communicate with peripheral 1\n*\/<\/code><\/pre>\n\n\n\n<p>Then, at same point, you&#8217;ll want to read from peripheral 2. You should disable peripheral 1 <span class=\"rnthl rntliteral\">CS<\/span> pin by setting it to <span class=\"rnthl rntliteral\">HIGH<\/span>, and enable peripheral 2 <span class=\"rnthl rntliteral\">CS<\/span> pin by setting it to <span class=\"rnthl rntliteral\">LOW<\/span>:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>digitalWrite(CS_1, HIGH); \/\/ disable CS pin from peripheral 1\ndigitalWrite(CS_2, LOW);  \/\/ enable CS pin to read from peripheral 2\n\n\/*\n use any SPI functions to communicate with peripheral 2\n*\/<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"spi-multiple-bus-hspi-vspi\">ESP32 Using Two SPI Bus Interfaces (Use HSPI and VSPI simultaneously)<\/h3>\n\n\n\n<p>To communicate with multiple SPI peripherals simultaneously, you can use the ESP32 two SPI buses (HSPI and VSPI). You can use the default HSPI and VSPI pins or use custom pins.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"750\" height=\"391\" src=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-bus-interfaces.png?resize=750%2C391&#038;quality=100&#038;strip=all&#038;ssl=1\" alt=\"ESP32 multiple SPI bus interfaces\" class=\"wp-image-113891\" srcset=\"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-bus-interfaces.png?w=750&amp;quality=100&amp;strip=all&amp;ssl=1 750w, https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-communication-multiple-bus-interfaces.png?resize=300%2C156&amp;quality=100&amp;strip=all&amp;ssl=1 300w\" sizes=\"(max-width: 750px) 100vw, 750px\" \/><\/figure><\/div>\n\n\n<p>Briefly, to use HSPI and VSPI simultaneously, you just need to.<\/p>\n\n\n\n<p><strong>1)<\/strong> First, make sure you include the SPI library in your code.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>#include &lt;SPI.h&gt;<\/code><\/pre>\n\n\n\n<p><strong>2)<\/strong> Initialize two <span class=\"rnthl rntliteral\">SPIClass<\/span> objects with different names, one on the HSPI bus and another on the VSPI bus. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>vspi = new SPIClass(VSPI);\nhspi = new SPIClass(HSPI);<\/code><\/pre>\n\n\n\n<p><strong>3)<\/strong> Call the <span class=\"rnthl rntliteral\">begin()<\/span> method on those objects.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>vspi.begin();\nhspi.begin();<\/code><\/pre>\n\n\n\n<p>You can pass custom pins to the <span class=\"rnthl rntliteral\">begin()<\/span> method if needed.<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>vspi.begin(VSPI_CLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);\nhspi.begin(HSPI_CLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);<\/code><\/pre>\n\n\n\n<p><strong>4)<\/strong> Finally, you also need to set the SS pins as outputs. For example:<\/p>\n\n\n\n<pre class=\"wp-block-code language-c\"><code>pinMode(VSPI_SS, OUTPUT);\npinMode(HSPI_SS, OUTPUT);<\/code><\/pre>\n\n\n\n<p>Then, use the usual commands to interact with the SPI devices, whether you&#8217;re using a sensor library or the SPI library methods.<\/p>\n\n\n\n<p>You can find an example of how to use multiple SPI buses on the <a href=\"https:\/\/github.com\/espressif\/arduino-esp32\/blob\/master\/libraries\/SPI\/examples\/SPI_Multiple_Buses\/SPI_Multiple_Buses.ino\" target=\"_blank\" rel=\"noreferrer noopener\">arduino-esp32 SPI library<\/a>. See the example below:<\/p>\n\n\n<pre style=\"max-height: 40em; margin-bottom: 20px;\"><code class=\"language-c\">\n\n\/* The ESP32 has four SPi buses, however as of right now only two of\n * them are available to use, HSPI and VSPI. Simply using the SPI API\n * as illustrated in Arduino examples will use VSPI, leaving HSPI unused.\n *\n * However if we simply initialize two instance of the SPI class for both\n * of these buses both can be used. However when just using these the Arduino\n * way only will actually be outputting at a time.\n *\n * Logic analyzer capture is in the same folder as this example as\n * &quot;multiple_bus_output.png&quot;\n *\n * created 30\/04\/2018 by Alistair Symonds\n *\/\n#include &lt;SPI.h&gt;\n\n\/\/ Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus\n\n#ifdef ALTERNATE_PINS\n#define VSPI_MISO 2\n#define VSPI_MOSI 4\n#define VSPI_SCLK 0\n#define VSPI_SS   33\n\n#define HSPI_MISO 26\n#define HSPI_MOSI 27\n#define HSPI_SCLK 25\n#define HSPI_SS   32\n#else\n#define VSPI_MISO MISO\n#define VSPI_MOSI MOSI\n#define VSPI_SCLK SCK\n#define VSPI_SS   SS\n\n#define HSPI_MISO 12\n#define HSPI_MOSI 13\n#define HSPI_SCLK 14\n#define HSPI_SS   15\n#endif\n\n#if !defined(CONFIG_IDF_TARGET_ESP32)\n#define VSPI FSPI\n#endif\n\nstatic const int spiClk = 1000000;  \/\/ 1 MHz\n\n\/\/uninitialized pointers to SPI objects\nSPIClass *vspi = NULL;\nSPIClass *hspi = NULL;\n\nvoid setup() {\n  \/\/initialize two instances of the SPIClass attached to VSPI and HSPI respectively\n  vspi = new SPIClass(VSPI);\n  hspi = new SPIClass(HSPI);\n\n  \/\/clock miso mosi ss\n\n#ifndef ALTERNATE_PINS\n  \/\/initialize vspi with default pins\n  \/\/SCLK = 18, MISO = 19, MOSI = 23, SS = 5\n  vspi-&gt;begin();\n#else\n  \/\/alternatively route through GPIO pins of your choice\n  vspi-&gt;begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);  \/\/SCLK, MISO, MOSI, SS\n#endif\n\n#ifndef ALTERNATE_PINS\n  \/\/initialize hspi with default pins\n  \/\/SCLK = 14, MISO = 12, MOSI = 13, SS = 15\n  hspi-&gt;begin();\n#else\n  \/\/alternatively route through GPIO pins\n  hspi-&gt;begin(HSPI_SCLK, HSPI_MISO, HSPI_MOSI, HSPI_SS);  \/\/SCLK, MISO, MOSI, SS\n#endif\n\n  \/\/set up slave select pins as outputs as the Arduino API\n  \/\/doesn't handle automatically pulling SS low\n  pinMode(vspi-&gt;pinSS(), OUTPUT);  \/\/VSPI SS\n  pinMode(hspi-&gt;pinSS(), OUTPUT);  \/\/HSPI SS\n}\n\n\/\/ the loop function runs over and over again until power down or reset\nvoid loop() {\n  \/\/use the SPI buses\n  spiCommand(vspi, 0b01010101);  \/\/ junk data to illustrate usage\n  spiCommand(hspi, 0b11001100);\n  delay(100);\n}\n\nvoid spiCommand(SPIClass *spi, byte data) {\n  \/\/use it as you would the regular arduino SPI API\n  spi-&gt;beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));\n  digitalWrite(spi-&gt;pinSS(), LOW);  \/\/pull SS slow to prep other end for transfer\n  spi-&gt;transfer(data);\n  digitalWrite(spi-&gt;pinSS(), HIGH);  \/\/pull ss high to signify end of data transfer\n  spi-&gt;endTransaction();\n}\n<\/code><\/pre>\n\t<p style=\"text-align:center\"><a class=\"rntwhite\" href=\"https:\/\/github.com\/espressif\/arduino-esp32\/raw\/master\/libraries\/SPI\/examples\/SPI_Multiple_Buses\/SPI_Multiple_Buses.ino\" target=\"_blank\">View raw code<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>This article was a quick and simple guide showing you how to use SPI communication with the ESP32 using the Arduino core\u2014with the ESP32 acting as a controller (<em>master<\/em>).<\/p>\n\n\n\n<p>In summary, the ESP32 has four SPI buses, but only two can be used to control peripherals, the HSPI and VSPI. Most ESP32 have pre-assigned HSPI and VSPI GPIOs, but you can always change the pin assignment in the code.<\/p>\n\n\n\n<p>You can use the HSPI and VSPI buses simultaneously to drive multiple SPI peripherals, or you can use multiple peripherals on the same bus as long as their CS pin is connected to a different GPIO.<\/p>\n\n\n\n<p>We didn&#8217;t dive deeply into examples, because each sensor, library, and case scenario is different. But, now you should have a better idea of how to interface one or multiple SPI devices with the ESP32.<\/p>\n\n\n\n<p>For more detailed information about the SPI Master driver on the ESP32, you can <a href=\"https:\/\/docs.espressif.com\/projects\/esp-idf\/en\/latest\/esp32\/api-reference\/peripherals\/spi_master.html\" target=\"_blank\" rel=\"noreferrer noopener\">check the espressif official documentation<\/a>.<\/p>\n\n\n\n<p>We didn&#8217;t cover setting the ESP32 as an SPI slave, but you can <a href=\"https:\/\/github.com\/hideakitai\/ESP32SPISlave\" target=\"_blank\" rel=\"noreferrer noopener\">check these examples<\/a>.<\/p>\n\n\n\n<p>We hope you find this tutorial useful. We have a similar article, but about I2C communication protocol. Check it out on the following link:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/esp32-i2c-communication-arduino-ide\/\">ESP32 I2C Communication: Set Pins, Multiple Bus Interfaces and Peripherals (Arduino IDE)<\/a><\/li>\n<\/ul>\n\n\n\n<p>Learn more about the ESP32 with our resources:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/randomnerdtutorials.com\/learn-esp32-with-arduino-ide\/\">Learn ESP32 with Arduino IDE<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/build-web-servers-esp32-esp8266-ebook\/\">Build Web Servers with ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/firebase-esp32-esp8266-ebook\/\">Firebase Web App with ESP32 and ESP8266<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/randomnerdtutorials.com\/projects-esp32\/\">Free ESP32 Projects and Tutorials<\/a><\/li>\n<\/ul>\n\n\n\n<p>Thanks for reading.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a simple guide about SPI communication protocol with the ESP32 using Arduino IDE. We\u2019ll take a look at the ESP32 SPI pins, how to connect SPI devices, define &#8230; <\/p>\n<p class=\"read-more-container\"><a title=\"ESP32 SPI Communication: Set Pins, Multiple SPI Bus Interfaces, and Peripherals (Arduino IDE)\" class=\"read-more button\" href=\"https:\/\/randomnerdtutorials.com\/esp32-spi-communication-arduino\/#more-113804\" aria-label=\"Read more about ESP32 SPI Communication: Set Pins, Multiple SPI Bus Interfaces, and Peripherals (Arduino IDE)\">CONTINUE READING \u00bb<\/a><\/p>\n","protected":false},"author":5,"featured_media":113880,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[281,276,277,299,264],"tags":[],"class_list":["post-113804","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-esp32-project","category-esp32","category-esp32-arduino-ide","category-0-esp32","category-project"],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/randomnerdtutorials.com\/wp-content\/uploads\/2022\/08\/ESP32-SPI-Communication-protocol.jpg?fit=1280%2C720&quality=100&strip=all&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/113804","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/comments?post=113804"}],"version-history":[{"count":26,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/113804\/revisions"}],"predecessor-version":[{"id":162918,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/posts\/113804\/revisions\/162918"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media\/113880"}],"wp:attachment":[{"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/media?parent=113804"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/categories?post=113804"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/randomnerdtutorials.com\/wp-json\/wp\/v2\/tags?post=113804"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}