ESP32S3 SPI communication not working

Hello, I’m having problems making the SPI communication to work, it stops mid-transfer…

My setup:
VSCode with Platformio, Espressif32 v6.10.0 using esp-idf
Microcontroller: ESP32S3
IC to communicate with via SPI: BL0942

I’ve made a very simple implementation, just to try out SPI master API, following this example code from esp-idf github repository.
This is my resulting test code:

#include "bl0942.h"
#include <stdlib.h>
#include <string.h>
#include "esp_log.h"
#include "driver/spi_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"

const char *TAG = "BL0942";
#define PIN_SPI_MOSI                        13
#define PIN_SPI_MISO                        11
#define PIN_SPI_SCK                         12

#define BL0942_REG_VOLTAGE                  0x08

bl0942_config_t *BL0942_PARAMS = nullptr;
spi_device_handle_t spi_bl0942_handle;

bl0942_status_t bl0942_spi_init(void);

bl0942_status_t bl0942_read_reg_spi(uint8_t reg_id, uint8_t *res, size_t size_reg);

bl0942_status_t bl0942_init(bl0942_config_t *config)
{
    if (config == nullptr)
    {
        ESP_LOGE(TAG, "%s - Null params", __func__);
        return BL0942_STATUS_ERR;
    }
    BL0942_PARAMS = config;
    if (bl0942_spi_init() != BL0942_STATUS_OK)
    {
        ESP_LOGE(TAG, "%s - Error SPI init", __func__);
        return BL0942_STATUS_ERR;
    }
    ESP_LOGI(TAG, "%s - BL0942 initialized", __func__);
    return BL0942_STATUS_OK;
}

bl0942_status_t bl0942_get_data(bl0942_data_t *data)
{
    if (data == nullptr)
    {
        ESP_LOGE(TAG, "%s - Null params", __func__);
        return BL0942_STATUS_ERR;
    }
    uint8_t buffer[4] = {0};
    //Read voltage value
    bl0942_read_reg_spi(BL0942_REG_VOLTAGE, buffer, sizeof(buffer));
    return BL0942_STATUS_OK;
}

bl0942_status_t bl0942_spi_init(void)
{
    //Init the SPI bus
    spi_bus_config_t buscfg = {
        .mosi_io_num = PIN_SPI_MOSI,
        .miso_io_num = PIN_SPI_MISO,
        .sclk_io_num = PIN_SPI_SCK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = 32,
    };
    esp_err_t ret = spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    //Init device
    spi_device_interface_config_t devcfg = {
      .command_bits = 0,                        //No command bits
      .address_bits = 0,                        //No address bits
      .dummy_bits = 0,                          //No dummy bits
      .mode = 1,                                //SPI mode 1: CPOL=0 CPHA=1
      .clock_source = SPI_CLK_SRC_DEFAULT,      //Use APB clock
      .duty_cycle_pos = 128,                    //50% duty cycle
      .cs_ena_pretrans = 0,                     //No CS activation before transaction
      .cs_ena_posttrans = 0,                    //No CS deactivation after transaction
      .clock_speed_hz = 9 * 100 * 1000,         //Clock out at 900 kHz
      .input_delay_ns = 0,                      //No input delay
      .spics_io_num = 10,                       //CS pin
      .flags = 0,                               //No flags
      .queue_size = 7,                          //We want to be able to queue 7 transactions at a time
      .pre_cb = nullptr,                        //Specify pre-transfer callback to handle D/C line,
      .post_cb = nullptr
    };
    //add device to the bus
    ret = spi_bus_add_device(SPI2_HOST, &devcfg, &spi_bl0942_handle);
    if (ret != ESP_OK) {
      ESP_LOGE(TAG, "%s - Error to add SPI device to the bus: %s", __func__, esp_err_to_name(ret));
      return BL0942_STATUS_ERR;
    }
    return BL0942_STATUS_OK;
}

bl0942_status_t bl0942_read_reg_spi(uint8_t reg_id, uint8_t *res, size_t size_reg)
{
    spi_transaction_t t;
    memset(&t, 0, sizeof(t));
    t.length = 32;
    t.tx_data[0] = reg_id;
    t.rxlength = 24;
    t.flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA;
    if (spi_device_transmit(spi_bl0942_handle, &t) != ESP_OK)
    {
        ESP_LOGE(TAG, "%s - Error to read SPI register", __func__);
        return BL0942_STATUS_ERR;
    }
    ESP_LOGI(TAG, "%s - Data read: %02X%02X%02X%02X", __func__, t.rx_data[0], t.rx_data[1], t.rx_data[2], t.rx_data[3]);
    //Copy data
    memcpy(res, t.rx_data, size_reg);
    return BL0942_STATUS_OK;
}

Here is the esp32 logs of the firmware (you can see there are no error in initialization):

I (316) main_task: Started on CPU0
I (326) main_task: Calling app_main()
I (326) BL0942: bl0942_init - BL0942 initialized
I (326) BL0942: bl0942_read_reg_spi - Data read: FFFFFFFF

And here is what happens looking at the gpios with the logic analyzer:

Is like the SPI lines don’t work properly, I’m very confused.

I’ve tried to change various configurations to the device and the bus, I’ve followed the SPI connections for the SPI2_HOST pinout from the SPI Master Driver API reference

If someone has any input on this, perhaps very silly, problem I will appreciate it very much

From the BL0942 datasheet:

In SPI communication method, first send 8bit initial byte (0x58) or (0xa8), (0x58) is read operation
identification byte, (0xa8) is write operation identification byte, and then send register address of BL0942

So you need to transmit 5 bytes, 0x58, register address, 0x00, 0x00, 0x00, and the MISO data should be read as also 5 bytes, with only the last 3 bytes used.

Better go even slower for testing. This should also make it easier to capture the signal with a logic analyzer. You’re not showing at which sample frequency you’ve captured your signals, but you should at least 4 times oversample.

1 Like

That is very true @maxgerhardt , I had a problem with the sampling of the logic analyzer, mine reaches 500kS/s. So I tried lowering the clock speed to 100kHz and the logic analyzer worked correctly.
On the other hand, I was also missing the implementation of the SPI communication for the BL0942 IC. And some other issues in the initialization of the tx_buffer and rx_buffer of the spi_transaction_t.

Thank you very much!