7 Replies Latest reply on Sep 19, 2018 10:34 PM by brvi

    Understanding SPI Comms

    user_80002741

      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

        • 1. Re: Understanding SPI Comms
          brvi

          Hi Joe,

           

          What is the master device you're using?

           

          Regards,

          Bragadeesh

          • 2. Re: Understanding SPI Comms
            brvi

            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

             

             

             

            • 3. Re: Understanding SPI Comms
              user_80002741

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

              • 4. Re: Understanding SPI Comms
                user_80002741

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

                • 5. Re: Understanding SPI Comms
                  user_80002741

                  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

                  • 6. Re: Understanding SPI Comms
                    brvi

                    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

                    • 7. Re: Understanding SPI Comms
                      brvi

                      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