2025-07-07 3:17 AM
Hi :
I want to switch my project from HAL to LL because of flash size.
But SPI doesn't work after switching.
When I using HAL, the code below in main function works fine, uart will print OK.
When I switch to LL, it will print NG.
After switching to LL, I already add LL_SPI_Enable(SPI1); to MX_SPI1_Init function.
Cubemx project and all code is as attachment.
uint8_t data = 0x80;
CS_GPIO_Port->BSRR = (uint32_t)CS_Pin << 16u;
#ifdef USE_HAL_DRIVER
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_SPI_Receive(&hspi1, &data, 1, 100);
#else
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, data);
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, 0xff);
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
data = LL_SPI_ReceiveData8(SPI1);
#endif
CS_GPIO_Port->BSRR = CS_Pin;
if(data == 0x05)
{
while (!LL_USART_IsActiveFlag_TXE(USART2));
LL_USART_TransmitData8(USART2, 'O');
while (!LL_USART_IsActiveFlag_TXE(USART2));
LL_USART_TransmitData8(USART2, 'K');
}
else
{
while (!LL_USART_IsActiveFlag_TXE(USART2));
LL_USART_TransmitData8(USART2, 'N');
while (!LL_USART_IsActiveFlag_TXE(USART2));
LL_USART_TransmitData8(USART2, 'G');
}
MX_SPI1_Init:
/**
* @brief SPI1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
LL_SPI_InitTypeDef SPI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = SCL_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SCL_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SDO_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SDO_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = SDA_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ALTERNATE;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
GPIO_InitStruct.Alternate = LL_GPIO_AF_0;
LL_GPIO_Init(SDA_GPIO_Port, &GPIO_InitStruct);
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
SPI_InitStruct.TransferDirection = LL_SPI_FULL_DUPLEX;
SPI_InitStruct.Mode = LL_SPI_MODE_MASTER;
SPI_InitStruct.DataWidth = LL_SPI_DATAWIDTH_8BIT;
SPI_InitStruct.ClockPolarity = LL_SPI_POLARITY_LOW;
SPI_InitStruct.ClockPhase = LL_SPI_PHASE_1EDGE;
SPI_InitStruct.NSS = LL_SPI_NSS_SOFT;
SPI_InitStruct.BaudRate = LL_SPI_BAUDRATEPRESCALER_DIV4;
SPI_InitStruct.BitOrder = LL_SPI_MSB_FIRST;
SPI_InitStruct.CRCCalculation = LL_SPI_CRCCALCULATION_DISABLE;
SPI_InitStruct.CRCPoly = 7;
LL_SPI_Init(SPI1, &SPI_InitStruct);
LL_SPI_SetStandard(SPI1, LL_SPI_PROTOCOL_MOTOROLA);
LL_SPI_EnableNSSPulseMgt(SPI1);
/* USER CODE BEGIN SPI1_Init 2 */
#ifndef USE_HAL_DRIVER
LL_SPI_Enable(SPI1);
#endif
/* USER CODE END SPI1_Init 2 */
}
Solved! Go to Solution.
2025-07-09 12:53 AM
Hi :
To resolve this, every time you send data, you need to read it once.
So the code should be as follow:
#ifdef USE_HAL_DRIVER
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_SPI_Receive(&hspi1, &data, 1, 100);
#else
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, data);
/*you need read after send */
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
LL_SPI_ReceiveData8(SPI1);
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, 0xff);
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
data = LL_SPI_ReceiveData8(SPI1);
#endif
2025-07-07 5:40 PM
Hi @Imen.D :
Can you help confirm this question?
2025-07-08 7:01 AM
Hello @Zhou JianQiang
What is not working exactly? Is it sending wrong data ? is the SPI clock generated ?
Could you share the content of SR and CR register after SPI init and before executing LL_SPI_TransmitData8(SPI1, data);
Please refer to the example below as starting point :
2025-07-08 7:10 AM
@Zhou JianQiang wrote:SPI doesn't work after switching.
That's uninformative.
What testing/investigation/debugging have you done to find what's going on?
Have you looked at the SPI lines with an oscilloscope and/or analyser to see what's happening on the wires?
Have you stepped through the old HAL code, and the new LL code, and compared what's happening?
Remember that the STM32 itself neither knows nor cares about HAL or LL - all that matters is that the registers get set to the correct things...
2025-07-09 12:53 AM
Hi :
To resolve this, every time you send data, you need to read it once.
So the code should be as follow:
#ifdef USE_HAL_DRIVER
HAL_SPI_Transmit(&hspi1, &data, 1, 100);
HAL_SPI_Receive(&hspi1, &data, 1, 100);
#else
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, data);
/*you need read after send */
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
LL_SPI_ReceiveData8(SPI1);
while (!LL_SPI_IsActiveFlag_TXE(SPI1));
LL_SPI_TransmitData8(SPI1, 0xff);
while (!LL_SPI_IsActiveFlag_RXNE(SPI1));
data = LL_SPI_ReceiveData8(SPI1);
#endif