cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F407xx SPI Slave usage - Polling method.

pradeepsysargus
Associate II
Posted on July 09, 2016 at 08:03

I am working on establishing SPI communication between STM32F407ZET6 and NRF52832 chipsets.

Currently, I am configuring STM32F407ZET6 is the slave as I need to send the data continuously from NRF52832.

I found code in github for configuring STM32F407xx as master, not as slave.

https://github.com/g4lvanix/STM32F4-examples/blob/master/SPI/main.c

The main function in this example continuously sends SPI data. In the same way, if you could show me how I can configure SPI slave and also continuously check for arrived data, it will be great. I am going to use polling method.

I know there is example code in spi standard peripheral drivers from ST that use interrupt method, but I am looking for polling method, that continuously check for arrived data.

Rgds,

5 REPLIES 5
Posted on July 09, 2016 at 15:54

uint8_t GetSPIByte(void)
{ 
/*!< Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
/*!< Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(SPI1);
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pradeepsysargus
Associate II
Posted on July 10, 2016 at 01:30

Hello Clive1,

Thanks for the reply.

Please correct me if I am wrong. You did not include the slave configuration.

Please look into the configuration and also corresponding main function that I am writing for SPI slave:

// this function initializes the SPI1 peripheral

void init_SPI1(void){

GPIO_InitTypeDef GPIO_InitStruct;

SPI_InitTypeDef SPI_InitStruct;

// enable clock for used IO pins

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* configure pins used by SPI1

* PA5 = SCK

* PA6 = MISO

* PA7 = MOSI

*/

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOA, &GPIO_InitStruct);

// connect SPI1 pins to SPI alternate function

GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

// enable clock for used IO pins

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

/* Configure the chip select pin

in this case we will use PE7 */

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOE, &GPIO_InitStruct);

GPIOE->BSRRL |= GPIO_Pin_7; // set PE7 high

// enable peripheral clock

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

/* configure SPI1 in Mode 0

* CPOL = 0 --> clock is low when idle

* CPHA = 0 --> data is sampled at the first edge

*/

SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines

SPI_InitStruct.SPI_Mode = SPI_Mode_Slave; // slave mode.

SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide

SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low; // clock is low when idle

SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge; // data sampled at first edge

SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high

SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

SPI_Init(SPI1, &SPI_InitStruct);

SPI_Cmd(SPI1, ENABLE); // enable SPI1

}

int main(void){

uint8_t received_val = 0;

init_SPI1();

while(1){

   received_val = GetSPIByte(); // receive data

}

}

In the above code, PA5,PA6,PA7 are configured as sck, miso, mosi. PE7 as chip select.

These pins are same as used in the master code that was there in the link I sent.

I changed SPI_InitStruct.SPI_Mode = SPI_Mode_Master; to  SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;  and commented out the line:

SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;

I am thinking slave need not give the frequency to the master, which is why I commented out the line that give frequency. In the main function while loop, I am continuously checking for received data, should I give some delay here?

Thanks,

From: clive1

Posted: Saturday, July 09, 2016 3:54 PM

Subject: STM32F407xx SPI Slave usage - Polling method.

uint8_t GetSPIByte(void)

{

   /*!< Wait to receive a byte */

  while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

 

  /*!< Return the byte read from the SPI bus */

  return SPI_I2S_ReceiveData(SPI1);

}

From: ch.pradeep

Posted: Saturday, July 09, 2016 8:03 AM

Subject: STM32F407xx SPI Slave usage - Polling method.

I am working on establishing SPI communication between STM32F407ZET6 and NRF52832 chipsets.

Currently, I am configuring STM32F407ZET6 is the slave as I need to send the data continuously from NRF52832.

I found code in github for configuring STM32F407xx as master, not as slave.

https://github.com/g4lvanix/STM32F4-examples/blob/master/SPI/main.c

The main function in this example continuously sends SPI data. In the same way, if you could show me how I can configure SPI slave and also continuously check for arrived data, it will be great. I am going to use polling method.

I know there is example code in spi standard peripheral drivers from ST that use interrupt method, but I am looking for polling method, that continuously check for arrived data.

Rgds,

Posted on July 10, 2016 at 15:33

The initialization for a Polling Slave should be nearly identical to that of an IRQ Slave.

I don't have any hardware set up to evaluate this, but there should be several slave examples within the SPL for EVAL or DISCO boards.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
pradeepsysargus
Associate II
Posted on August 08, 2016 at 14:56

Hello Clive1,

I am using the below SPI Slave configuration, Please look into it:

void init_SPI1(void){

GPIO_InitTypeDef GPIO_InitStruct;

SPI_InitTypeDef SPI_InitStruct;

// enable clock for used IO pins

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

/* configure pins used by SPI1

* PA5 = SCK

* PA6 = MISO

* PA7 = MOSI

*/

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_6 | GPIO_Pin_5;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;

GPIO_Init(GPIOA, &GPIO_InitStruct);

// connect SPI1 pins to SPI alternate function

GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);

GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);

// enable clock for used IO pins

//RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); COMMENT THIS LINE AS PORTE IS NOT NEEDED NOW

/* Configure the chip select pin

  in this case we will use PA4 */

GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4;

GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN;

GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;

GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;

GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP;

GPIO_Init(GPIOA, &GPIO_InitStruct);

// enable peripheral clock

RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); // 84 Mhz

/* configure SPI1 in Mode 0 

* CPOL = 0 --> clock is low when idle

* CPHA = 0 --> data is sampled at the first edge

*/

SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines

SPI_InitStruct.SPI_Mode = SPI_Mode_Slave;     // transmit in slave mode, NSS pin has to be always high

SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 8 bits wide

SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle

SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge

SPI_InitStruct.SPI_NSS = SPI_NSS_Soft | SPI_NSSInternalSoft_Set; // set the NSS management to internal and pull internal NSS high

SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

SPI_Init(SPI1, &SPI_InitStruct); 

SPI_Cmd(SPI1, ENABLE); // enable SPI1

}

uint8_t GetSPI1Byte(void)

{

   /*!< Wait to receive a byte */ 

 // while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);

  /*!< Return the byte read from the SPI bus */

  return SPI_I2S_ReceiveData(SPI1);

}

My main function is:

void main()

{

        init_SPI1();

uint8_t rcd_data = 0;

 

         while (1) 

{

if(!(GPIOA->IDR & 0x0010))

{

  rcd_data = GetSPI1Byte();

  printf(''Data Received: %x\r\n'',rcd_data);   

}

 

} // end of while loop

 }

As I said, I am trying to establish SPI communication between NRF52832 and STM32F407ZET6. 

I am able to see the clock and Chip select signals on the Oscilloscope from NRF chip. I checked that data is also sent from NRF chip. On slave side, the chipselect is going low, but a NULL(0x00) data is received all the time.

I configured Chip select as Input on Slave side. I am reading the Chipselect signal going low, and printing that value (NULL).

Can you please check my configuration and my main() code as well.?

Thanks,

Pradeep Ch.

Posted on August 08, 2016 at 18:21

Can you please check my configuration and my main() code as well?

I can only offer you a quick static analysis. Code looks to be reasonable. Make sure the data from the Master (it's Output) goes the the PA7 (the Slave's Input).

The cross-check would be to pull PA7 high and low and confirm 0xFF and 0x00 are observed.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..