Understanding SPI Comms

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 have not used the SPI Master function before and have a few questions. I am interface to the XRA1403 SPI 16-BIT IO Expander to toggle 16 LEDs. The SPI interface is described in the data sheet:

XRA1403_SPI.png

The SPI command Byte format is

Bit 7 (1=Read Operation and 0=Write Operation),

Bits6:1 is the Command Byte

Bit 0 is Reserved

My question is when I call the SPI_Write function will it clear bit 7 of the Command byte? Or must I control it in the Command Byte word.

#define OCR1_WR 0x02  // Write to Output Control Register, but 7 is cleared

#define OCR1_RD  0x82 // Read from Output Control Register, but 7 is set

So a write would look like:

SPIM_WriteTxData(OCR1_WR | 1);   // sets bit 1 in the OCR1 register

Is my read command correct?

But I am not sure how to do a read, can anyone help me with a read?

Thanks,

Joe

0 Likes
1 Solution

Hi Joe,

You can refer to the code example SCB_SpiCommMaster example project, where you need to only use the SPI Master (SCB) portion. PSoC has dedicated communication blocks called the SCB. If you have exhausted all your dedicated SCB blocks, then you can choose the UDB based SPI.

You need to have the following functions to read a data from XRA1403:

1. First you need to send the master command from the master SPI (SCB) device, that looks something like

#define OCR1_RD 0x82 .   /* 1000 0010b -> MSB set to 1 indicating read operation. You need to read the register 0x02 */

SPIM_SpiUartWriteTXdata(OCR1_RD);  /*Send the complete command as per given in packet format */

while(packet size != SPIM_SpiUartGetRxBufferSize())

{

}

/*Here packet size is no of packets to send. If packet size = no. of packets received, it means transmission is complete. In your application packet size is 1.*/

SCB_SpiUartClearRxBuffer();  /*Clear the data received from slave as it is junk for now. */

2. After successfully sending the command, your slave would have processed this command and will send the value of the register requested by the master. Now the master has to read this data from the slave. Remember, the master also has to send data through MOSI while receiving data from the slave (MISO). So you need to pass some temporary value to the buffer, which will be discarded by the slave.

uint8 temp = 0xFF;

SPIM_SpiUartWriteTxData(temp);

while(packet size != SPIM_SpiUartGetRxBufferSize())

{

}

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

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

Hope this helps!

Regards,

Bragadeesh

Regards,
Bragadeesh

View solution in original post

0 Likes
7 Replies
BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi Joe,

What is the master device you're using?

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

Hi Joe,

You can refer to the code example SCB_SpiCommMaster example project, where you need to only use the SPI Master (SCB) portion. PSoC has dedicated communication blocks called the SCB. If you have exhausted all your dedicated SCB blocks, then you can choose the UDB based SPI.

You need to have the following functions to read a data from XRA1403:

1. First you need to send the master command from the master SPI (SCB) device, that looks something like

#define OCR1_RD 0x82 .   /* 1000 0010b -> MSB set to 1 indicating read operation. You need to read the register 0x02 */

SPIM_SpiUartWriteTXdata(OCR1_RD);  /*Send the complete command as per given in packet format */

while(packet size != SPIM_SpiUartGetRxBufferSize())

{

}

/*Here packet size is no of packets to send. If packet size = no. of packets received, it means transmission is complete. In your application packet size is 1.*/

SCB_SpiUartClearRxBuffer();  /*Clear the data received from slave as it is junk for now. */

2. After successfully sending the command, your slave would have processed this command and will send the value of the register requested by the master. Now the master has to read this data from the slave. Remember, the master also has to send data through MOSI while receiving data from the slave (MISO). So you need to pass some temporary value to the buffer, which will be discarded by the slave.

uint8 temp = 0xFF;

SPIM_SpiUartWriteTxData(temp);

while(packet size != SPIM_SpiUartGetRxBufferSize())

{

}

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

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

Hope this helps!

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

Do you have a direct link to the SCB_SpiCommMaster example project? Thanks

0 Likes

Bragadeesh,

Hello, thank for the code it really helped me get going. Here is what I have so far:

#define OUTPUTCTRL1 0x02     // read/write, output control of p0-p7

#define OUTPUTCTRL1_RD 0x82     // read/write, output control of p0-p7

#define OUTPUTCTRL2 0x03    // read/write, output control of p8-p15

int packet_size = 1;

uint8 mydata = 0;

uint8 temp = 0xff;

CyGlobalIntEnable; /* Enable global interrupts. */

        

SPIM_LEDDRIVER_Start();

SPIM_LEDDRIVER_WriteTxData((GPIOCONF1 << 8)| 0x00); // set port0-7 to outputs

SPIM_LEDDRIVER_WriteTxData((GPIOCONF2 << 8)| 0x00); // set port8-15 to outputs

   

SPIM_LEDDRIVER_WriteTxData(OUTPUTCTRL1_RD << 8 | 0x0);

while(packet_size != SPIM_LEDDRIVER_GetRxBufferSize())

{

}

   

SPIM_LEDDRIVER_ClearRxBuffer(); // clear the data receive from the slave

   

SPIM_LEDDRIVER_WriteTxData(temp); // set port8-15 to outputs

while(packet_size != SPIM_LEDDRIVER_GetRxBufferSize())

{

}

   

SPIM_LEDDRIVER_ClearTxBuffer();// clear temp buffer data

mydata = SPIM_LEDDRIVER_ReadRxData();

----

Is it proper to shift up the address 8 bit and OR it with the data, for example SPIM_LEDDRIVER_WriteTxData((GPIOCONF1 << 8)| 0x00)? The shift direction is MSB first and would put the data words first and followed by the address word.

Also, how deep should my RX and TX buffers be?

SPI_Advanced.jpg

Thanks

0 Likes

Hi Joe,

You can't have a 8 bit buffer and try to send a 16 bit data. In the Configure SPI dialog box, in Configure tab, increase the data bits to 16. If you do that you will be able to send 16 bit data like you have tried in your code.

But if you want only 8 bit buffer, you need to send the data twice. For eg:

SPIM_LEDDRIVER_WriteTxData((GPIOCONF1);

SPIM_LEDDRIVER_WriteTxData(0x00);

Or instead of sending it two times, you can use SPIM_PutArray( uint8 data[], uint8 ByteCount) /* 8 bit buffer */

For eg:

uint8 data[2] = {0x82,0x00};

SPIM_PutArray(data,2);

Since you are reading and clearing the buffer often, the minimum of 4 bytes is enough for your application.

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

You can find the code example in PsoC Creator 4.2

Open PSoC Creator. File -> Code Example-> SCB_SpiCommMaster

Also, PSoC 5LP doesn't have SCB block. Only PSoC 4/6 have them.

Regards,

Bragadeesh

Regards,
Bragadeesh
0 Likes

I am using the SPI Master Full Duplex mode macro v2.50 in my PSOC5 Design.

0 Likes