Electrical – Setting up SPI on STM32F030C8

spistm32f0

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);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB, 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);

GPIO_PinAFConfig(GPIOB,GPIO_PinSource3,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource4,GPIO_AF_0);
GPIO_PinAFConfig(GPIOB,GPIO_PinSource5,GPIO_AF_0);

/******************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);
GPIO_SetBits(GPIOA,GPIO_Pin_15);
/******************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_CPOL = SPI_CPOL_Low;
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);
SPI_SSOutputCmd(SPI1, ENABLE);
SPI_Cmd(SPI1 , ENABLE);
}

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
 */ 


 fnSPI_Init();
 while (1)
 {
    fnSPI_Send_data(0x2A);
    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 */
assert_param(IS_SPI_ALL_PERIPH(SPIx));

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.


Update:

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

void fnSPI_Send_data(uint8_t addr)
{
GPIO_ResetBits(GPIOA,GPIO_Pin_15);
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");
GPIO_SetBits(GPIOA,GPIO_Pin_15);
}

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?

Best Answer

Common problem on STM32:

RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
-------^----------------------^-

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