SPI only returns 0xffff

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Rova_1179706
Level 2
Level 2
First like received First like given

Dear community,

For a couple of days I'm trying to extract data from a sensor. I tried using the examples and application notes but could not get it working. I tried it with DMA and interrupts but quickly decided it was too difficult.

The waveforms look good and the Logic analyser displays the correct information. The image below shows a single read-transaction. I only need the second value 0xA800.

pastedImage_0.png

main loop

    for(;;)

    {

        UART_PutString("Start Loop:\r\n");

        clearErrors();

        for( int i =0; i < 10; i++){

            printf("%x\r\n", readSPIWord(0x24));

        }

       

        CyDelay(1000);

    }

functions

void clearErrors(){

    //Write bit + 1E address + 07 data

    SPI_Write(0x1E07 & SPI_WRITE_BITMASK);

    //Write bit + 1F address + 0x46 keycode

    SPI_Write(0x1F46 & SPI_WRITE_BITMASK);

}

uint16 readSPIWord(uint8 address)

{

    uint16 readword;

    SPI_Write(address << 8);

    while(SPI_IsBusBusy());

    SPI_ClearRxFifo();

    SPI_Write(0x0000);

    while(SPI_IsBusBusy());

    readword = SPI_Read();

    return (uint16)readword;

}

(Wrong) Result

pastedImage_17.png

Could someone point me in the correct direction?

0 Likes
1 Solution

Hi Moto,

I have succeeded in getting (the correct) data with the following code. I needed to wait until the RX FIFO was cleared entirely. Then write the two words and wait until the FIFO contains them. It feels like a hack to me.

int main(void)

{

    uint8 addresses[9] = {0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x34, 0x36};

    __enable_irq();

    UART_Start();

    /* Also calls init, sets slave to 0 and calls enables */

    SPI_Start();

    UART_PutString("Hello");

    for(;;)

    {

        UART_PutString("\r\nStart Loop:\r\n");

        clearErrors();

        for( int i =0; i < 9; i++){

            readSPIWord(addresses);

        }

        CyDelay(1000);

    }

}

void clearErrors(){

    //Write bit + 1E address + 07 data

    SPI_Write(0x1E07 | (SPI_WRITE_BITMASK << 8));

    //Write bit + 1F address + 0x46 keycode

    SPI_Write(0x1F46 | (SPI_WRITE_BITMASK << 8));

}

uint16 readSPIWord(uint8 address)

{

    uint16 readword1 = 0xfffe;

    uint16 readword2 = 0xfffe;

    uint32 fifobuffer = 0;

    SPI_ClearRxFifo();

    while(SPI_GetNumInRxFifo() != 0);

    SPI_Write(address << 8);

    SPI_Write(0x0000);

    //Don't like this while here

    while(SPI_GetNumInRxFifo() != 2);

    fifobuffer = SPI_GetNumInRxFifo();

    if(fifobuffer){

      readword1 = SPI_Read();

      readword2 = SPI_Read();

    }

    printf("ADD: 0x%x BUFFER: %u - VALUES:0x%x 0x%x\r\n",address, fifobuffer, readword1, readword2);

    CyDelay(3); //Needed for printf

    return (uint16)readword1;

}

Logic Output:

Without the printf/UART the logic analyzer output is as follows:

pastedImage_10.png

This means the while-delay is not noticeable.

UART Output:

pastedImage_17.png   

Problem:

The while loop on line 42 will wait forever when something goes wrong with the SPI bus.

Thanks for your help, I can go on with this. Any feedback is appreciated.

View solution in original post

5 Replies
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

A couple of things, I'd like to check

(1) Is the MISO signal connected to the right pin?

(2) What is the pin configuration of MISO pin?

moto

0 Likes
Rova_1179706
Level 2
Level 2
First like received First like given

Hi Moto,pastedImage_0.png

My pins are correct I think. When I put random delays at places it returns 0x0000.

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Getting 0x0000 and 0xFFFF sounds good news.

This means MISO is receiving both values (0 and 1).

Next things I would try are

(1) Put some delay between address write and data read.

   (For this please refer to the datasheet of the sensor)

(2) Change ss0_m to GPIO (output) and keep it low during address write and data read.

(Same as (1), please check SPI protocol of the sensor)

moto

Hi Moto,

I have succeeded in getting (the correct) data with the following code. I needed to wait until the RX FIFO was cleared entirely. Then write the two words and wait until the FIFO contains them. It feels like a hack to me.

int main(void)

{

    uint8 addresses[9] = {0x1E, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x34, 0x36};

    __enable_irq();

    UART_Start();

    /* Also calls init, sets slave to 0 and calls enables */

    SPI_Start();

    UART_PutString("Hello");

    for(;;)

    {

        UART_PutString("\r\nStart Loop:\r\n");

        clearErrors();

        for( int i =0; i < 9; i++){

            readSPIWord(addresses);

        }

        CyDelay(1000);

    }

}

void clearErrors(){

    //Write bit + 1E address + 07 data

    SPI_Write(0x1E07 | (SPI_WRITE_BITMASK << 8));

    //Write bit + 1F address + 0x46 keycode

    SPI_Write(0x1F46 | (SPI_WRITE_BITMASK << 8));

}

uint16 readSPIWord(uint8 address)

{

    uint16 readword1 = 0xfffe;

    uint16 readword2 = 0xfffe;

    uint32 fifobuffer = 0;

    SPI_ClearRxFifo();

    while(SPI_GetNumInRxFifo() != 0);

    SPI_Write(address << 8);

    SPI_Write(0x0000);

    //Don't like this while here

    while(SPI_GetNumInRxFifo() != 2);

    fifobuffer = SPI_GetNumInRxFifo();

    if(fifobuffer){

      readword1 = SPI_Read();

      readword2 = SPI_Read();

    }

    printf("ADD: 0x%x BUFFER: %u - VALUES:0x%x 0x%x\r\n",address, fifobuffer, readword1, readword2);

    CyDelay(3); //Needed for printf

    return (uint16)readword1;

}

Logic Output:

Without the printf/UART the logic analyzer output is as follows:

pastedImage_10.png

This means the while-delay is not noticeable.

UART Output:

pastedImage_17.png   

Problem:

The while loop on line 42 will wait forever when something goes wrong with the SPI bus.

Thanks for your help, I can go on with this. Any feedback is appreciated.

MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Thank you for the good news!

BTW, for a mission-critical application usually, we need to apply a timeout to avoid deadlock.

something like

============

uint32_t timeout_limit = 20000 ; // you decide how long to wait till timeout

...

uint32_t timeout_count ;

timeout_count = 0 ;

while(SPI_GetNumInRxFifo() != 0) {

CyDelayUs(10) ; // please use appropriate delay function here

  timeout_count++ ;

  if (timeout_count >= timeout_limit) {

     // timeout!

     break ; // or return with error value

  }

}

...

=============

moto