cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART Byte-to-Byte treatment

Nero
Associate II

Hello,

 

I am trying to receive and transmit byte-to-byte on a STM32F429 Discovery, I will be using a STM32U5 Discovery soon. I used UART IT method but maybe there is a better solution...

Objective & Issue:

I want to continuously receive and send byte-to-byte, goal is to apply a function to each byte before transmitting it. Right now I can receive and transmit but I lose some characters in the process.

For example if I send "Passphrase" to Uart using a python script, my implementation will transmit something like "PasPhase". It gets worst if I add more code to do something to the byte for instance...

How can I fix this ? This is not the case if I use a bigger buffer but I want to make sure I receive a byte, treat it and send it through UART ASAP, maybe there is a way to receive next byte at the same time I am treating the current byte ?

 

What I did:

I am using HAL_UART_Receive_IT and HAL_UART_Transmit_IT based on examples I found in the F4 firmware.
I am using a tag UartReady to SET and RESET to alternate between Receive and Transmit.

 

/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file : main.c * @brief : Main program body ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define BUFFER_SIZE 1 /* USER CODE END PD */ /* Private variables ---------------------------------------------------------*/ UART_HandleTypeDef huart1; /* USER CODE BEGIN PV */ __IO ITStatus UartReady = RESET; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART1_UART_Init(void); /* Private user code ---------------------------------------------------------*/ /* USER CODE BEGIN 0 */ uint8_t volatile g_aui_read_buf[BUFFER_SIZE] = {0}; /* USER CODE END 0 */ /** * @brief The application entry point. * @retval int */ int main(void) { /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* Configure the system clock */ SystemClock_Config(); /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_USART1_UART_Init(); /* Infinite loop */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ UartReady = RESET; if (HAL_UART_Receive_IT(&huart1, &g_aui_read_buf, BUFFER_SIZE) != HAL_OK) { Error_Handler(); } while (UartReady != SET) { } UartReady = RESET; if (HAL_UART_Transmit_IT(&huart1, &g_aui_read_buf, BUFFER_SIZE) != HAL_OK) { Error_Handler(); } while (UartReady != SET) { } /* Reset transmission flag */ UartReady = RESET; } /* USER CODE END 3 */ } /** * @brief USART1 Initialization Function * None * @retval None */ static void MX_USART1_UART_Init(void) { huart1.Instance = USART1; huart1.Init.BaudRate = 115200; huart1.Init.WordLength = UART_WORDLENGTH_8B; huart1.Init.StopBits = UART_STOPBITS_1; huart1.Init.Parity = UART_PARITY_NONE; huart1.Init.Mode = UART_MODE_TX_RX; huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; huart1.Init.OverSampling = UART_OVERSAMPLING_16; if (HAL_UART_Init(&huart1) != HAL_OK) { Error_Handler(); } } /* USER CODE BEGIN 4 */ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *p_h_uart) { /* Set transmission flag: transfer complete */ UartReady = SET; } void HAL_UART_TxCpltCallback(UART_HandleTypeDef *p_h_uart) { UartReady = SET; } /* USER CODE END 4 */ /** * @brief This function is executed in case of error occurrence. * @retval None */ void Error_Handler(void) { /* USER CODE BEGIN Error_Handler_Debug */ /* User can add his own implementation to report the HAL error return state */ __disable_irq(); while (1) { } /* USER CODE END Error_Handler_Debug */ }
View more

 

 

1 ACCEPTED SOLUTION

Accepted Solutions

Example of ring buffer implementation:

http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/

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.

View solution in original post

4 REPLIES 4

That's a pretty inefficient way of doing it.

A common approach would be to use a Ring Buffer (aka Circular Buffer): your receiver puts its received characters into the buffer, and your processing takes characters from the buffer.

Thus the buffer takes up the "slack" between receiving & processing - to prevent data loss.

Example of ring buffer implementation:

http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/

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.

@mÆŽALLEm wrote:

Example of ring buffer implementation:


I'm actually using a simplified version of that at the moment!

@Nero don't be put off by the URL having "interrupt-free" in it: 

http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/

The article most certainly is about interrupt-driven comms!

Nero
Associate II

Thank you both @Andrew Neil  @mÆŽALLEm  for your replies, I will take a look at this !