2024-07-08 07:14 AM
1. CubeMX only allows HAL or LL for SPI and other peripherals. STM32C031C6 itself provides the good SPI clock rate.
SPI LL API function only allows two-byte R/W.. The slave STPM34 Meter IC requires 4-Byte SPI R/W. So we have to choose HAL SPI API calls, such as HAL_SPI_TransmitReceive().
However HAL introduces a big delay (15 us or more) between two consecutive HAL SPI-API calls. We need 6 SPI-API calls within 128us for our application, This big delay inserted by HAL makes it impossible. .
2. The only solution is to write the register low level SPI R/W functions. Is it possible to write it under the current CubeMx IDE compiler for STM32C031C6? Could you provide us the solutions?
Thanks,
Rong
Solved! Go to Solution.
2024-07-19 02:13 AM
Hello @RongShengWang
I updated my code. Could you check with this please.
void SPI_Transmit_Receive(const uint8_t *data_tx, uint8_t *data_rx, uint8_t size)
{
uint8_t rx_size= size;
uint8_t tx_size = size;
/* Set the Rx Fifo threshold */
if (size > 1U)
{
/* Set fiforxthreshold according the reception data length: 16bit */
CLEAR_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
}
else
{
/* Set fiforxthreshold according the reception data length: 8bit */
SET_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
}
/* Enable SPI */
SPI1->CR1 |= SPI_CR1_SPE;
while (size > 0)
{
/* Wait until TXE (Transmit buffer empty) flag is set */
while (!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_TXE));
/* Transmit data */
if (tx_size > 1U)
{
SPI1->DR = *((uint16_t *)data_tx);
data_tx += sizeof(uint16_t);
tx_size -= 2U;
}
else
{
*(__IO uint8_t *)&SPI1->DR = (*data_tx);
data_tx ++;
tx_size --;
}
/* Wait until RXNE (Receive buffer not empty) flag is set */
while (!__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_RXNE));
if (rx_size > 1U)
{
*((uint16_t *)data_rx) = (uint16_t)SPI1->DR;
data_rx += sizeof(uint16_t);
rx_size -= 2U;
if (rx_size <= 1U)
{
/* Set RX Fifo threshold before to switch on 8 bit data size */
SET_BIT(SPI1->CR2, SPI_RXFIFO_THRESHOLD);
}
}
else
{
(*(uint8_t *)data_rx) = *(__IO uint8_t *)&SPI1->DR;
data_rx++;
rx_size --;
}
}
/* Wait until the SPI is not busy */
while (__HAL_SPI_GET_FLAG(&hspi1, SPI_FLAG_BSY));
/* Disable SPI */
SPI1->CR1 &= ~SPI_CR1_SPE;
}
2024-07-08 07:17 AM
The auto-generated code just does the initialisation stuff - you can write your own register-level code to do the runtime sending thereafter.
2024-07-08 09:11 AM
Hi @RongShengWang ,
Here 2 examples with SPI LL APIs using STM32C031: https://github.com/STMicroelectronics/STM32CubeC0/tree/main/Projects/NUCLEO-C031C6/Examples_LL/SPI.
You can start from the IOC file of each example and adapt it to yours needs.
-Amel
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2024-07-08 09:30 AM
Hi, Almel,
SPI LL API function only allows two-byte R/W each time. The slave side requires 4-Byte SPI R/W each time. We can't use LL for the Master SPI.
HAL introduces a big delay (15 us -20 us) between two consecutive HAL SPI-API calls (such as two calls to HAL_SPI_TransmitReceive()). . We need 6 SPI-API calls within 128us for our application, This big delay inserted by HAL between any two consecutive HAL SPI-API calls makes it impossible. .
Could you explain how your LL example can overcome the problem in the above?
Thanks
Rong
2024-07-08 09:31 AM
Hi, Andrew Neil,
"you can write your own register-level code to do the runtime" - Could you provide me with a reference code?
Thanks,
Rong
2024-07-08 09:45 AM
Sorry, no.
I suggest you look at the LL code, and adapt that...
2024-07-08 10:00 AM
Hi,
"you can write your own register-level code to do the runtime sending thereafter." - The CubeMX compiler may not recognize the own register-level code, such as "SPI1->DR = (uint16_t)(tx_data << 8);", which I copied from some
reference projects using STM32 SPI registers to handle SPI.
How to make CubeMX compiler to recognize it?
Thanks,
Rong
2024-07-08 10:03 AM
@RongShengWang wrote:The CubeMX compiler ...
You mean the CubeIDE compiler - ie, GCC ?
@RongShengWang wrote:... may not recognize the own register-level code, such as "SPI1->DR = (uint16_t)(tx_data << 8);"
What makes you say that?
2024-07-08 10:05 AM
I am using CubeIDE compiler for everything now.
2024-07-08 10:09 AM
Hi, Almel,
SPI LL API function only allows two-byte R/W each time. The slave side requires 4-Byte SPI R/W each time. We can't use LL for the Master SPI because the protocol is 4-byte based.
Besides We need 6 SPI-API calls within 128us for our application.
Could you explain why LL can satisfy the above requirement?
Thanks,
Rong