I am trying to interface a GPIO Expander MCP23S18 (using SPI) with my ESP32-S2. The library used is spi_slave/sender/app_main.c and driver spi_master.h from components/drivers.
I don't understand what is going wrong and why it fails to work. My code is as below. Please help me with your inputs.
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
#include "gpio_expander.h"
#include "definitions.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "esp_spi_flash.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include <stdbool.h>
#define GPIO_MOSI 35
#define GPIO_MISO 37
#define GPIO_SCLK 36
#define GPIO_CS 41
static uint8_t state_low = 0;
static uint8_t state_high = 1;
#define WRITEADDR 0x40
#define IO_DIR_REG 0x00
#define GPIO_REG 0x09
#define SENDER_HOST SPI3_HOST
static const char *TAG = "GPIOEXP833";
esp_err_t ret;
spi_device_handle_t handle;
spi_transaction_t t;
int initgpio(task_t *_this)
{
if(_this->state > TASKSTATE_UNINITIALIZED) {
return -1;
}
gpio_config_t io_conf;
io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL<<GPIO_CS);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
gpio_reset_pin(GPIO_CS);
gpio_set_direction(GPIO_CS, GPIO_MODE_OUTPUT);
//Configuration for the SPI bus
spi_bus_config_t buscfg={
.mosi_io_num=GPIO_MOSI,
.miso_io_num=GPIO_MISO,
.sclk_io_num=GPIO_SCLK,
.quadwp_io_num=-1,
.quadhd_io_num=-1
};
//Configuration for the SPI device on the other side of the bus
spi_device_interface_config_t devcfg={
.command_bits=8,
.address_bits=8,
.dummy_bits=0,
.clock_speed_hz=5000000,
.duty_cycle_pos=128, //50% duty cycle
.mode=1,
.spics_io_num=GPIO_CS, //(1ULL<<GPIO_CS),
.cs_ena_posttrans=3, //Keep the CS low 3 cycles after transaction, to stop slave from missing the last bit when CS has less propagation delay than CLK
.queue_size=3
};
//Initialize the SPI bus and add the device we want to send stuff to.
ret=spi_bus_initialize(SENDER_HOST, &buscfg, SPI_DMA_CH_AUTO);
assert(ret==ESP_OK);
if (ret != ESP_OK) {
ESP_LOGI(TAG, "initialization failed");
}
else {
ESP_LOGI(TAG, "SPI initialized");
}
ret=spi_bus_add_device(SENDER_HOST, &devcfg, &handle);
assert(ret==ESP_OK);
t.flags = 0x0000;
t.tx_buffer=NULL;
t.rx_buffer=NULL;
t.user=IO_DIR_REG;
_this->state = TASKSTATE_RUNNING;
return -1;
}
void execgpio(task_t *_this) {
gpio_set_level(GPIO_CS, state_low);
t.cmd=WRITEADDR;
t.addr=GPIO_REG;
t.user=0x02;
// memset(&t, 0, sizeof(t));
ret=spi_device_transmit(handle, &t);
gpio_set_level(GPIO_REG, 0x02);
gpio_set_level(GPIO_CS, state_high);
}
Using the ESP32's SPI API is possible under the Arduino IDE.
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);
Thank you @Idahowalker. I have changed my configurations likewise. Which SPI host are you using?
typedef enum {
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master and SPI Slave driver on ESP32-S2
SPI1_HOST=0, ///< SPI1
SPI2_HOST=1, ///< SPI2
SPI3_HOST=2, ///< SPI3
SPI_HOST_MAX=3, ///< invalid host value
} spi_host_device_t;
Thank you @Idahowalker. So now I know that the SPI I am using is right. Below is my configuration:
However when I observe my spi signals on an analyzer, the MOSI data appears to be in reversed polarity (as in the image). Could you please tell me what parameters need to included or what existing configurations are to be changed so that MOSI is synced with the clock? I already played with frequency and spi mode. Thank you
Yes it compiles and flashes without an error. It gives an error only when my command bits and address bits are set to zero and that makes sense cause I'm send 8 bit command and address.