cancel
Showing results for 
Search instead for 
Did you mean: 

Communicate NUCLEO-G070RB USART with SPI as MSB

yurim
Associate II

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.

 

yurim_1-1745200797854.png

yurim_0-1745201521951.png

 

 

 

6 REPLIES 6
TDK
Super User

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);

 

If you feel a post has answered your question, please click "Accept as Solution".

@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?

AndrewNeil_0-1745400113695.png

https://www.st.com/resource/en/user_manual/um2319-description-of-stm32g0-hal-and-lowlayer-drivers-stmicroelectronics.pdf#page=825

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.

@TDK 

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.

yurim_0-1745455579000.png

yurim_1-1745455586615.png

 


Thank you.


@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

A complex system that works is invariably found to have evolved from a simple system that worked.
A complex system designed from scratch never works and cannot be patched up to make it work.
Pavel A.
Super User

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.

 

@Andrew Neil , @Pavel A. 

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;
}