cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 6

Rova_1179706
New Contributor II

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
Rova_1179706
New Contributor II

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
Esteemed Contributor

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
New Contributor II

Hi Moto,pastedImage_0.png

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

0 Likes
MotooTanaka
Esteemed Contributor

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

Rova_1179706
New Contributor II

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

MotooTanaka
Esteemed Contributor

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

Top labels