cancel
Showing results for 
Search instead for 
Did you mean: 

Why does the value of the variable inside the interrupt not change?

AlexanderKibarov
Associate III

In this code, the value of the range variable in the purse does not change correctly. What is the reason?

Board = NUCLEO-F413ZH

/* External variables --------------------------------------------------------*/
extern UART_HandleTypeDef huart4;
extern volatile uint8_t range;
extern uint8_t first_buffer[5];
extern uint8_t main_buffer[8];
/* USER CODE BEGIN EV */

void UART4_IRQHandler(void)
{
  /* USER CODE BEGIN UART4_IRQn 0 */

  /* USER CODE END UART4_IRQn 0 */
  HAL_UART_IRQHandler(&huart4);
  /* USER CODE BEGIN UART4_IRQn 1 */
  //__HAL_UART_ENABLE_IT(&huart4, UART_IT_RXNE);
  if(range == 0) {
	  HAL_UART_Receive_IT(&huart4, first_buffer, 5);
	  range = 1;
  }
  else if(range == 1){
	  HAL_UART_Receive_IT(&huart4, main_buffer, 8);
	  range = 0;
  }
  /* USER CODE END UART4_IRQn 1 */
}

 

1 ACCEPTED SOLUTION

Accepted Solutions
Karl Yamashita
Lead III

I just confirmed, writing your code in UART4_IRQHandler doesn't work. range doesn't update.

But writing your code in the callback works so range changes correctly. 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

View solution in original post

8 REPLIES 8
Pavel A.
Evangelist III

What if range is not 0 and not 1?

TDK
Guru

Generally, you should be putting HAL_UART_Receive_IT within a user callback such as the receive complete callback. The way it is now, it'll trigger off of any UART IRQ, including each received character. Certainly not what you want. Monitor the return status of HAL_UART_Receive_IT and do something useful when it's something other than HAL_OK.

Most likely, the variable is changing as it should but bugs in the code are responsible for the bad behavior you're seeing.

If you feel a post has answered your question, please click "Accept as Solution".

Hello, the full code is as follows:

 

main.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  */
#include "main.h"

UART_HandleTypeDef huart4;
UART_HandleTypeDef huart3;

PCD_HandleTypeDef hpcd_USB_OTG_FS;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_UART4_Init(void);

volatile uint8_t range = 0;
uint8_t first_buffer[5];
uint8_t main_buffer[8];

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_UART4_Init();

  __HAL_UART_ENABLE_IT(&huart4, UART_IT_RXNE);

  while (1)
  {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
      HAL_Delay(250);
  }
}

#endif /* USE_FULL_ASSERT */

 

stm32f4xx_it.h:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f4xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  */
/* USER CODE END Header */

#include "main.h"
#include "stm32f4xx_it.h"

extern UART_HandleTypeDef huart4;
extern volatile uint8_t range;
extern uint8_t first_buffer[5];
extern uint8_t main_buffer[8];

void UART4_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart4);

  if(range == 0) {
	  HAL_UART_Receive_IT(&huart4, first_buffer, 5);
	  range = 1;
  }
  else if(range == 1) {
	  HAL_UART_Receive_IT(&huart4, main_buffer, 8);
	  range = 0;
  }
}

 

 

The Range variable measures whether 5 bytes or 8 bytes will be read. However, the variable values do not change properly; sometimes it remains 1 when it should be 0, sometimes the opposite happens, and sometimes it works correctly. But regardless of the situation, it always reads the 5-byte portion the first time it runs, then reads the 8-byte portion without checking the value of the range variable.

Hello, the full code is as follows:

 

main.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  */
#include "main.h"

UART_HandleTypeDef huart4;
UART_HandleTypeDef huart3;

PCD_HandleTypeDef hpcd_USB_OTG_FS;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART3_UART_Init(void);
static void MX_USB_OTG_FS_PCD_Init(void);
static void MX_UART4_Init(void);

volatile uint8_t range = 0;
uint8_t first_buffer[5];
uint8_t main_buffer[8];

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USART3_UART_Init();
  MX_USB_OTG_FS_PCD_Init();
  MX_UART4_Init();

  __HAL_UART_ENABLE_IT(&huart4, UART_IT_RXNE);

  while (1)
  {
      HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14);
      HAL_Delay(250);
  }
}

#endif /* USE_FULL_ASSERT */

 

stm32f4xx_it.c:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file    stm32f4xx_it.c
  * @brief   Interrupt Service Routines.
  ******************************************************************************
  */
/* USER CODE END Header */

#include "main.h"
#include "stm32f4xx_it.h"

extern UART_HandleTypeDef huart4;
extern volatile uint8_t range;
extern uint8_t first_buffer[5];
extern uint8_t main_buffer[8];

void UART4_IRQHandler(void)
{
  HAL_UART_IRQHandler(&huart4);

  if(range == 0) {
	  HAL_UART_Receive_IT(&huart4, first_buffer, 5);
	  range = 1;
  }
  else if(range == 1) {
	  HAL_UART_Receive_IT(&huart4, main_buffer, 8);
	  range = 0;
  }
}

 

The Range variable measures whether 5 bytes or 8 bytes will be read. However, the variable values do not change properly; sometimes it remains 1 when it should be 0, sometimes the opposite happens, and sometimes it works correctly. But regardless of the situation, it always reads the 5-byte portion the first time it runs, then reads the 8-byte portion without checking the value of the range variable.

 

The code you linked still has the issues I pointed out in my previous reply.

If you feel a post has answered your question, please click "Accept as Solution".

Don't write anything in the UART4_IRQHandler. Write your code in the callback instead. Override the HAL_UART_RxCpltCallback callback. Not sure if that'll fix your issue, but at least the HAL driver will be done clearing any interrupts and/or save the error(s) prior to calling the callback.

 

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	if(range == 0) {
	  HAL_UART_Receive_IT(&huart4, first_buffer, 5);
	  range = 1;
	}
	else if(range == 1) {
	  HAL_UART_Receive_IT(&huart4, main_buffer, 8);
	  range = 0;
	}
}

Also, you should look into using HAL_UARTEx_ReceiveToIdle_IT or HAL_UARTEx_ReceiveToIdle_DMA and HAL_UARTEx_RxEventCallback, that way you can receive any variable length packet.

 

  

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.
Karl Yamashita
Lead III

I just confirmed, writing your code in UART4_IRQHandler doesn't work. range doesn't update.

But writing your code in the callback works so range changes correctly. 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

Thanks You Sir!