2025-04-20 7:02 PM - edited 2025-04-20 7:12 PM
Thank you always for your hard work,
I needed 4 SPIs, so while exploring the board, I found a text that could make USART work like SPI, so I tried this with the NUCLEO-G070RB.
The example I referenced is "USART_SyncCommunication_FullDuplex_DMA_Init" on that board.
Referring to the setting of the board, a program was written to check whether it was the same as the buffer sent by the buffer that received a specific message from USART (master) to SPI (slave).
The current code works well.
However, the standard setting of SPI is MSB first, but the example seems to be possible only with LSB first.
I want USART and SPI to communicate by MSB.
Attached is the setup of USART and SPI.
2025-04-21 5:08 AM
The setting appears to be missing in CubeMX.
Try setting the MSBFIRST bit in USART_CR2 after it's initialized.
SET_BIT(USART_CR2, USART_CR2_MSBFIRST);
2025-04-23 2:19 AM - edited 2025-04-23 2:22 AM
@TDK wrote:The setting appears to be missing in CubeMX.
I only had a quick look, but I also didn't see it in the STM32G0 HAL documentation:
https://www.st.com/resource/en/user_manual/um2319-description-of-stm32g0-hal-and-lowlayer-drivers-stmicroelectronics.pdf
via: https://www.st.com/en/embedded-software/stm32cubeg0.html#documentation
PS:
maybe this is it?
2025-04-23 5:47 PM
I've enabled MSB_FIRST BIT since the initialization of USART, but the output results remain unchanged. (It still seems to be operating as LSB first.)
Is there any way I can try it now?
Below are the buffers I sent to USART(UsartTx) and the buffers I received with SPI(SpiRx). In CUBE MX, I changed SPI to MSB First.
Thank you.
2025-04-25 12:15 AM
@yurim wrote:I've enabled MSB_FIRST BIT since the initialization of USART
Please show your code - ideally, a minimum but complete example which demonstrates the issue.
Both Rx & Tx
see: How to insert source code.
Have you used an oscilloscope and/or logic analyser to see what actually happens on the wires?
You would need to configure both ends for MSB-first
2025-04-26 12:34 PM - edited 2025-04-26 12:37 PM
From the RM, about the MSBFIRST: "This bitfield can only be written when the USART is disabled (UE=0)."
So don't set this bit after init(), rather set the AdvFeatureInit struct members as usual.
2025-05-28 9:30 PM
Thank you to all responders. I don't know what AdvFeatureInit is, but I tried setting the bit before Init(), but it doesn't work. Simply put, it's a main.c and .c file that communication USART-SPI. I use timer interrupt to periodically send USART and see if the SPI associated with USART matches the string I received.
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
SET_BIT(husart1.Instance->CR2, USART_CR2_MSBFIRST);
/* 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_DMA_Init();
MX_SPI1_Init();
MX_TIM1_Init();
MX_USART2_UART_Init();
MX_USART1_Init();
/* USER CODE BEGIN 2 */
// USART DMA Enable Transmitter
SET_BIT(husart1.Instance->CR3,USART_CR3_DMAT);
// USART DMA Enable Receiver
SET_BIT(husart1.Instance->CR3,USART_CR3_DMAR);
// SPI DMA Enable Transmitter
SET_BIT(husart1.Instance->CR3,SPI_CR2_TXDMAEN);
// SPI DMA Enable Receiver
SET_BIT(hspi1.Instance->CR2,SPI_CR2_RXDMAEN);
printf("\t# SYL Test Start\r\n");
HAL_TIM_Base_Start_IT(&htim1);
osKernelInitialize();
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
osKernelStart();
while (1)
{
}
}
// Transmission Buffer
uint8_t UsartTx[] = "123456789";
uint8_t SizeUsartTx = sizeof(UsartTx);
// Reception Buffer
uint8_t SpiRx[sizeof(UsartTx)];
__IO uint8_t SpiRxComplete = 0;
enum
{
TRANSFER_WAIT,
TRANSFER_COMPLETE,
TRANSFER_ERROR
};
void tmr_ISR(void){
StartTransfers();
}
void LED_On(void){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET);
}
void LED_Off(void){
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_RESET);
}
void LED_Toggle(void){
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5);
}
void StartTransfers(void)
{
// ready to receive SPI1
HAL_SPI_Receive_DMA(&hspi1, SpiRx, SizeUsartTx);
// USART1 -> SPI1
HAL_USART_Transmit_DMA(&husart1, UsartTx, SizeUsartTx);
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
if(hspi->Instance == SPI1)
{
SpiRxComplete = 1;
WaitAndCheckEndOfTransfer();
}
}
void WaitAndCheckEndOfTransfer(void)
{
// Wait for all transfers to complete
while(! SpiRxComplete)
{
// transmit error check
if(husart1.ErrorCode != HAL_USART_ERROR_NONE || hspi1.ErrorCode != HAL_SPI_ERROR_NONE)
{
Error_Handler();
}
}
// compare buffer
if (memcmp(UsartTx, SpiRx, SizeUsartTx)!= 0)
{
LED_On();
printf("\t Err");
}
else
{
//LED_Off();
}
ResetTest();
}
void ResetTest()
{
// reset
SpiRxComplete = 0;
}