Help with SPI Reading Not Working Properly

xpress_embedo
Posts: 12
Joined: Fri Jul 07, 2023 6:26 pm

Help with SPI Reading Not Working Properly

Postby xpress_embedo » Sun Jan 21, 2024 2:57 pm

Hello Everyone,

I am new to ESP32 and the ESP-IDF framework. I wanted to read some data over SPI, but it is not working, can someone please help me?
I am sharing my code below.

Code: Select all

#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define TOUCH_SPI_CLK_SPEED           (250 * 1000)
#define TOUCH_SPI_HOST                (SPI3_HOST)
#define TOUCH_SPI_MOSI                (GPIO_NUM_23)
#define TOUCH_SPI_MISO                (GPIO_NUM_19)
#define TOUCH_SPI_SCLK                (GPIO_NUM_18)
#define TOUCH_SPI_CS                  (GPIO_NUM_2)

#define TOUCH_CS_LOW()               gpio_set_level(TOUCH_SPI_CS, 0)
#define TOUCH_CS_HIGH()              gpio_set_level(TOUCH_SPI_CS, 1)

// Private Variables
spi_device_handle_t spi_touch_handle;

// Private Functions
void touch_read_data( uint8_t cmd, uint8_t *data, uint8_t len );

void app_main(void)
{
  //Initialize non-SPI GPIOs
  gpio_config_t io_conf = {};
  io_conf.pin_bit_mask = (1u<<TOUCH_SPI_CS);
  io_conf.mode = GPIO_MODE_OUTPUT;
  io_conf.pull_up_en = true;
  gpio_config(&io_conf);

  // bus configuration
  spi_bus_config_t touch_bus_cfg =
  {
    .mosi_io_num = TOUCH_SPI_MOSI,
    .miso_io_num = TOUCH_SPI_MISO,
    .sclk_io_num = TOUCH_SPI_SCLK,
    .max_transfer_sz = 200,
    .quadhd_io_num = -1,
    .quadwp_io_num = -1,
  };

  // touch device configuration
  spi_device_interface_config_t touch_dev_config =
  {
    .clock_speed_hz = TOUCH_SPI_CLK_SPEED,
    .mode = 0,
    .spics_io_num = -1,
    .input_delay_ns = 0,
    .queue_size = 50,
    .pre_cb = NULL,
    .post_cb = NULL,
    .flags = SPI_DEVICE_NO_DUMMY,
  };

  esp_err_t ret;
  spi_dma_chan_t dma_channel = SPI_DMA_CH1;   // don't enable DMA on Channel-0

  // initialize the SPI bus
  ret = spi_bus_initialize(TOUCH_SPI_HOST, &touch_bus_cfg, dma_channel);
  assert(ret == ESP_OK);

  // attach the touch to the SPI bus
  ret = spi_bus_add_device(TOUCH_SPI_HOST, &touch_dev_config, &spi_touch_handle);
  assert(ret == ESP_OK);

  TOUCH_CS_LOW();
  TOUCH_CS_HIGH();

  while (true)
  {
    uint8_t data[2] = {0x00, 0x00};
    touch_read_data(0x90, data, 2);
    printf("X = 0x%x, 0x%X\n", data[0], data[1] );
    data[0] = 0x00;
    data[1] = 0x00;
    touch_read_data(0xD0, data, 2);
    printf("X = 0x%x, 0x%X\n\n", data[0], data[1] );
    sleep(2);
  }
}
I wrote two versions of the "touch_read_data" function.

Code: Select all

void touch_read_data( uint8_t cmd, uint8_t *data, uint8_t len )
{
  esp_err_t ret;
  spi_transaction_t t;

  TOUCH_CS_LOW();
  memset( &t, 0x00, sizeof(t) );    // zero out the transaction
  t.length = (len + sizeof(cmd)) * 8;
  t.rxlength = (len * 8);
  t.cmd = cmd;
  t.rx_buffer = data;
  t.flags = SPI_TRANS_USE_RXDATA;
  ret = spi_device_polling_transmit(spi_touch_handle, &t);  // transmit
  // ret = spi_device_transmit(spi_touch_handle, &t);  // transmit
  TOUCH_CS_HIGH();
  assert(ret == ESP_OK);
}
This one is not working and UART I am getting 0x00, 0x00 for both reads.
I investigated by connecting the logic analyzer (unfortunately due to my setup problem, I can't connect the logic analyzer when the slave device is connected, which means that I can see what is transmitted but not what is received which is always 0xFF)
The following is the output, as can be seen, the command is not transmitted properly, I don't understand why.

Image

The other version of the function is this.

Code: Select all

void touch_read_data( uint8_t cmd, uint8_t *data, uint8_t len )
{
  esp_err_t ret;
  spi_transaction_t t;
  TOUCH_CS_LOW();
  memset( &t, 0x00, sizeof(t) );    // zero out the transaction
  t.length = 8;                     // Commands are 8-bits
  t.tx_buffer = &cmd;               // The data is command itself
  ret = spi_device_polling_transmit(spi_touch_handle, &t);  // transmit
  assert(ret == ESP_OK);            // should have no issues
  if( len )
  {
    memset( &t, 0x00, sizeof(t) );    // zero out the transaction
    t.length = len*8;
    t.rxlength = (len * 8);
    t.rx_buffer = data;
    t.flags = SPI_TRANS_USE_RXDATA;
    ret = spi_device_polling_transmit(spi_touch_handle, &t);  // transmit
    TOUCH_CS_HIGH();
    assert(ret == ESP_OK);
  }
  TOUCH_CS_HIGH();
}
And this is also not working, while reading the data I am getting 0x00, 0x00. The waveforms on the logic analyzer are as below.
Image

Here the transmitted commands are 0x90, 0xFF, and 0xFB, I don't know why 0xFF and 0xFB are transmitted, it should be 0x00, or maybe I don't know.
As I mentioned as of now I can't sniff the MISO line using a logic analyzer, so don't know what is coming from the device.
But when the device is connected, I am still getting zeros.

Can someone please help, if I made some mistake here.
Attachments
ESP32-SPI-Function-2.png
ESP32-SPI-Function-2.png (106.12 KiB) Viewed 1810 times
ESP32-SPI-Function-1.png
ESP32-SPI-Function-1.png (102.09 KiB) Viewed 1810 times

xpress_embedo
Posts: 12
Joined: Fri Jul 07, 2023 6:26 pm

Re: Help with SPI Reading Not Working Properly

Postby xpress_embedo » Mon Jan 22, 2024 8:48 pm

Hi Guys, is there anyone who can help me here?

I found one which could be a mistake but this change doesn't solve the problem.

Code: Select all

spi_dma_chan_t dma_channel = SPI_DMA_DISABLED;
Experts, please suggest.

ESP_Sprite
Posts: 9708
Joined: Thu Nov 26, 2015 4:08 am

Re: Help with SPI Reading Not Working Properly

Postby ESP_Sprite » Tue Jan 23, 2024 3:23 am

The 2nd waveform looks OK to me. You're not specifying any data to TX, so I imagine the driver simply sends dummy bytes. For the first waveform; the driver won't send the data in cmd unless you tell it to (I think it's a flag somewhere).

xpress_embedo
Posts: 12
Joined: Fri Jul 07, 2023 6:26 pm

Re: Help with SPI Reading Not Working Properly

Postby xpress_embedo » Tue Jan 23, 2024 8:49 pm

ESP_Sprite wrote:
Tue Jan 23, 2024 3:23 am
The 2nd waveform looks OK to me. You're not specifying any data to TX, so I imagine the driver simply sends dummy bytes. For the first waveform; the driver won't send the data in cmd unless you tell it to (I think it's a flag somewhere).
Thank You very much, your hint solved my problem. In the device configuration, I added "command_bits = 8", as shown below.

Code: Select all

  // touch device configuration
  spi_device_interface_config_t touch_dev_config =
  {
    .clock_speed_hz = TOUCH_SPI_CLK_SPEED,
    .mode = 0,
    .spics_io_num = -1,
    .input_delay_ns = 0,
    .queue_size = 50,
    .pre_cb = NULL,
    .post_cb = NULL,
    .command_bits = 8,
    .flags = SPI_DEVICE_NO_DUMMY,
  };
And then modified the "touch_data_read" function as.

Code: Select all

void touch_read_data( uint8_t cmd, uint8_t *data, uint8_t len )
{
  esp_err_t ret;
  spi_transaction_t t;

  TOUCH_CS_LOW();
  memset( &t, 0x00, sizeof(t) );    // zero out the transaction
  t.length = (len) * 8;
  t.rxlength = (len * 8);
  t.cmd = cmd;
  t.rx_buffer = data;
  // t.flags = SPI_TRANS_USE_RXDATA;   // when SPI_TRANS_USE_RXDATA, data is present in rx_data buffer otherwise rx_buffer
  t.flags = 0;                          // data will be recived in rx_buffer
  ret = spi_device_polling_transmit(spi_touch_handle, &t);  // transmit
  // ret = spi_device_transmit(spi_touch_handle, &t);  // transmit
  // rx_data will contain data only when t.flags = SPI_TRANS_USE_RXDATA
  // printf("rx_data = 0x%x, 0x%X\n", t.rx_data[0], t.rx_data[1]);
  data = t.rx_data;
  TOUCH_CS_HIGH();
  assert(ret == ESP_OK);
}
When t.flags = SPI_TRANS_USE_RXDATA, the received data is in rx_data buffer else in data.
One thing which I am not able to understand is t.length I thought it's value shall be (len + sizeof(cmd)) * 8, but instead I have to set (len) * 8.
And after changing this, I am getting sensible data from the slave device.
Many Thanks

ESP_Sprite
Posts: 9708
Joined: Thu Nov 26, 2015 4:08 am

Re: Help with SPI Reading Not Working Properly

Postby ESP_Sprite » Wed Jan 24, 2024 8:52 am

Length is the length of the data, in bits. Command (and address, if you use that) fields do not count against that; as you saw, you specify those when attaching the device to the SPI bus.

xpress_embedo
Posts: 12
Joined: Fri Jul 07, 2023 6:26 pm

Re: Help with SPI Reading Not Working Properly

Postby xpress_embedo » Sat Jan 27, 2024 5:27 pm

ESP_Sprite wrote:
Wed Jan 24, 2024 8:52 am
Length is the length of the data, in bits. Command (and address, if you use that) fields do not count against that; as you saw, you specify those when attaching the device to the SPI bus.
Thanks for clarification.

Who is online

Users browsing this forum: MicroController and 80 guests