I have two ESP32 cards. I want to set one of these cards as Master and the other as Slave and communicate via SPI. I have done this before on Arduino Uno, but I cannot do this on ESP32. Below are my Master and Slave codes that I have prepared simply. I can't get what I want in any way. Can anyone help?
Master Code:
#include <SPI.h>
#define CS_PIN 5 // Choose the appropriate pin for Chip Select (CS)
void setup() {
Serial.begin(115200);
SPI.begin();
}
void loop() {
char dataToSend = 'A';
digitalWrite(CS_PIN, LOW); // Start communication with the slave
SPI.transfer(dataToSend); // Send data to the slave
digitalWrite(CS_PIN, HIGH); // End communication with the slave
delay(2000); // Delay for demonstration purposes
}
Slave Code:
#include <SPI.h>
#define CS_PIN 5 // Choose the appropriate pin for Chip Select (CS)
void setup() {
Serial.begin(115200);
SPI.begin();
}
void loop() {
if (digitalRead(CS_PIN) == LOW) { // Check if CS (Chip Select) is LOW, meaning the device is selected
char receivedData = SPI.transfer(0); // Read received data from the master
// Display received data on the serial monitor
Serial.println("Received Data: " + String(receivedData));
delay(1000); // Optional delay for demonstration purposes
}
}
New Code - New Problem:
I tried to adapt the codes at https://microcontrollerslab.com/esp32-spi-communication-tutorial-arduino/. From what I understand it uses the following pins for SPI: MISO-12; MOSI-13; SCLK-14; SS-15. I set my connections the same way, but I cannot get the output I expected from the Slave. It remains waiting at the slave.wait line.
Master Code:
#include <SPI.h>
// Define ALTERNATE_PINS to use non-standard GPIO pins for SPI bus
#define HSPI_MISO MISO
#define HSPI_MOSI MOSI
#define HSPI_SCLK SCK
#define HSPI_SS SS
static const int spiClk = 1000000; // 1 MHz
//uninitalised pointers to SPI objects
SPIClass * hspi = NULL;
void setup() {
//initialise instance of the SPIClass attached to HSPI
hspi = new SPIClass(HSPI);
//initialise hspi with default pins
//SCLK = 14, MISO = 12, MOSI = 13, SS = 15
hspi->begin();
pinMode(HSPI_SS, OUTPUT); //HSPI SS
}
// the loop function runs over and over again until power down or reset
void loop() {
hspi_send_command();
delay(100);
}
void hspi_send_command() {
byte data_on = 0b00000001; // data 1 to turn on LED of slave
byte data_off = 0b0000000; // data 0 to turn off LED of slave
hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(HSPI_SS, LOW);
hspi->transfer(data_on);
digitalWrite(HSPI_SS, HIGH);
hspi->endTransaction();
delay(1000);
hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
digitalWrite(HSPI_SS, LOW);
hspi->transfer(data_off);
digitalWrite(HSPI_SS, HIGH);
hspi->endTransaction();
delay(1000);
}
*/
Slave Code:
#include <ESP32SPISlave.h>
ESP32SPISlave slave;
static constexpr uint32_t BUFFER_SIZE {32};
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];
#define LED 2
void setup() {
Serial.begin(115200);
delay(2000);
pinMode(LED, OUTPUT);
// begin() after setting
// HSPI = CS: 15, CLK: 14, MOSI: 13, MISO: 12 -> default
// VSPI = CS: 5, CLK: 18, MOSI: 23, MISO: 190
slave.setDataMode(SPI_MODE0);
slave.begin();
// slave.begin(VSPI); // you can use VSPI like this
// clear buffers
memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}
void loop() {
// block until the transaction comes from master
Serial.println("Initialize...");
slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);
Serial.println("*********************");
// if transaction has completed from master,
// available() returns size of results of transaction,
// and buffer is automatically updated
char data;
while (slave.available()) {
// show received data
Serial.print("Command Received: ");
Serial.println(spi_slave_rx_buf[0]);
data = spi_slave_rx_buf[0];
slave.pop();
}
if(data == 1 )
{
Serial.println("Setting LED active HIGH ");
digitalWrite(LED, HIGH);
}
else if(data == 0 )
{
Serial.println("Setting LED active LOW ");
digitalWrite(LED, LOW);
}
}
2 Answers 2
For ESP32, unless the exact board variant is specified, by default the macros for MISO
, MOSI
, SCK
and SS
are defined as follows and are used for VSPI(i.e. SPI0):
static const uint8_t SS = 5;
static const uint8_t MOSI = 23;
static const uint8_t MISO = 19;
static const uint8_t SCK = 18;
This can be seen in the source code and HSPI is automatically configured to use SCLK 14, MISO 12, MOSI 13 and SS 15 when SPI.begin()
is called, see this part of the source code.
Since you defined HSPI_SS
as #define HSPI_SS SS
, when you do pinMode(HSPI_SS, OUTPUT);
, you are actually setting pin 5 as output, not the pin 15 that you thought it was.
There are two ways to properly set up the HSPI port.
- What you can do is to define the macros as follows and call
hspi->begin();
by passing your configuration:
#define HSPI_MISO 12
#define HSPI_MOSI 13
#define HSPI_SCLK 14
#define HSPI_SS 15
void setup() {
hspi = new SPIClass(HSPI);
hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, HSPI_SS);
// rest of your setup code
}
- As you can see from the source code shown in the above link, if you don't explicitly pass the pins as parameters when calling
SPI.begin()
, the library will automatically assign the pins based on whether VSPI is used (SCLK 18, MISO 19, MOSI 23, SS 5), or HSPI is used (SCLK 14, MISO 12, MOSI 13 and SS 15). So all you need to define is yourHSPI_SS
pin:
#define HSPI_SS 15
void setup() {
hspi = new SPIClass(HSPI);
hspi->begin();
// rest of your setup code
}
-
Thank you so much. I managed to send a string expression. Below you can see the Slave-Master codes that send messages from Master to Slave using the "Hello From Master" string.Enes Orhan– Enes Orhan2023年11月30日 09:36:36 +00:00Commented Nov 30, 2023 at 9:36
You can see the Slave-Master codes that send messages from Master to Slave using the "Hello From Master" string.
Master Code:
#include <SPI.h>
#ifdef ALTERNATE_PINS
#define VSPI_MISO 19
#define VSPI_MOSI 23
#define VSPI_SCLK 18
#define VSPI_SS 5
#else
#define VSPI_MISO MISO
#define VSPI_MOSI MOSI
#define VSPI_SCLK SCK
#define VSPI_SS SS
#endif
static const int spiClk = 1000000; // 1 MHz
char input;
const int size_arr = 25;
char buf[size_arr];
String sendData = "Hello from Master";
//uninitalised pointers to SPI objects
SPIClass* vspi = NULL;
void setup() {
Serial.begin(115200);
vspi = new SPIClass(VSPI);
#ifndef ALTERNATE_PINS
vspi->begin();
#else
vspi->begin(VSPI_SCLK, VSPI_MISO, VSPI_MOSI, VSPI_SS);
#endif
pinMode(VSPI_SS, OUTPUT); //HSPI SS
vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
}
void loop() {
input = Serial.read();
if(input == 's'){
sendData.toCharArray(buf, size_arr);
spi_transmis(VSPI_SS, buf);
}
delay(50);
}
void send_spi(int selectPin, byte pram) {
digitalWrite(selectPin, LOW);
vspi->transfer(pram);
digitalWrite(selectPin, HIGH);
vspi->endTransaction();
delayMicroseconds(75);
}
void spi_transmis(int selectPin, char buf[]) {
for (int i = 0; i < size_arr; i++) {
send_spi(selectPin, buf[i]);
}
send_spi(selectPin, '\n');
}
Slave Code:
#include <ESP32SPISlave.h>
ESP32SPISlave slave;
static constexpr uint32_t BUFFER_SIZE { 1 };
uint8_t spi_slave_tx_buf[BUFFER_SIZE];
uint8_t spi_slave_rx_buf[BUFFER_SIZE];
const int size_arr = 151;
char buf[size_arr];
volatile int pos = 0;
volatile bool active;
volatile bool process;
String received;
void setup() {
Serial.begin(115200);
slave.setDataMode(SPI_MODE0);
slave.begin(VSPI);
memset(spi_slave_tx_buf, 0, BUFFER_SIZE);
memset(spi_slave_rx_buf, 0, BUFFER_SIZE);
}
void loop() {
recvHandle();
spiHandler();
}
void spiHandler() {
slave.wait(spi_slave_rx_buf, spi_slave_tx_buf, BUFFER_SIZE);
while (slave.available()) {
char c = spi_slave_rx_buf[0];
if (c == '\n') {
buf[pos] = '0円';
process = true;
} else {
buf[pos++] = c;
}
slave.pop();
}
}
void recvHandle() {
if (process) {
received = String(buf);
process = false;
pos = 0;
Serial.println(received);
delayMicroseconds(20);
}
}
Explore related questions
See similar questions with these tags.