简体   繁体   中英

How to fix Chip Select Timing for SPI on STM32F3?

I'm working on a project with the STM32F303RE that requires full-duplex SPI and I am using the HAL library provided by STM. While all lines are working in terms of SCK, MOSI and MISO, I've noticed that the chip select line goes low much longer than necessary and seems to be triggering off around 20kHz as opposed to the 2MHz SPI. This is a problem as the slave I am using triggers off the CS line and during multiple SPI calls the data becomes corrupted. How can I fix the timing?

I'm currently using a manual GPIO that simply sets low/high before and after the SPI call. From reading online, it seems the CS pin is a problem source for quite a few people as there is also the option to use a hardware NSS signal although people recommend against this as it doesn't work properly.

// Set SS pin low to activate
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);

// Read Temp
if(HAL_SPI_TransmitReceive(&hspi2, (uint8_t*)&master_buffer_tx[4], (uint8_t*)&master_buffer_rx[4], 1, 1000)!=HAL_OK){
      Error_Handler();
}

// Check finished
while(HAL_SPI_GetState(&hspi2) != HAL_SPI_STATE_READY){
}

// Set SS pin high to deactivate
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);

HAL_Delay(10);

I would expect CS to go low roughly half a cycle before SCK and similarly afterwards. These are the possible ideas I've had: Is the "Check finished" line causing the problem? Could it be my clock settings? Should the GPIO pin I use be the same as where NSS would be? Should I be using hardware NSS? Do I need to use interrupts and DMA?

Sorry if any of this seems naive as I'm still working on my understanding of the micro controller. Thanks!

CS and SCK timing

I think I can explain the delay between activation of CS and the SPI transfer: If you take a look inside HAL_SPI_TransmitReceive() you can see that it actually requires a lot of operations to set up and start the actual SPI transfer. Depending on your clock configuration this can easily take several microseconds (see also this question ).

I am a bit puzzled about the delay after the SPI transfer until CS is de-asserted. The HAL code should need much less operations to finish the transfer compared to the transfer preparation. The "Check finished" code should neither need many cycles, since it actually only checks a software flag (not even a hardware register). The call is not necessary though, because HAL_SPI_TransmitReceive() is a blocking function which only returns after the SPI transfer has finished.

Regarding your problem I wanted to recommend using the hardware NSS feature. But at second thought this asserts CS as soon as the SPI unit is enabled. The ST HAL does not seem to disable the SPI unit after each transfer - so this will not work as intended.

I think you need to analyze further what happens inside the HAL between the actual SPI transfer and the de-assertion of CS. This does not look like a normal behavior. It is not necessary to use interrupts or DMA to improve the CS behavior. These features take load from the CPU but require more complex code, which might not improve the CS delay.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM