AnsweredAssumed Answered

SPI transfer problem

Question asked by 14.curious_of_embedd on Jun 10, 2014
Latest reply on Jun 11, 2014 by 14.curious_of_embedd

Hi all;  

I'm trying to make two boards communicating with SPI. The Master is a board based on PIC µC and the slave is Discovery F3.
The protocol that i have to establish is as follows:

1) The master sends a command to the slave then it sends a data command of 4  bytes : this part is working fine.

2) The master sends a command to the slave. The slave decodes this address and then it sends back a data of 4 bytes.

The problem: data sent by the MISO line is shifted,that means it's not received by the master in the order expected.

I used a hardware chip select and it's activated with interruption.

Below is the code of both the Slave and Master.

The Slave SPI Handler
 
/**
* @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 = SPI_ReceiveData8(SPI1);
        Rx_Idx=0;
        Tx_Idx=0;
             
        switch(CmdReceived){
            case 0x01:
              receiveSPI=0x01;
              CmdStatus = 0x01;
              StartSend=0x00;
            break;
                     
            case 0x82 :
                if (StartSend)
                {
                 SendSPI=0x01;
                 CmdStatus = 0x01;
                 Spi_Case=0x01;
                 if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET) 
                                 // prepare to send the first byte
                  SPI_SendData8(SPI1,RegistreStaus[Tx_Idx++]);
                 if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != RESET)
                  SPI_ReceiveData8(SPI1);    // clear pending RX
                }
            break;
                     
            case 0x83:
                if (StartSend)
                {
                  SendSPI=0x01;
                  Spi_Case=0x02;
                  CmdStatus = 0x01;
                 if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET)   
                       // prepare to send the first byte
                   SPI_SendData8(SPI1,RegistreError[Tx_Idx++]);
                 if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != RESET) 
                   SPI_ReceiveData8(SPI1);      // clear pending RX            
                }
            break;
                     
            case 0x84:
                if (StartSend)
                {
                  SendSPI=0x01;
                  Spi_Case=0x03;
                  CmdStatus = 0x01;    
                  if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) != RESET) 
                                  // prepare to send the first byte
                     SPI_SendData8(SPI1,PostionRegister.NmIposition[Tx_Idx++]);
                  if (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) != RESET)
                     SPI_ReceiveData8(SPI1); // clear pending RX
                }                      
            break;
                     
            default:
                SendSPI=0x00;
                Spi_Case=0x00;
                CmdStatus = 0x00;
                receiveSPI=0x00;                        
            break;
        }// end of switch
                                 
    }// end of cmdStatus =0x00
        else
    {       // if cmdStatus
             
        if(receiveSPI)
        {
           RegistreCommand[Rx_Idx++] = SPI_ReceiveData8(SPI1);  // the array sent by the Master
                  
        } // end of receiveSPI
         
        /*------- Master <----> Salve */
        if (SendSPI)
        {   
            if( Spi_Case==0x03)
            {
                      
              while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // wait for Tx register to be empty
                 SPI_SendData8(SPI1,PostionRegister.NmIposition[Tx_Idx++]);
                  
              DummyData[Rx_Idx++]= SPI_ReceiveData8(SPI1); // the array sent by the Master
              STM_EVAL_LEDToggle(LED3);
                         
              if(Tx_Idx==0x04)
                CmdStatus=0x00;    
            }  // end of Spi_Case=0x03
             
            if( Spi_Case==0x02)
            {
               while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // wait for Tx register to be empty
                 SPI_SendData8(SPI1,RegistreError[Tx_Idx++]);
                  
               DummyData[Rx_Idx++]= SPI_ReceiveData8(SPI1); // the array sent by the Master                    
               STM_EVAL_LEDToggle(LED8);
                
               if(Tx_Idx==0x04)
                  CmdStatus=0x00;
            }// end of Spi_Case=0x02
             
            if( Spi_Case==0x01)
            {      
               while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); // wait for Tx register to be empty
                   SPI_SendData8(SPI1,RegistreStaus[Tx_Idx++]);
                    
               DummyData[Rx_Idx++]= SPI_ReceiveData8(SPI1);    // the array sent by the Master
               STM_EVAL_LEDToggle(LED9);
                
               if(Tx_Idx==0x04)
                 CmdStatus=0x00;
            } // end of Spi_Case=0x01  
        }// end os sendSPI
    }// end of cmdStatus =0x01
}// end of RXNE ineterruption
 
} // end of SPI handler

/* The Slave Chip select Routine */
/**
* @brief This interrupt handler detects rising and falling edges of the slave select line
*/
void EXTI15_10_IRQHandler(void)
{
    /* Handle the external interrupt for the SPI chip select (from PIC of the microcontroller) */
    if(EXTI_GetITStatus(EXTI_Line15)==SET)
    {
         
      /*Clear pending bit */
      EXTI_ClearITPendingBit(EXTI_Line15);
      if(GPIOA->IDR & GPIO_Pin_15)
      {
          STM_EVAL_LEDToggle(LED10);   
          if(receiveSPI==0x01)
          {
            receiveSPI=0x00;
            /* Waiting until RX FIFO is empty */
            while (SPI_GetReceptionFIFOStatus(SPI1) != SPI_ReceptionFIFOStatus_Empty)
            {}
    
            /* Wait busy flag */
            while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
            {}
 
            /* Waiting until TX FIFO is empty */
            while (SPI_GetTransmissionFIFOStatus(SPI1) != SPI_TransmissionFIFOStatus_Empty)
            {}
            /* Disable the SPI interrupt */
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_ERR, DISABLE);
            StartSend=0x01;
                      
                          
           }else if (SendSPI==0x01)
           {
                /* Waiting until RX FIFO is empty */
            while (SPI_GetReceptionFIFOStatus(SPI1) != SPI_ReceptionFIFOStatus_Empty)
            {}
    
            /* Wait busy flag */
            while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
            {}
            SendSPI=0x00;  
            Spi_Case=0x00;
                     
            /* Disable the SPI interrupt */
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, DISABLE);
            SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_ERR, DISABLE);
                             
            STM_EVAL_LEDToggle(LED7);
            }
                                  
      }else if (!(GPIOA->IDR & GPIO_Pin_15))
      {
        
         /* Enable the Rx buffer not empty interrupt */
        SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_RXNE, ENABLE);
   
        /* Enable the SPI Error interrupt */
        SPI_I2S_ITConfig(SPI1, SPI_I2S_IT_ERR, ENABLE);    
        STM_EVAL_LEDToggle(LED5);      
     
      }
}// end of if EXTILine

/* The Master part */
void vInterferoAxe1R(unsigned char ucRegister, unsigned long *pulValue)
 
{
 
    ucRegister = ucRegister + (READ<<7); //Command send to the slave
    SS_CPT1 = 1;
 
    __delay_us(1);
 
    cSPI1RW(ucRegister);
 
    __delay_us(1);
 
    *pulValue = cSPI1RW(0x00);          //Read MSB B3
 
    *pulValue = *pulValue<<8;
 
    *pulValue += cSPI1RW(0x00);         //Read  B2
 
    *pulValue = *pulValue<<8;
 
    *pulValue += cSPI1RW(0x00);         //Read  B1
 
    *pulValue = *pulValue<<8;
 
    *pulValue += cSPI1RW(0x00);         // Read LSB B0
 
    __delay_us(1);
 
    SS_CPT1 = 0;
 
}


Please any help would be appreciated, i spent a lot of time to resolve the problem but with no success.
If someone has an example to communicate  two board with SPI using interruption, please share it to have inspiration.

Best Regards, 

Outcomes