cancel
Showing results for 
Search instead for 
Did you mean: 

How to use the 'HAL_UART_Receive_IT' within a function?

Marco S
Associate II

Hello,

I'm working with an STM32G4 MCU and I want to listen the UART3 with interruption. I am testing with a code which changes the color of a led. The following code works fine :

//main.c
 
#include "main.h"
 
 
 
FDCAN_HandleTypeDef hfdcan3;
 
FDCAN_HandleTypeDef hfdcan4;
 
 
 
char uart3_buffer[64]={0};
 
uint8_t RxChar3;
 
 
 
int main(void)
 
{
 
 /* USER CODE BEGIN 1 */
 
 
 
 /* USER CODE END 1 */
 
 
 
 /* MCU Configuration--------------------------------------------------------*/
 
 
 
 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 
 HAL_Init();
 
 
 
 /* USER CODE BEGIN Init */
 
 
 
 /* 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_FDCAN3_Init();
 
 MX_UART4_Init();
 
 MX_USART3_UART_Init();
 
 
 
 /* USER CODE BEGIN 2 */
 
 
 
 
 
 /* USER CODE END 2 */
 
 
 
 /* Infinite loop */
 
 /* USER CODE BEGIN WHILE */
 
 while (1)
 
 {
 
	 	/* Listen the USART3. */
 
		HAL_UART_Receive_IT(&huart3, &RxChar3, 1);
 
 
 
		/* Copy only the non null characters into the buffer. */
 
		if(RxChar3==49){ // ASCII of character 1.
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET); /* Function to light on a led activating a GPIO. */
 
		}
 
		else if(RxChar3==50){ // ASCII of character 2.
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);/* Function to light on a led activating a GPIO. */
 
		}
 
		else if(RxChar3==51){ // ASCII of character 3.
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
 
		}
 
		else{
 
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET); /* Function to light on a led activating a GPIO. */
 
		}
 
 
 
		/* Sends the current value of Rxchar3 variable (only for debugging). */
 
		snprintf(uart3_buffer, sizeof(uart3_buffer), "Rxchar3: %u\n", RxChar3);
 
		HAL_UART_Transmit(&huart3, (uint8_t*)uart3_buffer, strlen(uart3_buffer), 0xFFFFFFFF);
 
	 HAL_Delay(500);
 
  /* USER CODE END WHILE */
 
 
 
  /* USER CODE BEGIN 3 */
 
 }
 
 /* USER CODE END 3 */
 
}

Nevertheless, as I have more than one than one serial port configured in the MCU I want to put the 'HAL_UART_Receive_IT' function within another function which receives as input parameter the number of serial interface. I have done as follows:

main.c

//main.c
FDCAN_HandleTypeDef hfdcan3;
FDCAN_HandleTypeDef hfdcan4;
 
char uart3_buffer[64]={0};
uint8_t RxChar3;
 
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
 
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* 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_FDCAN3_Init();
  MX_UART4_Init();
  MX_USART3_UART_Init();
 
  /* USER CODE BEGIN 2 */
 
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  	/* Listen the USART3. */
		UART_RX_String01(3); // Listen UART3
 
		/* Copy only the non null characters into the buffer. */
		if(RxChar3==49){  // ASCII of character 1.
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_SET); /* Function to light on a led activating a GPIO. */
		}
		else if(RxChar3==50){  // ASCII of character 2.
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);/* Function to light on a led activating a GPIO. */
		}
		else if(RxChar3==51){ //  ASCII of character 3.
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_1, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_RESET); /* Function to power off a led deactivating a GPIO. */
		}
		else{
			HAL_GPIO_WritePin(GPIOD, GPIO_PIN_4, GPIO_PIN_SET); /* Function to light on a led activating a GPIO. */
		}
 
		/* Sends the current value of Rxchar3 variable (only for debugging). */
		snprintf(uart3_buffer, sizeof(uart3_buffer), "Rxchar3: %u\n", RxChar3);
		HAL_UART_Transmit(&huart3, (uint8_t*)uart3_buffer, strlen(uart3_buffer), 0xFFFFFFFF);
	  HAL_Delay(500);
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

uart_func.h

//uart_func.h
#ifndef INC_UART_FUNCTIONS_H_
#define INC_UART_FUNCTIONS_H_
 
#include "stm32g4xx_hal.h"
 
extern UART_HandleTypeDef huart3;
extern UART_HandleTypeDef huart4;
 
void UART_RX_String01(uint8_t);
 
#endif /* INC_UART_FUNCTIONS_H_ */

uart_func.c

//uart_func.c
#include "uart_func.h"
void UART_RX_String01(uint8_t port_number){
	uint8_t RxStringBuffer;
	HAL_StatusTypeDef RX_State;
 
	/* Select the UART port to be listened. */
	if (port_number==3){
		RX_State = HAL_UART_Receive_IT(&huart3, &RxStringBuffer, 1);
 
		/* Send the function's return value. */
		snprintf(uart_buffer, sizeof(uart_buffer), "Rx State %u", RX_State);
		HAL_UART_Transmit(&huart3, (uint8_t*)uart_buffer, strlen(uart_buffer), 0xFFFFFFFF);
	}
 
	if (port_number==4){
		RX_State = HAL_UART_Receive_IT(&huart4, &RxStringBuffer, 1);
 
		/* Send the function's return value. */
		snprintf(uart_buffer, sizeof(uart_buffer), "Rx State %u", RX_State);
		HAL_UART_Transmit(&huart4, (uint8_t*)uart_buffer, strlen(uart_buffer), 0xFFFFFFFF);
	}
}

The 'main.h' header file includes the 'uart_func.h' header. The problem I have with this is that in this case the MCU blocks around 20 seconds when I send a character to the serial interface. Then it continues turning. Why does this happen? Or isn't it possible to call this function out of the main.c ?

11 REPLIES 11

Exactly.

In order to be properly sent, data (located at an address in stack when declared as local) should remain consistent until transfer is completed : that's why it works when adding a delay. Without delay, after function exits, stack content is overwritten by further functions calls and parameters of your code.

Using HAL, use of a buffer declared as local as in your example, is possible only with "polling mode" function : HAL_UART_Transmit()

This function exits only when transfer is completed, so msg buffer content could be overwrtitten without impacting the transfer.

Regards

Totally agree...