2025-05-03 6:38 AM - last edited on 2025-05-07 12:24 PM by Andrew Neil
Hello,
I am working on a project with a Nucleo-G431KB. I am using UART1 to receive GPS data (LEA-6S module, 9600 baud, 3.3V) on pin PB7 (RX), and I send data to a LoRa module (Ebyte E32868T20 module, 3.3V, 9600 baud too) on PB6 (TX).
I configured UART1 in asynchronous mode with interrupts enabled (USART1 global interrupt active).
In my code, I call HAL_UART_Receive_IT(&huart1, &recep, 1) at startup, and I relaunch HAL_UART_Receive_IT at the end of HAL_UART_RxCpltCallback().
The GPS sends data correctly (tested with a direct connection) and the lora module works too (tested by sending text every 3 seconds), but on the Nucleo, the UART interrupt never seems to trigger.
I give you my main.c and my .ioc file
Any idea what could block the UART RX interrupt on the G431KB?
Thanks!
2025-05-03 7:45 AM
Hi,
basically it should work, but :
- did you enable callback in Cube ?
- on any error uart will stop working - and then..?
You need callback on receive + error :
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
printf("UART7 error testvar hex %ld \n ",testvari);
// *** ... try again
HAL_UART_Receive_IT(&huart7, &ESP_RX[ESP_RX_COUNT], 1);
}
2025-05-07 5:59 AM
thank you but this solution doesn't seems to work. I modified my program since last time, here it is.
the principal evolution is that I use UART1 for the GPS and UART2 for the Lora module. (I have also I2C for a C02 sensor but I don't use it for the moment).
I enabled callback and put this error function. I don't have any results, I don't recieve any message that indicates that i went in my interrupt.
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "string.h"
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define GPS_BUFFER_SIZE 128
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
COM_InitTypeDef BspCOMInit;
I2C_HandleTypeDef hi2c2;
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
volatile uint8_t gps_buffer[GPS_BUFFER_SIZE]; //array that stores characters
uint8_t recep; //byte that recieve the data
volatile uint8_t trameComplete = 0; //this boolean indicates when the gps frame is over
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_I2C2_Init(void);
/* USER CODE BEGIN PFP */
void USART2_SendString(char *str);
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
void USART2_SendString(char *str) //function that send strings
{
HAL_UART_Transmit(&huart2, (uint8_t*)str, strlen(str), HAL_MAX_DELAY);
}
void Lora_init (void)
{
uint8_t CommandeLora[] = {0xC0, 0x00, 0x01, 0x1A, 0x17, 0x44};
HAL_GPIO_WritePin(M0_GPIO_Port, M0_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(M1_GPIO_Port, M1_Pin, GPIO_PIN_RESET);
HAL_UART_Transmit(&huart1, CommandeLora, sizeof(CommandeLora), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_GPIO_WritePin(M0_GPIO_Port, M0_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(M1_GPIO_Port, M1_Pin, GPIO_PIN_RESET);
}
void GPS_init (void)
{
//Enable GGA on UART
uint8_t enable_GGA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x29};
// Disable RMC (Recommended Minimum Specific GPS/Transit Data)
uint8_t disable_RMC[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x40};
// Disable GLL (Geographic Position – Latitude/Longitude)
uint8_t disable_GLL[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x2B};
// Disable GSA (GNSS DOP and Active Satellites)
uint8_t disable_GSA[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x32};
// Disable GSV (GNSS Satellites in View)
uint8_t disable_GSV[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x39};
// Disable VTG (Course Over Ground and Ground Speed)
uint8_t disable_VTG[] = {0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x05, 0x47};
//Send message every 3 sec
uint8_t set_rate_3s[] = {0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xB8, 0x0B, 0x01, 0x00, 0x01, 0x00, 0xD9, 0x41};
HAL_UART_Transmit(&huart1, enable_GGA , sizeof(enable_GGA), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, disable_RMC, sizeof(disable_RMC), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, disable_GLL, sizeof(disable_GLL), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, disable_GSA, sizeof(disable_GSA), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, disable_GSV, sizeof(disable_GSV), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, disable_VTG, sizeof(disable_VTG), HAL_MAX_DELAY);
HAL_Delay(100);
HAL_UART_Transmit(&huart1, set_rate_3s, sizeof(set_rate_3s), HAL_MAX_DELAY);
HAL_Delay(100);
}
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
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_USART1_UART_Init();
MX_USART2_UART_Init();
MX_I2C2_Init();
/* USER CODE BEGIN 2 */
uint32_t previousTick = HAL_GetTick();
Lora_init();
GPS_init();
/* USER CODE END 2 */
/* Initialize leds */
BSP_LED_Init(LED_GREEN);
/* Initialize COM1 port (115200, 8 bits (7-bit data + 1 stop bit), no parity */
BspCOMInit.BaudRate = 115200;
BspCOMInit.WordLength = COM_WORDLENGTH_8B;
BspCOMInit.StopBits = COM_STOPBITS_1;
BspCOMInit.Parity = COM_PARITY_NONE;
BspCOMInit.HwFlowCtl = COM_HWCONTROL_NONE;
if (BSP_COM_Init(COM1, &BspCOMInit) != BSP_ERROR_NONE)
{
Error_Handler();
}
/* Infinite loop */
/* USER CODE BEGIN WHILE */
/**
* @brief Start Receive operation in interrupt mode.
* @note This function could be called by all HAL UART API providing reception in Interrupt mode.
* @note When calling this function, parameters validity is considered as already checked,
* i.e. Rx State, buffer address, ...
* UART Handle is assumed as Locked.
* @PAram huart UART handle.
* @PAram pData Pointer to data buffer (u8 or u16 data elements).
* @PAram Size Amount of data elements (u8 or u16) to be received.
* @retval HAL status
*/
// HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
HAL_UART_Receive_IT(&huart1, &recep, 1);
while (1)
{
if (HAL_GetTick() - previousTick >= 1000) // send a message every 3 seconds to test communication
{
USART2_SendString("test\r\n");
previousTick = HAL_GetTick();
};
if (trameComplete==1)
{
USART2_SendString("IT WORKS !\r\n"); //test if the interruption works
trameComplete=0;
}
if (trameComplete==2)
{
USART2_SendString("ERROR\r\n"); //test if the interruption works
trameComplete=0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1_BOOST);
/** Initializes the RCC Oscillators according to the specified parameters
* in the RCC_OscInitTypeDef structure.
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = RCC_PLLM_DIV4;
RCC_OscInitStruct.PLL.PLLN = 85;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;
RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief I2C2 Initialization Function
* @PAram None
* @retval None
*/
static void MX_I2C2_Init(void)
{
/* USER CODE BEGIN I2C2_Init 0 */
/* USER CODE END I2C2_Init 0 */
/* USER CODE BEGIN I2C2_Init 1 */
/* USER CODE END I2C2_Init 1 */
hi2c2.Instance = I2C2;
hi2c2.Init.Timing = 0x40B285C2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
{
Error_Handler();
}
/** Configure Analogue filter
*/
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c2, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
{
Error_Handler();
}
/** Configure Digital filter
*/
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c2, 0) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN I2C2_Init 2 */
/* USER CODE END I2C2_Init 2 */
}
/**
* @brief USART1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
/* USER CODE BEGIN USART1_Init 0 */
/* USER CODE END USART1_Init 0 */
/* USER CODE BEGIN USART1_Init 1 */
/* USER CODE END USART1_Init 1 */
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
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;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART1_Init 2 */
/* USER CODE END USART1_Init 2 */
}
/**
* @brief USART2 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART2_UART_Init(void)
{
/* USER CODE BEGIN USART2_Init 0 */
/* USER CODE END USART2_Init 0 */
/* USER CODE BEGIN USART2_Init 1 */
/* USER CODE END USART2_Init 1 */
huart2.Instance = USART2;
huart2.Init.BaudRate = 9600;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart2, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart2, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN USART2_Init 2 */
/* USER CODE END USART2_Init 2 */
}
/**
* @brief GPIO Initialization Function
* @PAram None
* @retval None
*/
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, M0_Pin|M1_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : M0_Pin M1_Pin */
GPIO_InitStruct.Pin = M0_Pin|M1_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}
/* USER CODE BEGIN 4 */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
static uint16_t gps_index = 0; //this is the index of the array
static uint8_t gps_receiving = 0; //this control if the uart is recieving
if (huart->Instance == USART1)
{
trameComplete = 1; //i putted this boolean here to test if the interruption works
if (recep == '$') // start of the frame
{
gps_index = 0;
gps_receiving = 1;
gps_buffer[gps_index++] = recep;
}
else if (gps_receiving)
{
if (gps_index < (GPS_BUFFER_SIZE - 1))
{
gps_buffer[gps_index++] = recep;
// end of frame detected : "\r\n"
if ((recep == '\n' && (gps_index >= 2)) &&( gps_buffer[gps_index - 2] == '\r'))
{
gps_receiving = 0;
}
}
else
{
// overflow: reset
gps_index = 0;
gps_receiving = 0;
}
}
// Relaunch uart it
HAL_UART_Receive_IT(&huart1, &recep, 1);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
trameComplete = 2;
// *** ... try again
HAL_UART_Receive_IT(&huart1, &recep, 1);
}
/* USER CODE END 4 */
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* Copyright (c) 2025 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 */
/**
* @}
*/
/**
* @}
*/
/**
* @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 */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @PAram file: pointer to the source file name
* @PAram line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
2025-05-07 10:40 AM - edited 2025-05-07 10:42 AM
It should work now.
Did you check, the interrupt is called at all?
Maybe you puzzled a wire... so make a breakpoint in the UART int, just to see, the UART getting data at all.
If nothing, look in debug at the SFR, UART registers and the settings there.
And what is in Rx data register...at all.
2025-05-07 12:13 PM
The GPS sends data correctly (tested with a direct connection) and the lora module works too (tested by sending text every 3 seconds), but on the Nucleo, the UART interrupt never seems to trigger.
What does direct connection mean? Are you using a Click board that has a USB connection to a serial terminal? Or a USB<>Serial adapter?
Hopefully you have a ground reference between the devices?
Have you checked with an oscilloscope if you're getting data activity on the Nucleo pin CN4-7? You should have an open pin in between the CN4-7 and CN4-9 and not mistakenly connected the GPS to CN4-8.
2025-05-07 12:27 PM
As @Karl Yamashita said, test that the signal is actually arriving at the STM32 RX pin.
Before worrying about interrupts, get it working in polled mode.
Before worrying about GPS and LoRa, get it working with a PC terminal.
On debugging serial comms:
2025-05-08 4:14 AM
Thank you for the awnser but my GPS sends data correctly, I checked with hterm (a serial terminal) and a module that convert UART to USB. I did the same thing with my LORA module. I also have the same ground reference between every devices. I also checked the activity on a oscilloscope and every connection is ok.
2025-05-08 4:22 AM
I think that can help me but at which line should I put my breakpoint and how do I check the flags, registers etc...
2025-05-08 4:29 AM
Thank you for the awnser, I will check in polled mode. I am shure that my UART1 and UART2 can transmit but idk if they can recieve. I already checked communication of the lora and the gps with a serial terminal (hterm) and a USB/UART converter so I am sure my gps sends data correctly at 9600 bauds (I also checked with an oscilloscope).