EmbDev.net

Forum: µC & Digital Electronics SPI communication between two microcontrollers


von jeorges F. (Company: xlue) (khal1985)


Rate this post
useful
not useful
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

von lkmiller (Guest)


Rate this post
useful
not useful
jeorges FrenchRivera wrote:
> In the MISO line the frame is shifted, c.a.d (0x47, 0xAF, 0x41, 0x05,
> 0x05)
Looks like some kind of little- and big-endian hassle somewhere in the 
unknown program...

von Easylife (Guest)


Rate this post
useful
not useful
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.

von jeorges (Guest)


Rate this post
useful
not useful
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 ?

von Vincent V. (Company: Nikhef) (vvanbeveren)


Rate this post
useful
not useful
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.

von Easylife (Guest)


Rate this post
useful
not useful
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.

von jeorges (Guest)


Rate this post
useful
not useful
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

von Easylife (Guest)


Rate this post
useful
not useful
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

von jeorges (Guest)


Rate this post
useful
not useful
Thank you Easylife  for your help, your explanations are very clear, 
i'll try your suggestions and let you know.

Best regards

von jeorges (Guest)


Rate this post
useful
not useful
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

von stst (Guest)


Rate this post
useful
not useful
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.

von jeorges (Guest)


Rate this post
useful
not useful
@ 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 ?

von Anjali Verma (Guest)


Rate this post
useful
not useful
Please post your code...I'm stuck with the same

von Martin C. (Guest)


Rate this post
useful
not useful
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.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.