cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030 SPI with long time between bytes and wrong output

David Martins
Senior
Posted on October 29, 2017 at 22:42

Hello, I'm having some problems with the STM32F030 SPI.

I've read enough about this and I know there are some problems .... but I can not find justification for this.

Why does the SPI send 2 bytes and then stop for 17uS (this time can vary with the main clock, which in my case is 8MHz) and then send the next 2 bytes?

What is the reason for this long break?

Why does SPI take so long to start sending after I change the status of CSN pin?

I leave here an image of the signals and part of the code that I'm using ...

/* SPI1 init function */

void MX_SPI1_Init(void)

{

hspi1.Instance = SPI1;

hspi1.Init.Mode = SPI_MODE_MASTER;

hspi1.Init.Direction = SPI_DIRECTION_2LINES;

hspi1.Init.DataSize = SPI_DATASIZE_8BIT;

hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi1.Init.NSS = SPI_NSS_SOFT;

hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;

hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi1.Init.TIMode = SPI_TIMODE_DISABLE;

hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

hspi1.Init.CRCPolynomial = 7;

hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

if (HAL_SPI_Init(&hspi1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)

{

GPIO_InitTypeDef GPIO_InitStruct;

if(spiHandle->Instance==SPI1)

{

/* USER CODE BEGIN SPI1_MspInit 0 */

/* USER CODE END SPI1_MspInit 0 */

/* SPI1 clock enable */

__HAL_RCC_SPI1_CLK_ENABLE();

/**SPI1 GPIO Configuration

PA5 ------> SPI1_SCK

PA6 ------> SPI1_MISO

PA7 ------> SPI1_MOSI

*/

GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_PULLUP;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;

GPIO_InitStruct.Alternate = GPIO_AF0_SPI1;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* USER CODE BEGIN SPI1_MspInit 1 */

/* USER CODE END SPI1_MspInit 1 */

}

}

void HW_SPI_send(uint8_t cmd, uint8_t* rx_buff, uint8_t lenght)

{

uint8_t tx_buff[lenght + 1];

memset(tx_buff, 0xFF, lenght + 1);

tx_buff[0] = cmd;

HAL_SPI_TransmitReceive(&hspi1, tx_buff, rx_buff, lenght + 1, 5000);

}

int main(void)

{

/* USER CODE BEGIN 1 */

uint8_t RX_buff[5];

/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */

HAL_Init();

/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */

SystemClock_Config();

/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_SPI1_Init();

/* USER CODE BEGIN 2 */

SET_CSN_PIN;

HAL_Delay(1000);

HAL_SPI_MspInit (&hspi1);

//clean output buffer

/************************************************************************ SEE NEXT QUESTION ***/

HAL_SPI_TransmitReceive(&hspi1, (uint8_t*) 0xFF, (uint8_t*) RX_buff, 1, 5000);

HAL_Delay(100);

/***************************************************************************** PROBLEM ******/

CLEAR_CSN_PIN;

HW_SPI_send(0x0A, RX_buff, 5);

SET_CSN_PIN;

(....)

}

https://s1.postimg.org/1cxyypuswv/Capturar.jpg

https://s1.postimg.org/3n7s8cptbj/Capturar.jpg

***********************************************************************************

PS: I have one more question.

Why does the first byte, after configuring the SPI, send junk?

Look at this example.

I send '0xFF', but the MCU sends 0xD1...

https://s1.postimg.org/131xvq3s8v/Capturar.jpg

stm32f030 spi stm32f0 stm32f030-spi

15 REPLIES 15
Posted on October 31, 2017 at 10:07

Can you give me more help?

Basically I've tried all the flags, but I can not read the last byte ...

I can write a reg (to the slave) and I can do it correctly.

In the logic analyzer everything is correct!

The byte I am always reading is the STATUS byte, which is received simultaneously with the register send.

In the images it corresponds to '0x0E.

What am I doing wrong?

Posted on October 31, 2017 at 10:44

There are several generations of SPI IPs, one without FIFO, a newer one with and which the way to write to the DR has meaning (8 or 16 bit WRITE).

Similarly, for reading back in the 2nd gen SPI, the RXNE flag depends on how full is the incoming FIFO (there is a bit to define when RXNE is set). If the HAL is working correctly and is slow, look at how the SPI HW registers access sequence. As SPI is full duplex, the TXE clears as soon as the DR is written, then say 8 SPI clocks are transmitted and then the DR will contain the received data. Beware: If you are using a debugger with breakpoint, DO NOT WATCH THE SPI DR REGISTER. Why? Because when you stop the program, the debugger will READ the DR and shows it. In this case, it's a race condition with the STM32 SW :)

Posted on October 31, 2017 at 12:46

I opened the 'HAL_SPI_TransmitReceive' function to try to see how they are managing the process.

I'm going to do something similar, but with LL libs.

I'll try it out sooner and write something here again.

Thank you.

Hugues Libotte
Associate III
Posted on November 09, 2017 at 16:42

Hello.

I have similar problem/question.

Did you reach the solution ?

Thanks for your feedback.

Posted on November 09, 2017 at 17:31

Hello.

Yes, I started using LL libs. I used Cube_MX to do all the configuration and then created the following function to send/receive data via SPI.

void SPI_TransmitReceive_LL(uint8_t* TX_buffer, uint8_t* RX_buffer, uint8_t lenght)

{

uint8_t TX_cnt, RX_cnt;

TX_cnt = 0;

RX_cnt = 0;

while ((TX_cnt < lenght) || (RX_cnt < lenght))

{

if ((LL_SPI_IsActiveFlag_TXE(SPI1)) && (TX_cnt < lenght))

{

LL_SPI_TransmitData8(SPI1, TX_buffer[TX_cnt]);

TX_cnt++;

}

if ((LL_SPI_IsActiveFlag_RXNE(SPI1)) && (RX_cnt < lenght))

{

RX_buffer[RX_cnt] = LL_SPI_ReceiveData8(SPI1);

RX_cnt++;

}

}

}

Example:

clean_reset_buffers(tx_buff, rx_buff, 4);

tx_buff[0] = NRF_WRITE_REG + RX_ADDR_P0;

tx_buff[1] = RX_ADD1;

tx_buff[2] = RX_ADD2;

tx_buff[3] = RX_ADD3;

CSN_PIN_LOW;

SPI_TransmitReceive_LL(tx_buff, rx_buff, 4);

CSN_PIN_HIGH;

PS: this forum sucks to do code block sharing!

They could add something so the code does not miss the formatting.
Posted on November 09, 2017 at 22:56

Hello

Thanks. I will try this ! I keep you informed.

Bye

Hugues