cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F303VC SPI Communication: SPI2 (Slave) SPI1 (Master)

AT.8
Associate II

Is it possible to send data from SPI2 to SPI1 ? SPI2 being the slave. In SPI, Master initiates the communication, correct ?

This is how i do it:

When the Slave SPI2 receives a byte from SPI1, i set a flag, and i check for this flag in main context.

If this flag is set, i send a dummy byte from Master and wait for the interrupt in SPI1 IRQ Handler (configured for RXNE interrupt).

if( Slave_Rx_Flag == 1 ){
 
     SPI_Master_Tx_Data(0x00); //Dummy byte
     SPI_Slave_Tx_Data(0x5D);
     Delay_us(50);
      Slave_Rx_Flag = 0;
}

My transmit function for slave looks so:

while (!LL_SPI_IsActiveFlag_TXE(SPI2))
     ; // wait while not empty
LL_SPI_TransmitData8(SPI2, byte); // NO EFFECT ??

void SPI1_IRQHandler( void ) {
 
	Master_Rx_Flag =1;
	uint8_t spi2_data ;
	spi2_data = SPI1->DR;
}

I am reading 0x00 when i expect 0x5D.

SPI2 (Slave) is initialized this way:

 /** MASTER      SLAVE
     * **********   **********
     * PA4 - NSS    PB12 - NSS
     * PA5 - SCK    PB13 - SCK
     * PA6 - MISO   PB14 - MISO
     * PA7 - MOSI   PB15 - MOSI
     */
	if (RESET == __HAL_RCC_GPIOB_IS_CLK_ENABLED())
	{
	     __HAL_RCC_GPIOB_CLK_ENABLE();
	}
 
	LL_GPIO_InitTypeDef gpioSPIInitStr;
 
	gpioSPIInitStr.Alternate = LL_GPIO_AF_5;
	gpioSPIInitStr.Pin       =  LL_GPIO_PIN_13  | LL_GPIO_PIN_15;
	gpioSPIInitStr.Mode      = LL_GPIO_MODE_ALTERNATE;
	gpioSPIInitStr.Speed     = LL_GPIO_SPEED_FREQ_HIGH;
	gpioSPIInitStr.Pull      = LL_GPIO_PULL_UP; 
	gpioSPIInitStr.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
 
	LL_GPIO_Init(GPIOB, &gpioSPIInitStr);
 
	gpioSPIInitStr.Alternate = LL_GPIO_AF_5;
	gpioSPIInitStr.Pin       =  LL_GPIO_PIN_14;
	gpioSPIInitStr.Mode      = LL_GPIO_MODE_INPUT;
	gpioSPIInitStr.Speed     = LL_GPIO_SPEED_FREQ_HIGH;
	gpioSPIInitStr.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
 
	LL_GPIO_Init(GPIOB, &gpioSPIInitStr);
 
	gpioSPIInitStr.Alternate = LL_GPIO_AF_5;
	gpioSPIInitStr.Pin       =  LL_GPIO_PIN_12; //NSS
	gpioSPIInitStr.Mode      = LL_GPIO_MODE_INPUT;
	gpioSPIInitStr.Pull      = LL_GPIO_PULL_NO;	                                           
	gpioSPIInitStr.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
 
	LL_GPIO_Init(GPIOB, &gpioSPIInitStr);
 
 
 __HAL_RCC_SPI2_CLK_ENABLE();
 
    LL_SPI_InitTypeDef SPI_SlaveInitStruct;
    SPI_SlaveInitStruct.BaudRate          = LL_SPI_BAUDRATEPRESCALER_DIV4;
    SPI_SlaveInitStruct.ClockPhase        = LL_SPI_PHASE_2EDGE;
    SPI_SlaveInitStruct.ClockPolarity     = LL_SPI_POLARITY_HIGH;
    SPI_SlaveInitStruct.CRCCalculation    = LL_SPI_CRCCALCULATION_DISABLE;
    SPI_SlaveInitStruct.DataWidth         = LL_SPI_DATAWIDTH_8BIT;
    SPI_SlaveInitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
    SPI_SlaveInitStruct.BitOrder          = LL_SPI_MSB_FIRST;
    SPI_SlaveInitStruct.Mode              = LL_SPI_MODE_SLAVE;
    SPI_SlaveInitStruct.NSS               = LL_SPI_NSS_HARD_OUTPUT; 
 
    LL_SPI_Init(SPI2, &SPI_SlaveInitStruct);
    LL_SPI_Enable(SPI2);
 
    LL_I2S_EnableIT_RXNE(SPI2);
    HAL_NVIC_SetPriority(SPI2_IRQn, 0 , 0 );
    HAL_NVIC_EnableIRQ(SPI2_IRQn);

4 REPLIES 4
KnarfB
Principal III

It is possible, but I don't know the API functions you are using for TX. The slave must be prepared to receive/transmit ahead, because it all happens at the same time. Can be done with polling:

for(;;)
  {
	  while( !(SPI2->SR & SPI_SR_TXE) ); // poll for TX empty
	  SPI2->DR = tx[ti++];
 
	  while( !(SPI3->SR & SPI_SR_RXNE) ); // poll for RX non-empty
	  rx[rxi++] = SPI3->DR;
  }

but this is kinda cheating because we assume exactly when to read. In a more realistic scenario you might use interrupt or DMA for the receiver.

hth

KnarfB

My Transmit function from Slave to Master looks so:

while (!LL_SPI_IsActiveFlag_TXE(SPI2))
     ; // wait while not empty
LL_SPI_TransmitData8(SPI2, byte); // NO EFFECT ??

My Receive interrupt handler looks so:

void SPI1_IRQHandler( void ) {
	Master_Rx_Flag =1;
	uint8_t spi2_data ;
	spi2_data = SPI1->DR;
}

TDK
Guru

> Is it possible to send data from SPI2 to SPI1 ? SPI2 being the slave. In SPI, Master initiates the communication, correct ?

Yes. Correct.

> SPI_Master_Tx_Data(0x00); //Dummy byte

> SPI_Slave_Tx_Data(0x5D);

The slave needs to be ready to send before the maser starts the clock. Your order is backwards.

If you feel a post has answered your question, please click "Accept as Solution".
S.Ma
Principal

Please try developping using 2 boards. Loop back on the same chip to have only one debug plateform will cause additional debug and recode effort when dissociating master slave to 2 devices. Overall time spent will be lesser.