[SPI master] only recieving first byte from slave

StefanRvO
Posts: 16
Joined: Sun Mar 06, 2016 9:25 pm

[SPI master] only recieving first byte from slave

Postby StefanRvO » Sat Jul 22, 2017 6:35 pm

Hi
I'm trying to use the spi_master driver to communicate with an CS5463 Energy monitoring IC..

I have no problems with writing to the registers of the chip, but if i try to read them, I only recieve the first byte of the data sent on SDO. I have attached a logic analyzer, and i can see that the chip actually sends all the data, so it seems to be an issue on the ESP32 side.

I will write the most relevant pieces of code below, but it can be seen in its entirety at Github.

Code: Select all


#define SYNC0 0xFE
#define SYNC1 0xFF

CS5463::CS5463(gpio_num_t slave_select)
{
    printf("Creating device with CS %d\n", slave_select);
    spi_device_interface_config_t devcfg;
    memset(&devcfg, 0, sizeof(devcfg));
    devcfg.clock_speed_hz=2000000,               //Clock out at 2 MHz
    devcfg.mode=0,                                //SPI mode 0
    devcfg.spics_io_num = slave_select,               //CS pin
    devcfg.queue_size = 1,
    devcfg.pre_cb = nullptr;
    devcfg.command_bits = 8;
    ESP_ERROR_CHECK(spi_bus_add_device(HSPI_HOST, &devcfg, &this->spi));
}

void CS5463::init_spi(gpio_num_t miso, gpio_num_t mosi, gpio_num_t clk)
{
    if(CS5463::initialised == false)
    {   //Init spi device.
        printf("initialising SPI bus\n");
        spi_bus_config_t buscfg;
        memset(&buscfg, 0, sizeof(buscfg));
        buscfg.miso_io_num = miso;
        buscfg.mosi_io_num = mosi;
        buscfg.sclk_io_num = clk;
        buscfg.quadwp_io_num=-1;
        buscfg.quadhd_io_num=-1;
        ESP_ERROR_CHECK(spi_bus_initialize(HSPI_HOST, &buscfg, 1));
        CS5463::initialised = true;
    }
    else
        printf("SPI already initialised");
}



int CS5463::read_temperature(float *temp)
{
    int err;
    uint8_t data_out[3];
    err = this->read_register(registers::temperature, data_out);
    printf("0x%.2x%.2x%.2x\n", data_out[0], data_out[1], data_out[2]);
    *temp = (*(int8_t *)data_out);
    *temp += data_out[1] / float(1 << 7);
    *temp += data_out[2] / float(1 << 15);
    return err;
}

int CS5463::read_register(registers the_register, uint8_t *databuff)
{
    uint8_t data_out[3] = {SYNC1, SYNC1, SYNC1};
    return this->do_spi_transaction(the_register << 1, sizeof(data_out), data_out, databuff);
}

int CS5463::do_spi_transaction(uint8_t cmd, uint8_t len, uint8_t *data_out, uint8_t *data_in)
{
    spi_transaction_t t;
    printf("cmd: 0x%.2x, len: %d\n", cmd, len);
    memset(&t, 0, sizeof(t));       //Zero out the transaction
    t.length = len * 8;
    t.tx_buffer = data_out;
    t.rx_buffer = data_in;
    t.command = cmd;
    esp_err_t ret;
    xSemaphoreTake(this->spi_mux, portMAX_DELAY);
    ret = spi_device_transmit(this->spi, &t);  //Transmit!
    xSemaphoreGive(this->spi_mux);
    return ret;
}
When i call read_temperature(), i get the following output:
cmd: 0x26, len: 3
0x120000
However, with a logic analyser attached, i can see that the chip actually sends data in the last two bytes:
Image

Am I using the spi driver wrong, or what reasons can there be for the last two bytes not showing up in the rx_buffer?

Regards
Stefan

ESP_michael
Posts: 37
Joined: Mon Aug 28, 2017 10:25 am

Re: [SPI master] only recieving first byte from slave

Postby ESP_michael » Mon Aug 28, 2017 10:53 am

We've fixed several issues in past days. These issues exist when you use the RX DMA.
Please update to the latest idf and have a try.

However, I'm afraid there's still something wrong with the half-duplex mode and cannot be fixed in a short time.
The issue occurs when DMA is enabled in half-duplex mode and use MISO phase after a MOSI phase.
To quickly get around this issue, you may try one of the following method:

1. use full-duplex mode instead
2. disable the DMA by set the last parameter to 0 in bus initialization function just as belows:

Code: Select all

ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);
this may forbid you from transmitting and receiving data longer than 32 bytes.
3. try to use command and address field to replace the MOSI phase. They should be used at the same time, so the output length is restricted to 1+1 bytes at least and 2+8 bytes at most.

I highly recommand you to use the full-duplex mode. It's easier to use with fewer restrictions.

If the problem still exists, please come back again.

Who is online

Users browsing this forum: MicroController and 169 guests