1 2 Previous Next 20 Replies Latest reply on Jan 16, 2017 6:45 AM by user_1377889

    PSoc 4-MPU9250 SPI Writing and Reading function

    bks1987

      Hi guys,

         

      Currently I am using PSoC 4200M as master to readout the motion sensor data (MPU9250, as slaver) via SCB SPI. I have basically finished the program, but it does not work. 

         

      As I am very new for PSoC, I just like to confirm with your the correctness of the SPI writing and reading function. 

         

      I have defined dedicated functions for registers Writing and Reading, as shown below.
      /* Write Register*/
      void MPU9250_WriteReg( uint8_t WriteAddr, uint8_t WriteData )
      {
        SPIM_SpiUartWriteTxData(WriteAddr);
        SPIM_SpiUartWriteTxData(WriteData);
      }

         

      /* Read Register*/
      uint8_t MPU9250_ReadReg( uint8_t ReadAddr )
      {
        uint8_t ReadData = 0;
          
        SPIM_SpiUartWriteTxData(0x80 | ReadAddr);
        ReadData = SPIM_SpiUartReadRxData();
        return ReadData;
      }

         

      /* Read a series of  Registers*/
      void MPU9250_ReadRegs( uint8_t ReadAddr, uint8_t *ReadBuf, uint8_t Bytes )
      {
        uint8_t i =0;
        
        SPIM_SpiUartWriteTxData(0x80 | ReadAddr);  
        for(i = 0; i < Bytes; i++)
        ReadBuf[i] = SPIM_SpiUartReadRxData()
      }

         

      But some websites said the Reading function need to add dummy bytes, and said the typical flow for the SPI master should be:
      1) Send command byte(s)
      2) Read and discard dummy byte(s) returned
      Then to read back any response from the slave:
      3) Send dummy byte(s)
      4) Read response bytes(s) returned

         

      Then, I updated the Reading functions correspondingly, as shown below:
      /* Read Register updated*/
      uint8_t MPU9250_ReadReg( uint8_t ReadAddr )
      {
        uint8_t ReadData = 0;
        uint8_t dummy = 0;
          
        SPIM_SpiUartWriteTxData(0x80 | ReadAddr);
        dummy = SPIM_SpiUartReadRxData();
        SPIM_SpiUartWriteTxData(0xFF); // Dummy
        ReadData = SPIM_SpiUartReadRxData();
        return ReadData;
      }

         

      /* Read a series of  Registers updated*/
      void MPU9250_ReadRegs( uint8_t ReadAddr, uint8_t *ReadBuf, uint8_t Bytes )
      {
        uint8_t i =0;
        uint8_t dummy=0;
          
        for(i = 0; i < Bytes; i++) {
        SPIM_SpiUartWriteTxData(0x80 | ReadAddr + i);
        dummy = SPIM_SpiUartReadRxData();
        SPIM_SpiUartWriteTxData(0xFF); // Dummy
        ReadBuf[i] = SPIM_SpiUartReadRxData();}  
      }

         

      If possible, could you help me check the correctness of both Writing and Reading function? Could you tell me which way is correct? Or even both ways are incorrect?

         

      Many thanks for your help.

         

      Kind Regards

         

      Wesley

        • 1. Re: PSoc 4-MPU9250 SPI Writing and Reading function
          user_1377889

          Welcome in the forum, Wesley.

             

          The second way is the correct way.

             

          But

             

          Before reading with SPIM_SpiUartReadRxData() you need to wait for the byte ready, the API will not wait.

             

          When reading "a series" of bytes from successive locations you should move the SPIM_SpiUartWriteTxData(0x80 | ReadAddr + i); out of the loop. Most devices have got a data pointer which gets incremented.

             

           

             

          Bob

          • 2. Re: PSoc 4-MPU9250 SPI Writing and Reading function
            bks1987

            Hi Bob, 

               

            Thanks a lot for your warm welcome :). 

               

            And many thanks for your reply, it is really helpful. If so, my writing function is right?

               

            Sorry, would you mind tell me a bit of more details about how to implement the 'wait' function/'ready' flag for reading? 

               

            Many thanks again.

               

            Kind Regards

               

            Wesley

            • 3. Re: PSoc 4-MPU9250 SPI Writing and Reading function
              user_1377889

              Use SCB_SpiUartGetRxBufferSize() to check for the number of bytes received. When this is equal to the number of bytes sent you may continue with reading the results / dummies.

                 

               

                 

              Bob

              • 4. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                bks1987

                Hi Bob, thanks a lot for your reply. 

                   

                Sorry for bothering you again.

                   

                I have updated the code correspondingly below, but it still does not work... 

                   

                /* Read Register*/

                   

                uint8_t MPU9250_ReadReg( uint8_t ReadAddr )
                {
                  uint8_t ReadData = 0;
                  uint8_t dummy = 0;
                    
                  SPIM_SpiUartWriteTxData(0x80 | ReadAddr); // Read Command and Address
                  SPIM_SpiUartWriteTxData(0xFF); // Write Dummy 

                   

                  while (SPIM_SpiUartGetRxBufferSize() < 2) {} // Wait

                   

                  dummy = SPIM_SpiUartReadRxData(); // Read Dummy
                  ReadData = SPIM_SpiUartReadRxData(); // Read Data
                  return ReadData;
                }

                   

                /* Read a seizes of Registers*/

                   

                void MPU9250_ReadRegs( uint8_t ReadAddr, uint8_t *ReadBuf, uint8_t Bytes )
                {
                  uint8_t i =0;
                  uint8_t dummy=0;
                  
                   for(i = 0; i < Bytes; i++){
                    SPIM_SpiUartClearRxBuffer();
                    SPIM_SpiUartWriteTxData(0x80 | (ReadAddr+i)); // Read Command and Address
                    SPIM_SpiUartWriteTxData(0xFF); // Write Dummy 
                    
                    while (SPIM_SpiUartGetRxBufferSize() < 2) {} // Wait
                    
                    dummy = SPIM_SpiUartReadRxData(); // Read Dummy
                    ReadBuf[i] = SPIM_SpiUartReadRxData(); // Read Data
                    
                    SPIM_SpiUartClearRxBuffer();}  // Reset buffer size to 0
                }

                   

                I should misunderstand some points (particularly for the reading seizes of registers), could you give some feedbacks/advices?

                   

                Best Wishes

                   

                Wesley

                • 5. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                  user_1377889

                  Wouldn't bee too bad when you tell us what doesn't work. Did you use the debugger to see what runs?

                     

                  Post your complete project, so that we all can have a look at all of your settings. To do so, use
                  Creator->File->Create Workspace Bundle (minimal)
                  and attach the resulting file.

                     

                   

                     

                  Bob

                  • 6. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                    bks1987

                    Hi Bob, 

                       

                     

                       

                    Thanks a lor for your reply. 

                       

                     

                       

                    Sorry, I didn't explain clearly. I used a logic analyzer to see the SPI signals. The SPI write is ok, but the SPI reading data is not correct, and the data is not changed with the motion sensor. I suppose maybe my MPU9250_ReadReg and MPU9250_ReadRegs are still wrong, then the data cna not be read properly? 

                       

                     

                       

                    I attached my project file here. The SPI function is defined in the mpu6500.c file.

                       

                     

                       

                    I also attached a screenshot of my logic analyzer. the channel 3 (MOSI) '187' is the read command & address, and the '255' is the write dummy, the channel 0 (MISO) '0' is the dummy reading and '219' is the data reading. '188' and subsequent registers are in the same flow. Here the readregs function is used. 

                       

                     

                       

                    Could you feel free to have a look? Many thanks for your help.

                       

                     

                       

                    Kind Regards

                       

                     

                       

                    Wesley 

                    • 7. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                      user_1377889

                      Logic analyzer pictures look ok.

                         

                      Your buffer for sprintf() is too small clobbering some ram data.

                         

                      Set SPIM byte mode in advanced configuration.

                         

                       

                         

                      Bob

                      • 8. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                        bks1987

                        Hi Bob,

                           

                        Many thanks for your help, it is partially working! I got 4-axis data from the motion sensor via SPI. 

                           

                        I think because limited by the size of the buffer, I can not readout the full 9-axis/6-axis data.

                           

                        Do you know is there any other way to further increase the SPI buffer size?

                           

                        Many thanks for your help.

                           

                        I wish you Merry Christmas and Happy New Year ahead!

                           

                        Best wishes

                           

                        Wesley

                        • 9. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                          user_1377889

                          "I think because limited by the size of the buffer, I can not readout the full 9-axis/6-axis data." Your SPI buffer was set to 32 bytes size.

                             

                          Your sprintf() buffer was too small.

                             

                          And did you reset the index i in ReadBuf[i] to zero again?

                             

                           

                             

                          Season greetings

                             

                          Bob

                          • 10. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                            bks1987

                            Hi Bob,

                               

                            Many thanks for your reply. So if my understanding is correct, the only way is to increase the buffer size of SPIM? I found in the SCB datasheet(I attached below, SCB_P4_v3_20.pdf, in Page 98-99),  for PSoC 4200M the maximum RX/TX buffer size can only be 16 bytes. Then it seems no matter how larger the buffer size is set, the actual buffer size will be 16 bytes? If so, as you know, is there any other way to increase the SPIM buffer size?

                               

                            ps, I used the MPU6500_ReadReg function (single register reading) to readout the data one register by one register. 

                               

                            Many thanks for your help.

                               

                            Kind Regards

                               

                            Wesley 

                            • 11. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                              user_1377889

                              You are referring to the minimum buffer size which is 16 bytes in your case. Actually in last project post buffer size was set to 32.

                                 

                              Your selected buffer size will limit how many bytes you may send (and in parallel receive) before reading them off. So with your current algorithm the actual value is quite sufficient.

                                 

                              A problem can occur when the transmission is fast and the fifo gets empty: The ss-line will get high, indicating the slave a transaction end. To avoid this you may try:

                                 
                                    
                              • Remove the ss-line from the SPIM component.
                              •     
                              • Add an output pin without hardware connection, strong drive initially high.
                              •     
                              • Manually (programmatically ;-) pull the new ss pin low before accessing the SPIM and release to high when done.
                              •    
                                 

                               

                                 

                              Bob

                              • 12. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                                bks1987

                                Hi Bob,

                                   

                                Many thanks.

                                   

                                Sorry, I was confused by the datasheet :). If so, the SPI buffer size should not a problem? 

                                   

                                I use logic analyzer analyze the signals, seems the ss signal is ok? the screenshot is attached. The problem is from register '196' in MOSI, there is no any data in MISO, then I can only get part of the data, e.g. I only get 4-axis data of the 6-axis motion sensor.

                                   

                                Do you have thought about that?

                                   

                                Thanks a lot.

                                   

                                Wesley

                                • 13. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                                  user_1377889

                                  But you are aware that the gyro output must be zero when the MPU9250 is not rotating around any axis?

                                     

                                   

                                     

                                  Bob

                                  • 14. Re: PSoc 4-MPU9250 SPI Writing and Reading function
                                    bks1987

                                    But if I change the reading sequence, there is always some data cannot be readout, either gyro or accelerometer, and only up to 4-axis data can be read. very strange.... The MPU can well communicate with I2C program, but the project requires SPI, which drive me crazy...

                                       

                                    Best 

                                       

                                    Wesley

                                    1 2 Previous Next