2024-11-18 06:50 AM - edited 2024-11-18 06:53 AM
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 */
}
Solved! Go to Solution.
2024-11-18 07:54 AM
Example of ring buffer implementation:
http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/
2024-11-18 06:56 AM
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.
2024-11-18 07:54 AM
Example of ring buffer implementation:
http://www.simplyembedded.org/tutorials/interrupt-free-ring-buffer/
2024-11-18 08:23 AM
@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!
2024-11-19 12:46 AM - edited 2024-11-19 12:47 AM
Thank you both @Andrew Neil @SofLit for your replies, I will take a look at this !