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 */
}

 

 

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.

@SofLit 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  @SofLit  for your replies, I will take a look at this !