SPI communication between two microcontrollers

OP (Company: xlue) #3730558
Hello everyone,

I am trying to make communication between an STM32F3 microcontroller and 
a custom board baser on PIC microcontroller using SPI protocol.

The STM32F3 acts as a Slave and the custom board as a Master. The clock 
is set to 10 MHz. I’m using NSS hardware, and getting EXTI once CS gets 
low in NSS pin. The CPOL and CPHA are compatible between the two boards.
I am using Interrupt base communication in the Slave side.
The application consists of:
1) The Master sends a command to the Slave, then a data of 4 bytes : 
This part works fine
2) The Master sends continuously different commands, The Slave process 
the command, then sends its proper data (4 bytes) depending on the 
received command. The Updating is about 20 KHz.

I have a problem with the second case, in fact, when the Master sends a 
command, let’s say 0x01, the Slave process this address and then sends 
back a frame let’s say 0x410547AF.

In the MISO line the frame is shifted, c.a.d (0x47, 0xAF, 0x41, 0x05, 
0x05) instead of (0xXX, 0x41,0x05, 0x47, 0xAF), because 0xXX should be 
0x00,the which  corresponds to the byte sent when the address is 
received.

I also used the debug mode(i'm using Keil µVision) to view the SR 
register and I can see that the FIFO transmission level is always at 2, 
that explains why the frame is shifted by 2 bytes. But I can’t find a 
solution to my problem, do you have an idea what would be the problem 
please?
If you want some code sample, I can post it.
I hope that my problem is clear.
Thanks in advance
Best regards
Guest #3730658
You probably have to pre-fill the slave output buffer with one byte 
(0x00) to have this byte being sent out on MISO out while transmitting 
the command byte.
Also you have to make sure the slave is able to process the command byte 
fast enough to load the 4-byte answer into the output buffer before the 
9th bit clock cycle occurs.
Maybe a short delay between end of command byte and clocking in MISO 
data is necessary here.
Guest #3733751
I reduced the SPI clock to 1.8MHz, I also add short delay between end of 
command byte and clocking in MISO data, the result is :

The initial Frame is 0x410547AF, the LSB byte sent in first. In the MISO 
line, the frame received is 0x41(when the address is received from the 
master),0xAF, 0xAF, 0x47, 0x05.

>You probably have to pre-fill the slave output buffer with one byte
(0x00) to have this byte being sent out on MISO out while transmitting
the command byte.

When I do that, the frame becomes worst:  0x47 (when the address is 
received from the master), 0x05, 0x41, 0x00, 0xAF.

Any explanation ?
(Company: Nikhef) #3734536
Its not shifted. It sends it 2 bytes at a time, using the wrong 
endieness and the wrong byte order. Its probably a matter of configuring 
the right control registers (maybe the DATAINV field). You may also want 
to byte reverse your response first using the REV intrinsic.
Guest #3734710
jeorges wrote:
>>You probably have to pre-fill the slave output buffer with one byte
> (0x00) to have this byte being sent out on MISO out while transmitting
> the command byte.
>
> When I do that, the frame becomes worst:  0x47 (when the address is
> received from the master), 0x05, 0x41, 0x00, 0xAF.

If you receive 0x47 while address is sent my the master, the MISO out 
buffer definitely wasn't be pre-filled with 0x00.
You have literally to send out a 0x00 from you slave before the master 
sends a command to make sure the 0x00 will be clocked out when the 
command is transferred.

In general it seems that you SPI interface works 16-bit wide.
So you have two options: either you manage to configure it to 8-bit 
transfer width, or you extend you command to 16 bits too.

Another thing to consider: is there is any possibility to clear the MISO 
buffer after having received the command?
This could make sure that there are no "leftovers" in the MISO buffer.
I would also recommend to perform this buffer clearing each time after a 
transfer was done.
Also don't forget to pre-fill the MISO buffer with 0x00 resp. 0x0000 
every time a transfer ended to make sure there is data in the MISO 
buffer to "answer" the next command cycle.
Guest #3734979
Little-endian is the default memory format for ARM processors. Even if i 
the bytes are reversed doesn't resolve the problem, in this case i have 
0xAF(when the address is received from the master) 0x41, 0x41,0x05, 
0x47.
i don't understand why 0x41 is repeated two times, I am tearing my hair 
out on this one and hoping someone can help.

Best Regards
Guest #3735143
jeorges wrote:
> in this case i have
> 0xAF(when the address is received from the master)

With "address" you probably mean "command byte"..?

Remember how SPI works on hardware side.
There are 2 shift registers, one for MOSI data, one for MISO data.
Both are clocked synchronously by the SPI bitclock.

So if you see a 0xAF on MISO while receiving the command, that 0xAF must 
be a leftover in the MISO shift register from the previous transfer.

I guess the point where the slave is sending out the 4-byte dataword is 
8 bit behind of the point you like it to happen:
1
This is what you observe:
2

3
MOSI: 0x01 0x00 0x00 0x00 0x00
4
MISO: 0xAF 0x41 0x41 0x05 0x47
5
           ^__ expected point to send out 0x410547AF
6

7
This is what I think is happening:
8

9
MOSI: 0x01 0x00 0x00 0x00 0x00
10
MISO: 0xAF 0x41 0x41 0x05 0x47
11
                ^__ actual point where 0x410547AF is sent out
12

13
So for transferring the 0xAF there is no SPI clockcycles, and 0xAF remains in the MISO shift register.
14

15
Try this:
16

17
      16-bit    2x 16-bit 
18
      command   data
19
      v-------v v-----------------v
20
MOSI: 0x01 0x00 0x00 0x00 0x00 0x00
21
MISO: 0x?? 0x?? 0x41 0x05 0x47 0xAF
22
                ^__ actual point where 0x410547AF is sent out
23

24
0x?? will probably be some garbage, but doesn't matter
Guest #3735614
Thank you Easylife  for your help, your explanations are very clear, 
i'll try your suggestions and let you know.

Best regards
Guest #3743033
Hi Easylife,

As you suggested : >I pre-fill the MISO buffer with 0x00 every time a 
transfer ended to make sure there is data in the MISO buffer to "answer" 
the next command cycle.
Now it works for a speed of 2MHz and I can have :
MISO: 0x00 0x41 0x05 0x47 0xAF

I tried to increase the speed to reach 10MHz but as I mentioned, some 
bytes still in Tx buffer, the slave is not quick enough to serve the 
Master.

May be it's a question of code optimization... Furthermore, I am using 
Interrupt to detect the rising and falling edge of the chip select. This 
can't help a lot.

Best Regards
Guest #3743751
The master should always check whether the Tx buffer is empty before 
sending (writing) new bytes. There should be some flags which signalize 
this.

On the slave side, there should also be a flag which signalizes the Rx 
buffer full status and generates an IRQ. This IRQ should be used to read 
the data as quick as possible. Speed rather than code optimization is 
important here.

The whole system cannot perform faster than the slave can read.
Guest #3744327
@ stst
>On the slave side, there should also be a flag which signalizes the Rx buffer 
>full status and generates an IRQ. This IRQ should be used to read
>the data as quick as possible:
Yes this my problem when i use the 10MHz, in the slave side, the IRQ 
can't read and then write to Tx as quick as possible even if i use Tx 
and Rx flag.
But how can i evaluate the IRQ time ?
Guest #5296728
On every prebuilt SPI slave I had to work with, or was interested in,
it works differently:

The answer from the slave is transferred while the NEXT command is sent 
by the master. Then a higher transfer speed is possible but you have to 
handle this in the master's software.

Martin C.

Reply

A question of your own? This thread is over 12 years old. Ask it in a thread of its own – more people read along there, and it gets answered more often and sooner.

Start a new thread

A fix, an addition or feedback on this thread? Then reply here.

Formatting
  • [c]C-Code[/c]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]
  • [[Title]] – link to an article
  • Link to another post: right-click its post ID (#8078628), copy the address, paste it into the text

More about formatting

Post long source code as an attachment, not in the text.

Already registered? Log in

Not shown to anyone. We send you a link; your post appears once you confirm it there.

By submitting you create a free account and accept the terms of use.