1 2 Previous Next 16 Replies Latest reply on Sep 19, 2017 2:28 PM by user_343349849

    SPI rate change in code

    user_343349849

      I have an application that needs to set up a device at low SPI rate (< 3MHz) and then switch to SPI rate up to 20MHz for normal speed operation.

       

      Could someone please explain or give example how to change the SPI rate for these in code.

       

      Thank you

        • 1. Re: SPI rate change in code
          user_1377889

          Use an external clock for your SPI component. Then you can change the clock frequency using different approaches. On PSoC5 you can use a PWM as input to SPI. Generally you can modify the clock divider using the clock APIs described in "System Reference Guide" from Creator help.

           

          Bob

          1 of 1 people found this helpful
          • 2. Re: SPI rate change in code
            ntan

            THE SPIM component can have a Clock input to specify the bit rate.

            GS003207.png

            There is a radio button on the Advanced tab.  The clock input appears when the "External Clock" is selected as the "Clock Selection"

            GS003208.png

            It was shown in the "Configure" tab saying the bit rate is 1/2 of the Input Clock Frequency.

            GS003209.png

            The output frequency of the Clock component (Clock_SPIM) is set to MASTER_CLK/1 where the MASTER_CLK=40MHz in this case.

            GS003210.png

            The output frequency can be set by an API functions Clock_SPIM_SetDividerValue()  For example, the divider value is set to 7, the Clock output becomes 5.71MHz and the bit rate is set to 2.86MHz

            The important thing is to set a highest clock frequency to the Clock component when the project is built.  If lower frequency is set, a slow logic may be synthesized not supporting higher frequency.

             

            Please note that I did not confirm the behavior of my project on the PSoC 5LP because I don't have enough measurement equipment right now.

             

            Regards,

            Noriaki

            1 of 1 people found this helpful
            • 3. Re: SPI rate change in code
              user_343349849

              Thanks for the responses,

               

              I can get it running up to 12MHz with a bit of slope on the output signal and some ringing on my scope.

               

              I have not played around much with system master clock. The IMO is set to 3MHz and PLL as well as master clock set to 24MHz.

               

              Can I simply enter any desired PLL and Master clock value that is multiple of 3 up to 5LP max. frequency?

               

              I read somewhere the max.SPI rate is 18MHz, would this mean I am best to set the Master clock to say 32MHz and run SPI at 16MHz?

               

              The waveform is deteriorating at the higher speeds. The High Speed Mode is selected. Is there something I can do with the drive pins to ensure better waveform at higher rates?

              • 4. Re: SPI rate change in code
                ntan

                You can specify the PLL and MASTER clock by the Configure System Clocks dialogue which is invoked by the "Edit Clock..." button at the top of the "Clocks" tab of the CYpress Design Wide Resource (CYDWR) file in the workspace explorer.

                GS003211.png

                You can specify the clock frequency by this dialogue.  PSoC Creator calculate a suitable frequency realized by the PSoC 5LP and show as the "Nominal" frequency.

                GS003212.png

                The datasheet of the SPIM component can be opened from the context menu of the component instance.  There is an AC characteristics table in the datasheet as follows.

                GS003213.png

                The maximum bit rate is depend on the operation mode.  In 8-bit High-speed mode case, the maximum frequency is 18MHz.  Sorry, this SPIM does not support 20MHz bit rate.

                 

                Regards,

                Noriaki

                • 5. Re: SPI rate change in code
                  user_343349849

                  OK, 18MHz max.

                   

                  I note on the scope there is delay between each byte being sent out the SPI port.

                   

                  My code writes the packet out in a loop like this:

                   

                  SPI_WriteTxData(ch);

                    while(!(SPI_ReadTxStatus() & SPI_STS_SPI_DONE));

                   

                  Is there a  way to prevent gaps between the bytes?

                  • 6. Re: SPI rate change in code
                    ntan

                    The status flag SPI_DONE means the end of the current transfer.  So, there should be some gap between data bytes.

                    GS003215.png

                    Please try to use the TX_FIFO_NOT_FULL flag.  You can push multiple data unless the FIFO full and the SPIM component automatically sent data bytes as fast as possible.

                     

                    Regards,

                    Noriaki

                    • 7. Re: SPI rate change in code
                      user_343349849

                      Thanks Noriaki,

                       

                      So I could just wait until buffer not full like this...

                       

                      uint8 writeSPI(uint8 ch)

                      {

                        while(!(SPI_ReadTxStatus() & SPI_STS_TX_FIFO_NOT_FULL)){};

                        SPI_WriteTxData(ch);

                        return SPI_ReadRxData();

                      }

                       

                      What about the BYTE_COMPLETE Flag? would that also work.

                      • 8. Re: SPI rate change in code
                        ntan

                        Please refer the component datasheet.  There is a description about the Status Register.

                        GS003220.png

                        The datasheet is contained in the PSoC Creator or can be downloaded from following page.

                        Serial Peripheral Interface (SPI) Master | Cypress Semiconductor

                         

                        Regards,

                        Noriaki

                        • 9. Re: SPI rate change in code
                          user_343349849

                          I am still having trouble getting rid of the gaps between bytes. Below is my code and image of the data output.

                           

                          The Master clock is set to 64MHz and the SPI clock to 32MHz.

                           

                          char buf[11] = {0xa1,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x99};

                           

                           

                          void writeSPI(char c)

                          {

                             while(!(SPI_ReadTxStatus() & SPI_STS_TX_FIFO_NOT_FULL)){};

                             SPI_WriteTxData(c); 

                            

                          }

                           

                           

                          int main(void)

                          {

                              SPI_Start();

                              CyGlobalIntEnable; /* Enable global interrupts. */

                              SPI_Clock_SetDividerValue(3);  //3 = 12MHz

                              for(;;)

                              {

                                 CS_Write(0);

                                 for(int i = 0 ; i < 11; i++)

                                 {

                                    writeSPI(buf[i]);

                                    while(!(SPI_ReadTxStatus() & SPI_STS_SPI_DONE));

                                 }

                                 CS_Write(1);

                                 CyDelay(1);

                                

                              }

                          }

                           

                          spi captured.JPG

                          • 10. Re: SPI rate change in code
                            ntan

                            You don't need to check the SPI_DONE flag in the LOOP.  Move the line after the for loop.  Data are pushed to FIFO as possible.

                             

                            In addition, it is not required to wait for the FIFO_NOT_FULL flag before calling the WriteTxData() method because the method blocks until the FIFO not full.  There is following sentence in the datasheet as follows.

                             

                            Side Effects:

                            Data may be placed in the memory buffer and will not be transmitted until all other previous data has been transmitted. This function blocks until there is space in the output memory buffer.

                             

                            GS003221.png

                            Regards,

                            Noriaki

                            • 11. Re: SPI rate change in code
                              user_343349849

                              Does the PutArray function send bytes as fast as possible and block until sent? I don't mind clocking while data being sent but need to send data as fast as possible.

                               

                              Also, if I used PutArray, does this automatically accumulate received bytes into the rx register and after the put I read the rx buffer?

                               

                              I set up the 64MHz Master clock and tried divide by 2 as SPI clock source - this should set rate to 16MHz but I get invalid data output.

                              Seems I can only get around 12MHz reliably (By setting divider to 3 and use 21.3 MHz as SPI source clock.

                               

                              Thanks

                              • 12. Re: SPI rate change in code
                                user_343349849

                                When I use PutArray at around 12MHz I get reliable data but wondering why after every 3 bits the Clock duration is doubled (changes to 80ns instead of 40ns).

                                 

                                SPI waveform.JPG

                                • 13. Re: SPI rate change in code
                                  ntan

                                  It seems that the Clock component connected to the SPIM's clock input has non-50% duty clock waveform.  Please check the Clock signal at the clock input of SPIM.

                                   

                                  Regards,

                                  Noriaki

                                  • 14. Re: SPI rate change in code
                                    user_343349849

                                    Do you mean to connect a pin to the Clock source and look on scope?

                                     

                                    Below is image of the component on screen and values.

                                     

                                    The closest I can get to what I want is using PutArray but I only get 1 byte back when reading rx data?

                                    When I look on my analyzer I see the correct data coming back from the Slave device. But not receiving it in my code.

                                     

                                    uint8 spiTxData[8] = {0xA1,0x11,0x22,0x33,0x44,0x55,0x66,0x77};  //write to reg 0x00

                                    uint8 spiReadData[8] = {0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00};

                                     

                                    int main(void)

                                    {

                                        CyGlobalIntEnable; /* Enable global interrupts. */

                                        SPI_Start();

                                        SPI_CLOCK_SetDivider(8); //2.66 MHz

                                        for(;;)

                                        {

                                          SPI_PutArray(spiTxData,8);  //Write an array of data to the Device (0xa1 = write command for location 0x21)

                                          while(!(SPI_ReadTxStatus() & SPI_STS_SPI_DONE));

                                          SPI_PutArray(spiReadData,8); //Read from location 0x21

                                          while(!(SPI_ReadTxStatus() & SPI_STS_SPI_DONE));

                                          numRxBytes = SPI_GetRxBufferSize();  //ONLY get 1 bytes here

                                          for(uint8 i = 0; i < 8;i++){

                                            spiRxData[i] = SPI_ReadRxData();

                                          }

                                          CyDelay(1);

                                        

                                        }

                                    }

                                     

                                    clock onfig.JPG

                                    1 2 Previous Next