ESP32 : a simple way to use spi hardware for simple devices like 74hc595 ?

Hi all,
at the beginning, I am trying to initialise the spi bus
I have the following error, can you please tell me what I am doing wrong :

about the structure :
sorry, unimplemented: non-trivial designated initializers not supported
};
^

#include<Arduino.h>
#include"driver/spi_master.h"// spi
#include"driver/gpio.h"// matrice

// ----------------------------------------------------------------------------
// Definition of macros
// ----------------------------------------------------------------------------

// setting SPI properties // HSPI_HOST
#definepin_num_mosi23 //// mis là pour le test avec analyse logique
#definepin_num_miso18 ////
#definepin_num_clk19

// ----------------------------------------------------------------------------
// Definition of global constants
// ----------------------------------------------------------------------------

void setup() {
Serial.begin(115200);

//Initialize the SPI bus
////esp_err_t ret;
spi_bus_config_t buscfg={
.miso_io_num = pin_num_miso,
.mosi_io_num = pin_num_mosi,
.sclk_io_num = pin_num_clk,
.quadwp_io_num = -1,
.quadhd_io_num = -1,
.max_transfer_sz = 32,

};
//Initialize the SPI bus

spi_bus_initialize(HSPI_HOST, &buscfg, 0); // DMA_CHAN = 0
////ESP_ERROR_CHECK(ret);

}

// ----------------------------------------------------------------------------
// Main control loop ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ----------------------------------------------------------------------------

/* un petit main qui fait travailler l’esp32 : */
void loop() {

digitalWrite(LED_BUILTIN,HIGH);

}

You're trying to compile C code using a C++ compiler. You need C++20 for designated initializers to work in C++.

Why not simply use the SPI library? https://github.com/espressif/arduino-esp32/tree/master/libraries/SPI

Here's what I use for driving 74HC595s over SPI: https://tttapa.github.io/Arduino-Helpers/Doxygen/d9/d5f/1_8SPI-Blink_8ino-example.html

Please use [code] tags when posting code.

Pieter

ESP32 using the SPI API under the Arduino IDE.

#include "ESP32_SPI_API.h"
/////////////////////////////
///////////////////////////
uint8_t txData[2] = { };
uint8_t rxData[25] = { };
uint8_t low;
int8_t high;
//////
//////////////////////////////////
uint8_t GetLowBits()
{
  return low;
}
int8_t GetHighBits()
{
  return high;
}
////////////////////////////////////////
int fInitializeSPI_Channel( int spiCLK, int spiMOSI, int spiMISO, spi_host_device_t SPI_Host, bool EnableDMA)
{
  esp_err_t intError;
  spi_bus_config_t bus_config = { };
  bus_config.sclk_io_num = spiCLK; // CLK
  bus_config.mosi_io_num = spiMOSI; // MOSI
  bus_config.miso_io_num = spiMISO; // MISO
  bus_config.quadwp_io_num = -1; // Not used
  bus_config.quadhd_io_num = -1; // Not used
  intError = spi_bus_initialize( HSPI_HOST, &bus_config, EnableDMA) ;
  return intError;
}
//////
int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin)
{
  esp_err_t intError;
  spi_device_interface_config_t dev_config = { };  // initializes all field to 0
  dev_config.address_bits     = 0;
  dev_config.command_bits     = 0;
  dev_config.dummy_bits       = 0;
  dev_config.mode             = 3 ;
  dev_config.duty_cycle_pos   = 0;
  dev_config.cs_ena_posttrans = 0;
  dev_config.cs_ena_pretrans  = 0;
  dev_config.clock_speed_hz   = 5000000;
  dev_config.spics_io_num     = csPin;
  dev_config.flags            = 0;
  dev_config.queue_size       = 1;
  dev_config.pre_cb           = NULL;
  dev_config.post_cb          = NULL;
  spi_bus_add_device(HSPI_HOST, &dev_config, &h);
  // return intError;
  // return h;
} // void fInitializeSPI_Devices()
///////////////////////////////////////////////////////////////
int fReadSPIdata16bits( spi_device_handle_t &h, int _address )
{
  uint8_t address = _address;
    esp_err_t intError = 0;
    low=0; high=0;
    spi_transaction_t trans_desc;
    trans_desc = { };
    trans_desc.addr =  0;
    trans_desc.cmd = 0;
    trans_desc.flags = 0;
    trans_desc.length = (8 * 3); // total data bits
    trans_desc.tx_buffer = txData;
    trans_desc.rxlength = 8 * 2 ; // Number of bits NOT number of bytes
    trans_desc.rx_buffer = rxData;
    txData[0] = address | 0x80;
    intError = spi_device_transmit( h, &trans_desc);
    low = rxData[0]; high = rxData[1];
  //  if ( intError != 0 )
  //  {
  //    Serial.print( " WHO I am LSM9DS1. Transmitting error = ");
  //    Serial.println ( esp_err_to_name(intError) );
  //  }
  return intError;
} // void fSendSPI( uint8_t count, uint8_t address, uint8_t DataToSend)
////
int fWriteSPIdata8bits( spi_device_handle_t &h, int _address, int _sendData )
{
  uint8_t address =  _address;
  uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 2); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = address  & 0x7F;
  txData[1] = sendData;
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
//  //  if ( intError != 0 )
//  //  {
//  //    Serial.print( " LSM9DS1_REGISTER_CTRL_REG6_XL. Transmitting error = ");
//  //    Serial.println ( esp_err_to_name(intError) );
//  //  }
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )
//

Using the SPI API is way more advantageous than using the Arduino IDE ESP32 core.

The OP should be able to see that under the Arduino IDE to initialize the SPI configuration structures it needs to be done a bit differently than in the examples.

PieterP: You're trying to compile C code using a C++ compiler. You need C++20 for designated initializers to work in C++. ok, will retry later

Why not simply use the SPI library? https://github.com/espressif/arduino-esp32/tree/master/libraries/SPI because just for me, simple and easy do not have the same meaning, yet I will follow your advice, thanks !

PieterP: Here's what I use for driving 74HC595s over SPI: https://tttapa.github.io/Arduino-Helpers/Doxygen/d9/d5f/1_8SPI-Blink_8ino-example.html awesome, maybe later, thanks

Please use [code] tags when posting code. but its ugly because of the colors ...

Pieter

Hi guys, thanks, I will try SPI

#include “ESP32_SPI_API.h”
#include “ESP32_SPI_API.c”

please where to find ?

trimarco232:

include "ESP32_SPI_API.h"

please where to find ?

Good question. It does not seem to be part of the standard ESP32 core installed by Arduino IDE. Perhaps @Idahowalker will be so kind to explain. [u]EDIT:[/u] As far as I could tell, it's @Idahowalker's creation: https://forum.arduino.cc/index.php?topic=723198.msg4862056#msg4862056

include "ESP32_SPI_API.c"

You NEVER #include a .c or .cpp file.

I have picked up the files here

and put ESP32_SPI_API.c in my scr repository

now I have the following error, in the ESP32_SPI_API.h file : include/ESP32_SPI_API.h:16:50: error: expected ';', ',' or ')' before '&' token int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin);

trimarco232:
#include “ESP32_SPI_API.h”
#include “ESP32_SPI_API.c”

please where to find ?

I wrote them. Is that what the OP wants to do write to use the ESP32 SPI API directly?

ESP32_SPI_API.h

#include <driver/spi_master.h>
#include "sdkconfig.h"
#include "esp_system.h" //This inclusion configures the peripherals in the ESP system.
////////////////////////////////////
//
//#define MAGTYPE  true
//#define XGTYPE   false
//////////////////////////
///////////////////////////
//
////////////////////////////
 uint8_t GetLowBits();
 int8_t GetHighBits();
 int fReadSPIdata16bits( spi_device_handle_t &h, int address );
 int fWriteSPIdata8bits( spi_device_handle_t &h, int address, int sendData );
 int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin);
// spi_device_handle_t fInitializeSPI_Devices( int csPin);
int fInitializeSPI_Channel( int spiCLK, int spiMOSI, int spiMISO, spi_host_device_t SPI_Host, bool EnableDMA);

trimarco232:
because just for me, simple and easy do not have the same meaning, yet I will follow your advice, thanks !

Then please post your definitions of simple and easy.

In my opinion, the SPI library is orders of magnitude simpler and easier than ESP32_SPI_API.c:

#include <SPI.h>

const uint8_t latchpin = 5;
const SPISettings settings{8000000, MSBFIRST, SPI_MODE0};

void setup() {
  SPI.begin();
  pinMode(latchpin, OUTPUT);
  digitalWrite(latchpin, HIGH);
}

void setShiftRegValue(uint8_t value) {
  SPI.beginTransaction(settings);
  digitalWrite(latchpin, LOW);
  SPI.transfer(value);
  digitalWrite(latchpin, HIGH);
  SPI.endTransaction();
}

void loop() {
  setShiftRegValue(0x55);
  delay(150);
  setShiftRegValue(0xAA);
  delay(150);
}

trimarco232:
but its ugly because of the colors …

Don’t post it with colors, use CTRL+SHIFT+V to paste without markup.

ESP32_SPI_API.cpp

#include "ESP32_SPI_API.h"
/////////////////////////////
///////////////////////////
uint8_t txData[2] = { };
uint8_t rxData[25] = { };
uint8_t low;
int8_t high;
//////
//////////////////////////////////
uint8_t GetLowBits()
{
  return low;
}
int8_t GetHighBits()
{
  return high;
}
////////////////////////////////////////
int fInitializeSPI_Channel( int spiCLK, int spiMOSI, int spiMISO, spi_host_device_t SPI_Host, bool EnableDMA)
{
  esp_err_t intError;
  spi_bus_config_t bus_config = { };
  bus_config.sclk_io_num = spiCLK; // CLK
  bus_config.mosi_io_num = spiMOSI; // MOSI
  bus_config.miso_io_num = spiMISO; // MISO
  bus_config.quadwp_io_num = -1; // Not used
  bus_config.quadhd_io_num = -1; // Not used
  intError = spi_bus_initialize( HSPI_HOST, &bus_config, EnableDMA) ;
  return intError;
}
//////
int fInitializeSPI_Devices( spi_device_handle_t &h, int csPin)
{
  esp_err_t intError;
  spi_device_interface_config_t dev_config = { };  // initializes all field to 0
  dev_config.address_bits     = 0;
  dev_config.command_bits     = 0;
  dev_config.dummy_bits       = 0;
  dev_config.mode             = 3 ;
  dev_config.duty_cycle_pos   = 0;
  dev_config.cs_ena_posttrans = 0;
  dev_config.cs_ena_pretrans  = 0;
  dev_config.clock_speed_hz   = 5000000;
  dev_config.spics_io_num     = csPin;
  dev_config.flags            = 0;
  dev_config.queue_size       = 1;
  dev_config.pre_cb           = NULL;
  dev_config.post_cb          = NULL;
  spi_bus_add_device(HSPI_HOST, &dev_config, &h);
  // return intError;
  // return h;
} // void fInitializeSPI_Devices()
///////////////////////////////////////////////////////////////
int fReadSPIdata16bits( spi_device_handle_t &h, int _address )
{
  uint8_t address = _address;
    esp_err_t intError = 0;
    low=0; high=0;
    spi_transaction_t trans_desc;
    trans_desc = { };
    trans_desc.addr =  0;
    trans_desc.cmd = 0;
    trans_desc.flags = 0;
    trans_desc.length = (8 * 3); // total data bits
    trans_desc.tx_buffer = txData;
    trans_desc.rxlength = 8 * 2 ; // Number of bits NOT number of bytes
    trans_desc.rx_buffer = rxData;
    txData[0] = address | 0x80;
    intError = spi_device_transmit( h, &trans_desc);
    low = rxData[0]; high = rxData[1];
  //  if ( intError != 0 )
  //  {
  //    Serial.print( " WHO I am LSM9DS1. Transmitting error = ");
  //    Serial.println ( esp_err_to_name(intError) );
  //  }
  return intError;
} // void fSendSPI( uint8_t count, uint8_t address, uint8_t DataToSend)
////
int fWriteSPIdata8bits( spi_device_handle_t &h, int _address, int _sendData )
{
  uint8_t address =  _address;
  uint8_t sendData = _sendData;
  esp_err_t intError;
  spi_transaction_t trans_desc;
  trans_desc = { };
  trans_desc.addr =  0;
  trans_desc.cmd = 0;
  trans_desc.flags = 0;
  trans_desc.length = (8 * 2); // total data bits
  trans_desc.tx_buffer = txData;
  trans_desc.rxlength = 0 ; // Number of bits NOT number of bytes
  trans_desc.rx_buffer = NULL;
  txData[0] = address  & 0x7F;
  txData[1] = sendData;
  intError = spi_device_transmit( h, &trans_desc);
  return intError;
//  //  if ( intError != 0 )
//  //  {
//  //    Serial.print( " LSM9DS1_REGISTER_CTRL_REG6_XL. Transmitting error = ");
//  //    Serial.println ( esp_err_to_name(intError) );
//  //  }
} // void fWriteSPIdata8bits(  spi_device_handle_t &h, uint8_t address, uint8_t sendData )
//

PieterP: In my opinion, the SPI library is orders of magnitude simpler and easier than ESP32_SPI_API.c:

For the average user with a ESP32 the ESP32 SPI Arduino Core is wonderful.

Also, the Arduino IDE ESP32 SPI core is chained down with default settings.

PieterP: Then please post your definitions of simple and easy.

imho : simple : SBI led_port, led_pin easy :

include strata of libraries

digital_write(led_pin, HIGH);

trimarco232: imho : simple : SBI led_port, led_pin easy :

include strata of libraries

digital_write(led_pin, HIGH);

So, what are you looking for with this thread?

about the structure :
sorry, unimplemented: non-trivial designated initializers not supported
};

I showed the OP how to use ESP32 API structures under the Arduino IDE by posting an example of usage.

gfvalvo: So, what are you looking for with this thread?

to try to program hardware spi as close as possible to the api, in an easy way (I have done it with the ledc api, it was ok)

because some times I want to do custom settings like a transmission baudrate that is not part of the proposed values but may be spi api is still above my programming skills, so I'll have to go back to the spi library, and hope it will fit my needs in this case I will try PieterP's example but before let's give @Idahowalker a chance :)

trimarco232: but before let's give Idahowalker a chance :)

OK, then go with @Idahowalker's example code, modifying as necessary for your application.

Idahowalker: I showed the OP how to use ESP32 API structures under the Arduino IDE by posting an example of usage.

I am under platformio IDE, may this cause problems with this ?

I have no idea.