- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 = 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 = 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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 = 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Logic analyzer pictures look ok.
Your buffer for sprintf() is too small clobbering some ram data.
Set SPIM byte mode in advanced configuration.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"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 to zero again?
Season greetings
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
But you are aware that the gyro output must be zero when the MPU9250 is not rotating around any axis?
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Can you post your actual project.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Bob,
Happy New Year! I wish you had a nice Christmas!
I have attached the project below, along with the MPU9250 documents.
Currently I am still trying to readout the 6-axis accelerometer and gyroscope data, and still only 4-axis data can be readout. If possible, could you help me have a look and give some feedbacks?
Many thanks for your kind help.
Kind Regards
Wesley
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Not a good idea to hijack a foreign thread. Please create a new thread in the PSoC4 forum.
Bob
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Rob,
I wish all is well.
I finally got the program worked! Thanks a lot for your continuous kind help, I do appreciate that.
Many thanks again.
Kind Regards
Wesley
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
You are always welcome, Lesley.
Bob