Help with SPI Master Read

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

cross mob
joli_601446
Level 5
Level 5
10 likes given 10 sign-ins 5 sign-ins

Hello, I am interfacing with a 16-port GPIO expander using SPI on the PSOC5. I am using a Master SPI and am able to program the GPIO expander using the Write function of the SPI module. But know I would like to read some of the registers in the GPIO expander. I need some help with the programming for the SPI Master read. Is anyone has some examples on doing a read please share them with me.

Thank you very much,

Joe

0 Likes
1 Solution

The datasheet says the ReadRxData returns the next Byte per Word of received data.

No, the datasheet tells the value returned is a byte or a word depending on the bit setting of the SPI component which is 16 in your case.

So I sent 1 16bit word, so I will need to read the buffer twice.

You sent 2 (two) 16 bit values, this is the reason why you need to read the buffer twice

I'm not sure what to expect on the first read, it returns 0. What should I expect?

As I pointed out in my first post: When the very first byte/word is sent, the interface does not "know" yet what to answer, so a dummy byte/word is returned. This is zero (0) in your case and has no meaning.

Bob

View solution in original post

0 Likes
15 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

SPI Master does not have an explicit read method, Instead for every bit (byte) the SPI interface sends, one bit (byte) is returned immediately from the slave. When the very first byte is sent, the interface does not "know" yet what to answer, so a dummy byte is returned which should be skipped.

SPI has no read command, so you must send dummy bytes to retrieve the information wanted.

A pitfall is the select line, which is automatically taken low when a byte is sent. When the buffer is empty it is taken high again. This can lead to interface errors when the byte sequence is not provided fast enough resulting in ss-line glitches.

Bob

0 Likes
joli_601446
Level 5
Level 5
10 likes given 10 sign-ins 5 sign-ins

Bob,

Hello, thank you very much for responding to my message. Here is some example code for your comments:

uint8 packet size = 1;

uint8 OutputControlReg = 0x02;               // Register I want to read from

SPIM_WriteTxData(OutputControlReg);

while(packet size != SPIM_GetRxBufferSize())

{

}

SPIM_ClearTxBuffer();   /* Clear temp buffer data */

data = ReadRxdata();  /* Read the RxBuffer data */

Does this make sense to you?

Respectfully,

Joe

0 Likes

Despite the packet size is 1, you should put the write into the while loop.Remember that you need to write one byte for every byte you want to read plus the initial dummy byte. No need to clear the TxBuffer at end. Only needed when there was an error condition. In your case it might hinder the complete transmission to the slave.I would suggest you to left click on SPI Master in the component catalog and select "Find code example"

Bob

0 Likes
joli_601446
Level 5
Level 5
10 likes given 10 sign-ins 5 sign-ins

Bob,

HI, I'm making some progress. I do see data coming out of the GPIO expander but my code keeps optimizing out the code.

Optimized_outb.jpg

When I debug the code I do see the value of buffer_size to be 2. Does that mean there is 2 8bit words in the Receive FIFO? The problem is when I execute the command rd_data = SPIM_LEDDRIVER_ReadRxData() the rd_data is optimized out. Why does that happen?

Thank you very much,

Joe

0 Likes
lock attach
Attachments are accessible only for community members.

Bob,

HI, I've attached my project. I also right clicked on the SPI module as you suggested but I didn't see any examples that might be SPI related.

Thank you very much for helping me.

Joe

0 Likes

Joe,

To fix the optimize issue without doing a global non-optimize in the compile:

change: uint8 rd_data = 0;  to volatile uint8 rd_data = 0;

This will force the compiler to not optimize rd_data.  This will allow the debugger to better show you the results.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

The other "right" click for code examples.

SPI component is set to 16 bit wide. This is for reading and writing. You should change your variables accordingly from uint8 to uint16 or change SPI to 8 bits wide.

You wrote 2 bytes to SPI, so you will receive two bytes.

Bob

0 Likes

Bob,

HI, here is the SPI interface for the XRA1403 Expander:

Expandor_SPI_Interface.jpg

Being a newbie with SPI I'm guessing this is a 16-bit interface and that is why I have the SPI module set to 16. Is this not right?

Joe

0 Likes

That is right, bur

t you defined

uint8 rd_data = 0;

which is not 16 bit wide

Bob

0 Likes

Okay, thanks for looking at the SPI image and agreeing with my assumption that it is a 16-bit SPI interface. I will make the change you suggested and give it a try. Thank you very much.

0 Likes
lock attach
Attachments are accessible only for community members.

Hello, I got things working but need some help in a question or two:

Here is a shot of the read data:

logic.jpg

The register is a 5 in it and that is what is reading back to the  SPI Master.

In order to get things to work, I needed to read the RxBuffer twice. Here is my code:

The first read returns 0 and the second read returns 5 which is what I wrote to the GPIOCONF1 register:

Debug.jpg

The datasheet says the ReadRxData returns the next Byte per Word of received data. So I sent 1 16bit word, so I will need to read the buffer twice. I'm not sure what to expect on the first read, it returns 0. What should I expect?

On the second read I get back 5 which is what I wrote to the 8-bit register.

I had to use the volatile data type to keep the rd_data variable from being optimized out which probably makes sense because rd_data was never used anywhere else in the code.

I've included my project.

Thank you very much,

Joe

0 Likes

The datasheet says the ReadRxData returns the next Byte per Word of received data.

No, the datasheet tells the value returned is a byte or a word depending on the bit setting of the SPI component which is 16 in your case.

So I sent 1 16bit word, so I will need to read the buffer twice.

You sent 2 (two) 16 bit values, this is the reason why you need to read the buffer twice

I'm not sure what to expect on the first read, it returns 0. What should I expect?

As I pointed out in my first post: When the very first byte/word is sent, the interface does not "know" yet what to answer, so a dummy byte/word is returned. This is zero (0) in your case and has no meaning.

Bob

0 Likes

Bob,

Hello, I did a quick test where I did an SPIM_LEDDRIVER_WriteTxData and had the logic analyzer set up to capture a lot of time. I saw the transaction but nothing on the MISO line. My next command was data = SPIM_LEDDRIVER_GetRxBufferSize and it returned a 1. Just like you said. Very interesting. Here I only did a write to the SPI slave device but the SPI Master interface on the PSOC does not "know" a read is not occurring, so I'm assuming that it latches in whatever it sees on the MOSI line, which in this case is a low so it would latch in 0's.

Is this the proper understanding?

Thank you very much,

Joe

0 Likes

As you can see from the configuration dialog and the datasheet there is an Rx (and Tx) buffer (you did set it to 10 words) and a 4 items deep FIFO from which the buffer is filled.

Your observations regarding the MISO read are quite correct.

Bob

0 Likes

Thanks Bob for all your work and patience in helping me. Thank you for not kicking me to the street when I don't understand things. I really appreciate it.

Have a great day!

0 Likes