This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

SPI communication between two microcontrollers

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 frequency sends by the Master 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 the first byte corresponds to the byte when the address is received.
I also used the debug mode 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

Parents
  • I don't know why the FIFO is always at 2 bytes, but processors that support FIFO normally requires you to configure some baudrate or timeout information so the processor can figure out when enough time has passed without new information and then generate a timeout interrupt to have the code pick up the last incoming bytes from the FIFO.

    Another thing - SPI requires the same number of bytes in both directions. So when you send a command in one direction, you have to send the same number of dummy bytes (maybe 0xff or 0x00) in the other direction. As soon as the slave knows the command it may issue a response - and the master must then send dummy bytes to keeep the SPI transfer running and give the slave the clock ticks required to send back the response.

    Of course, it's possible to stagger multiple transfers instead of sending dummy bytes. But that requires a more complex protocol and is mainly meaningful if there are similar amounts of data in both directions.

Reply
  • I don't know why the FIFO is always at 2 bytes, but processors that support FIFO normally requires you to configure some baudrate or timeout information so the processor can figure out when enough time has passed without new information and then generate a timeout interrupt to have the code pick up the last incoming bytes from the FIFO.

    Another thing - SPI requires the same number of bytes in both directions. So when you send a command in one direction, you have to send the same number of dummy bytes (maybe 0xff or 0x00) in the other direction. As soon as the slave knows the command it may issue a response - and the master must then send dummy bytes to keeep the SPI transfer running and give the slave the clock ticks required to send back the response.

    Of course, it's possible to stagger multiple transfers instead of sending dummy bytes. But that requires a more complex protocol and is mainly meaningful if there are similar amounts of data in both directions.

Children
  • Thank you Per for your response.

    Processors that support FIFO normally requires you to configure some baudrate or timeout information: You mean that the speed i use is too much ? how can i add this timeout to my SPI handler?
    Below is my code for the SPI handler of the Slave :

    /**
    * @brief Hnadle the SPI interrupt
    */
    void SPI1_IRQHandler(void)
    {
    
      /* SPI in Slave Receiver mode--------------------------------------- */
      if (SPI_I2S_GetITStatus(SPI1, SPI_I2S_IT_RXNE) == SET)
      {
                    /*------- Master --> Slave */
        if (CmdStatus == 0x00)
        {
            CmdReceived = SPI1_RXDR8;
                    Rx_Idx=0;
                    Tx_Idx=0;
    
                    switch(CmdReceived){
                        case 0x01:
                              receiveSPI=0x01;
                              CmdStatus = 0x01;
                              StartSend=0x00;
                              Cpt_Spi=0;
                            break;
    
                            case 0x81 :
    
                                    SendSPI=0x01;
                                    CmdStatus = 0x01;
                                    Spi_Case=0x01;
                                    if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)
                      SPI1_RXDR8=SPI_Tx1[Tx_Idx++];   // prepare the first byte to be send when the clock is received
                            break;
    
                            case 0x84:
    
                                    SendSPI=0x01;
                    Spi_Case=0x02;
                    CmdStatus = 0x01;
                                    if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)
                       SPI1_RXDR8=SPI_Tx2[Tx_Idx++];  //  // prepare the first byte to be send when the clock is received
                              }
                            break;
    
                            default:
                               SendSPI=0x00;
                   Spi_Case=0x00;
                   CmdStatus = 0x00;
                   receiveSPI=0x00;
                            break;
    
                          }// end of switch
            }// end of cmdStatus =0x00
            else
        {
    
              if(receiveSPI)  // in this case the slave receives data from the master
              {
             SPI_Rx[Rx_Idx++] = SPI1_RXDR8;  // the array sent by the Master in the receive mode
    
              } // end of receiveSPI
                    /*------- Master <----> Salve */
    
              if (SendSPI)         // in this case the slave receives dummy data from the master and sends back its proper data
          {
                    if( Spi_Case==0x01){
    
                      DummyData[Rx_Idx++]=SPI1_RXDR8; // the array sent by the Master
    
                      if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)
                   SPI1_RXDR8=SPI_Tx1[Tx_Idx++];
                    }
                    if( Spi_Case==0x02){
    
                       DummyData[Rx_Idx++]= SPI1_RXDR8; // the array sent by the Master
    
               if(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)
                   SPI1_RXDR8=SPI_Tx2[Tx_Idx++];
                    }
    
              }// end os sendSPI
    
            }// end of cmdStatus =0x01
    
    }// end of RXNE ineterruption