ESP32-S3 SPI on custom GPIO pins

biggerfish
Posts: 4
Joined: Mon Jan 06, 2025 7:03 pm

ESP32-S3 SPI on custom GPIO pins

Postby biggerfish » Sat Jan 31, 2026 8:15 pm

Hello,

I posted a similar question about a year ago. I am porting Arduino IDE code to ESP-IDF and cannot get SPI on ESP-IDF to work.

My code interfaces with a ADC that supports full duplex, SPI Mode 1 (TI AMC131M01).

I need to send the command 0x7880 followed by 0x0001. A dummy CRC is used to pad this to 24-bits.

When I use Arduino SPI.h, I send and receive the following data, which is correct:

SEND: 0x78 80 00 00 01 00 00 00 00 00 00 00 00 00 00

RECV: 0xFF 21 00 80 00 00 C3 10 00 58 80 00 80 00 00

However when I try to send the same thing using the ESP-IDF SPI library, I get an incorrect response.

SEND: 0x78 80 00 00 01 00 00 00 00 00 00 00 00 00 00

RECV: 0x02 a0 00 00 00 00 2e 3c 80 00 11 00 00 00 00

Is there additional configuration to set up the following GPIO pins to work with SPI? This is the only thing I can think of:

CS -> GPIO 16
MOSI -> GPIO 15
MISO -> GPIO 8
SCK -> GPIO 17

I'm using the following code:

Code: Select all


#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"
#include "esp_system.h"

#include "driver/gpio.h"
#include "hal/gpio_types.h"
#include "esp_intr_types.h"
#include <driver/spi_master.h>
#include <string.h>
#define ADC_CS_PIN GPIO_NUM_16
#define ADC_MOSI_PIN GPIO_NUM_15 // DIN
#define ADC_MISO_PIN GPIO_NUM_8 // DOUT
#define ADC_SCK_PIN GPIO_NUM_17
spi_device_handle_t adc_spi_handle;

void write_spi(uint8_t *data,int n,bool echo)
{
  if(echo)
  {
    printf("SEND: 0x");
    for(int i = 0; i < n; i++)
    {
        printf("%02x",data[i]);
        printf(" ");
    }
    printf("\n");
  }
  spi_transaction_t spi_transaction = {};
  //memset(&spi_transaction,0,sizeof(spi_transaction));
  spi_transaction.addr = 0;
  spi_transaction.cmd = 0;
  spi_transaction.flags = 0;
  spi_transaction.length = n*8;
  spi_transaction.rxlength = n*8;
  spi_transaction.tx_buffer = data;
  spi_transaction.rx_buffer = data;

  gpio_set_level(ADC_CS_PIN, 0);
  vTaskDelay(10 / portTICK_PERIOD_MS);
  esp_err_t ret = spi_device_transmit(adc_spi_handle,&spi_transaction);
  vTaskDelay(10 / portTICK_PERIOD_MS);
  gpio_set_level(ADC_CS_PIN, 1);
  ESP_ERROR_CHECK(ret);

  if(echo)
  {
    printf("RECV: 0x");
    for(int i = 0; i < n; i++)
    {
        printf("%02x",data[i]);
        printf(" ");
    }
    printf("\n");
  }


}

void enable_adc()
{
    // Send the WREG command to the AMC131M01 ADC. This command should write 0x0001 to the DCDC_CTRL register
    uint8_t adc_data[] = {0x78, 0x80, 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
    // I think I should receive 0x5880 response in bytes 9 and 10.
    write_spi(adc_data,15,true);
}
void app_main(void)
{
  gpio_reset_pin(ADC_CS_PIN);
  gpio_reset_pin(ADC_MOSI_PIN);
  gpio_reset_pin(ADC_MISO_PIN);
  gpio_reset_pin(ADC_SCK_PIN);
  gpio_set_direction(ADC_CS_PIN, GPIO_MODE_OUTPUT);
  gpio_set_level(ADC_CS_PIN, 1);
  spi_bus_config_t spi_config = {};
  //memset(&spi_config,0,sizeof(spi_config));
  spi_config.mosi_io_num = ADC_MOSI_PIN;
  spi_config.miso_io_num = ADC_MISO_PIN;
  spi_config.sclk_io_num = ADC_SCK_PIN;
  spi_config.quadwp_io_num = -1;
  spi_config.quadhd_io_num = -1;
  spi_config.data4_io_num = -1;
  spi_config.data5_io_num = -1;
  spi_config.data6_io_num = -1;
  spi_config.data7_io_num = -1;
  spi_config.max_transfer_sz = 256;
  spi_config.intr_flags = 0;
  spi_config.flags = SPICOMMON_BUSFLAG_MASTER;
  spi_config.isr_cpu_id = ESP_INTR_CPU_AFFINITY_0;
      
  spi_device_interface_config_t devcfg = {};
  // memset(&devcfg,0,sizeof(devcfg));
  devcfg.command_bits = 0;
  devcfg.address_bits = 0;
  devcfg.dummy_bits = 0;
  devcfg.mode = 1;
  devcfg.duty_cycle_pos   = 128;
  devcfg.cs_ena_posttrans = 0;
  devcfg.cs_ena_pretrans  = 0;
  devcfg.clock_speed_hz = 25000000;
  devcfg.clock_source = SPI_CLK_SRC_APB;
  devcfg.spics_io_num = ADC_CS_PIN;
  devcfg.flags            = 0;
  devcfg.queue_size       = 1;
  devcfg.pre_cb           = NULL;
  devcfg.post_cb          = NULL;
  devcfg.input_delay_ns = 0;

  esp_err_t ret = spi_bus_initialize(SPI2_HOST,&spi_config,SPI_DMA_DISABLED);
  vTaskDelay(100 / portTICK_PERIOD_MS);
  ESP_ERROR_CHECK(ret);
  ret = spi_bus_add_device(SPI2_HOST,&devcfg,&adc_spi_handle);
  vTaskDelay(100 / portTICK_PERIOD_MS);
  ESP_ERROR_CHECK(ret);



  while(true)
  {
    enable_adc();
    vTaskDelay(5000 / portTICK_PERIOD_MS);
  }

}


The equivalent Arduino SPI.h code works just fine however:

Code: Select all

	SPI.begin();
	SPISettings settingsA(25000000,MSBFIRST,SPI_MODE1);
	SPI.beginTransaction(settingsA);
	pinMode(ADC_CS_PIN,OUTPUT);
	uint8_t data[] = {0x78, 0x80, 0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
	digitalWrite(ADC_CS_PIN,LOW);
	SPI.transfer(data,n);
	digitalWrite(ADC_CS_PIN,HIGH);

Who is online

Users browsing this forum: Applebot, Baidu [Spider], Bytespider, ChatGPT-User, meta-externalagent, PerplexityBot, Qwantbot and 3 guests