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
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...
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.
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 ?
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.
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.
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
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 |
Thank you Easylife for your help, your explanations are very clear, i'll try your suggestions and let you know. Best regards
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
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.
@ 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 ?
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
Log in with Google account
No account? Register here.