I have written the following SPI initialization code for SPI1 on my STM32F030C8 micro-controller.

Here is the function which initializes SPI1:

void fnSPI_Init()
SPI_InitTypeDef SPI1_Config;
GPIO_InitTypeDef GPIO_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

/*****************MOSI, MISO SCLK GPIO Config********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_3;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_Init(GPIOB, &GPIO_InitStructure);


/******************Chip Select GPIO Config**********************/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/******************SPI1 Config for RC522************************/
SPI1_Config.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI1_Config.SPI_Mode = SPI_Mode_Master;
SPI1_Config.SPI_DataSize = SPI_DataSize_8b;
SPI1_Config.SPI_CPHA = SPI_CPHA_1Edge;
SPI1_Config.SPI_NSS = SPI_NSS_Hard;
SPI1_Config.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
SPI1_Config.SPI_FirstBit = SPI_FirstBit_MSB;
SPI1_Config.SPI_CRCPolynomial = 7;

SPI_Init(SPI1 , &SPI1_Config);

Here as per the data sheet I'm using PB3, PB4 and PB5 in the alternate function 0 mode.

Main function:

int main(void)
 /*!< At this stage the microcontroller clock setting is already configured, 
   this is done through SystemInit() function which is called from startup
   file (startup_stm32f0xx.s) before to branch to application main.
   To reconfigure the default setting of SystemInit() function, refer to
   system_stm32f0xx.c file

 while (1)
    Delay(100000);  // This is running proper as intended

The function body for fnSPI_Send_data() is as follows:

void fnSPI_Send_data(uint8_t addr)
GPIO_ResetBits(GPIOA,GPIO_Pin_15);   // Chip select low
printf("\n\r Send spi data");

SPI_SendData8(SPI1,addr);   // standard perip lib fn for stm32f0xx

printf("\n\r Data sent");
GPIO_SetBits(GPIOA,GPIO_Pin_15);    // Chip select high

Function body for the SPI_SendData8() function:

void SPI_SendData8(SPI_TypeDef* SPIx, uint8_t Data)
uint32_t spixbase = 0x00;

/* Check the parameters */

spixbase = (uint32_t)SPIx; 
spixbase += 0x0C;

*(__IO uint8_t *) spixbase = Data;  

Now the observed behavior is that the GPIO voltage levels are switching between high and low on the chip select pin, which is verified using the DSO. This means that the SPI_SendData8() function is getting executed. Also the printf() function verifies that the code is not getting stuck at any part.

But when I monitor the SCK or MOSI pins, the DSO shows there are no pulses. So my question is: Is my initialization of SPI correct? Do I need to change any other register values or anything?

According to this code, there should be data on the MOSI line.

Please help me on this one.


Changed fnSPI_Send_data() function to check the contents of the flags.

void fnSPI_Send_data(uint8_t addr)
printf("\n\r Check if FIFO empty");
while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

printf("\n\r FIFO empty");
SPI_SendData8(SPI1,addr);    // FIFO has space to accept data

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);

printf("\n\r Data sent");

Output observed is that the code is getting stuck at the first while() loop which checks if the FIFO is empty enough to accept the data. How can the FIFO have data on initialization?

  • \$\begingroup\$ I really don't know whether it's relevant, but the data register is 16 bit and I think with your code you're writing an eight bit value. Why aren't you using what's defined in the headers to access the registers? SPI1->DR if memory serves correct. Or maybe SPIx->DR if you're passing a pointer to the particular peripheral you're using into the function. \$\endgroup\$
    – DiBosco
    Jan 10, 2018 at 12:11
  • \$\begingroup\$ The SPI_SendData() function is doing the same thing right which you mentioned ie SPI->DR ? It places the data onto the Data register. And the above code in the standard perip function is also doing the same thing i guess. \$\endgroup\$ Jan 10, 2018 at 13:09
  • 1
    \$\begingroup\$ I realise it's, in theory, doing the same thing. It doesn't answer the question - or the observation about it being a sixteen bit register. \$\endgroup\$
    – DiBosco
    Jan 10, 2018 at 13:20

1 Answer 1


Common problem on STM32:

RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

There could well be more typos, that was probably only the first one.

  • \$\begingroup\$ Ohh yes. I made the changes and now the fnSPI_Send_data() is getting executed. Now when i check the CS pin there are high-low pulses after the intended delay but nothing on the MOSI line. How can i verify if i'm getting the required correct data on the MOSI line. I do not have debugging option available or else i would have checked via breakpoints. Please suggest some another way by which i can verify the sent data on the MOSI line. \$\endgroup\$ Jan 11, 2018 at 7:47
  • \$\begingroup\$ Why don't you just use SPIx->DR = Data in your SPI_SendData8() function? I currently don't see whether your code would actually work. The fact that this is a 16-bit register is irrelevant as long as you have the SPI unit configured for 8-bit mode. \$\endgroup\$
    – Turbo J
    Jan 11, 2018 at 20:02
  • \$\begingroup\$ Earlier, I tried SPIx->DR also. Still there are neither clock pulses on SCK nor data pulses on MOSI. Is there something wrong with my system clock config? \$\endgroup\$ Jan 12, 2018 at 4:35
  • \$\begingroup\$ filehosting.org/file/details/718697/system_stm32f0xx \$\endgroup\$ Jan 12, 2018 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.