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
S.Ma
Principal
Posted on October 30, 2017 at 04:59

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

0xFF is hardly a 32 bit address. You can try:

uint8_t FF = 0xFF;

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

For the rest, don't know. No problem on STM32F437 to run SPI at 20MHz without any delay between blocks of data.

What is your SYSCLK (which frequency the core runs)?

Posted on October 30, 2017 at 09:44

Yes it worked.

The first byte is now '0xFF'.

But I do not understand why the address of the variable has implications here ...

https://s1.postimg.org/7ozqc0gl6n/Capturar.jpg

The rest, despite the attempts, I can not make improvements.

Communication continues in 2-byte blocks.

Send 2 bytes - pause - send 2 bytes - pause -etc ...

I continue without having an answer to the CSN line.

T

he transfers are made in 10uS, but the 'HAL_SPI_TransmitReceive' function takes 80uS to run until the end.

https://s1.postimg.org/8t2zr80pbz/Capturar.jpg

Posted on October 30, 2017 at 09:49

If there is a DMA, you could use 2 channels, one for TX one for RX. For high speed serial buses such as SPI, DMA makes sense for optimum throughput.

If you use polling, the function returns not until the last byte was received. It is more efficient to use interrupt service routine for SPI (ISR).

There should be some examples of SPI in different modes (polling, interrupt, etc...) in STM32 Cube for the corresponding nucleo board.

Posted on October 30, 2017 at 09:51

If the core runs at 8MHz, it's 8 cycles per microsecond: use the HW assistance to the max (DMA), and/or use the low layer library (less portable, more optimized)

Posted on October 30, 2017 at 11:06

Thanks for the answers.

I would prefer to use polling because I always have to wait for the slave's response ...

I can try using LL libs to get better results, maybe ...

But in relation to my questions (so I can sleep well) these problems basically are caused by HAL libs?

Posted on October 30, 2017 at 11:07

Sorry, I forgot to refer. Yes the main clock of the MCU is 8MHz.

Posted on October 30, 2017 at 11:14

The HAL lib focuses on portability while Low Layer focuses on optimisation.

I don't know if your compiler is generating the code with max speed optimisation (usually they focus for size), and if the Flash wait states are properly configured.

When the core frequency is low and speed is the priority, use HW resources as much as possible AND low layer libraries.

Posted on October 31, 2017 at 00:13

I made a difficult approach to try to understand the differences.

But now this already looks like something I expected to see!

uint8_t stat, ff;

stat = STATUS;

ff = 0xFF;

CSN_PIN_LOW;

LL_SPI_TransmitData8(SPI1, stat);

while (LL_SPI_IsActiveFlag_BSY(SPI1))

;

LL_SPI_TransmitData8(SPI1, ff);

while (LL_SPI_IsActiveFlag_RXNE(SPI1) == 0)

;

RX_byte = LL_SPI_ReceiveData8(SPI1);

while (LL_SPI_IsActiveFlag_BSY(SPI1))

;

CSN_PIN_HIGH;

Look's mutch better...

https://s1.postimg.org/4i95nqy41b/Capturar.jpg

Posted on October 31, 2017 at 05:20

Well done. If sending many bytes, DMA assistance will help too. Sometime, if you really want to speed things up, you may try to have a NSS high/low positive pulse when starting the communication, so the last while is put back at the beginning in case the core does other things between 2 SPI transactions.