cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive_IT() only fires once, and I don't know why.

BBara.1
Associate II

Hi!

I am trying to write a program where I am waiting for receiving 6 bytes of data through UART. It works just fine the first time, than I restart the receive_IT function and nothing happens anymore. I have other codes where I use it just the same, the only difference is the MCU. For this project I am using an STM32F030F4P6.

main.c

volatile uint8_t rx_buffer[6] = {0};
int8_t step = 1;
/* 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_TIM3_Init();
  MX_USART1_UART_Init();
  MX_TIM14_Init();
  /* USER CODE BEGIN 2 */
  HAL_UART_Receive_IT(&huart1, rx_buffer, 6);
 
  HAL_GPIO_WritePin(Sleep_X_GPIO_Port, Sleep_X_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(Sleep_Y_GPIO_Port, Sleep_Y_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(Sleep_Z_GPIO_Port, Sleep_Z_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(Step_X_GPIO_Port, Step_X_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(Step_Y_GPIO_Port, Step_Y_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(Step_Z_GPIO_Port, Step_Z_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_RESET);
 
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

stm32f0xx_it.c

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
	/*
	 * x, e = 221
	 * x, h = 224
	 *
	 * y, e = 222
	 * y, h = 225
	 *
	 * z, e = 223
	 * z, h = 226
	 *
	 * p, k = 219
	 * p, b = 210
	 */
 
	for(i=0; i<2; i++){
		sum_rx += rx_buffer[i];
	}
 
	for(i=2;i<6;i++){
		sum_step += ((rx_buffer[i] - 48) * power(10, 5-i));
	}
 
	/*sum_step += (rx_buffer[5] - 48);
	sum_step += ((rx_buffer[4] - 48) * 10);
	sum_step += ((rx_buffer[3] - 48) * 100);
	sum_step += ((rx_buffer[2] - 48) * 1000);*/
 
	switch(sum_rx){
 
	case 221:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(Sleep_X_GPIO_Port, Sleep_X_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_X_GPIO_Port, Step_X_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_X_GPIO_Port, Step_X_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_X_GPIO_Port, Sleep_X_Pin, GPIO_PIN_RESET);
	break;
	case 224:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(Sleep_X_GPIO_Port, Sleep_X_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_X_GPIO_Port, Step_X_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_X_GPIO_Port, Step_X_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_X_GPIO_Port, Sleep_X_Pin, GPIO_PIN_RESET);
	break;
 
 
 
	case 222:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(Sleep_Y_GPIO_Port, Sleep_Y_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_Y_GPIO_Port, Step_Y_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_Y_GPIO_Port, Step_Y_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_Y_GPIO_Port, Sleep_Y_Pin, GPIO_PIN_RESET);
	break;
	case 225:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(Sleep_Y_GPIO_Port, Sleep_Y_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_Y_GPIO_Port, Step_Y_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_Y_GPIO_Port, Step_Y_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_Y_GPIO_Port, Sleep_Y_Pin, GPIO_PIN_RESET);
	break;
 
 
 
	case 223:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_RESET);
		HAL_GPIO_WritePin(Sleep_Z_GPIO_Port, Sleep_Z_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_Z_GPIO_Port, Step_Z_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_Z_GPIO_Port, Step_Z_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_Z_GPIO_Port, Sleep_Z_Pin, GPIO_PIN_RESET);
	break;
	case 226:
		HAL_GPIO_WritePin(Dir_GPIO_Port, Dir_Pin, GPIO_PIN_SET);
		HAL_GPIO_WritePin(Sleep_Z_GPIO_Port, Sleep_Z_Pin, GPIO_PIN_SET);
		for(i=0; i<sum_step; i++){
			HAL_GPIO_WritePin(Step_Z_GPIO_Port, Step_Z_Pin, GPIO_PIN_SET);
			Delay(2);
			HAL_GPIO_WritePin(Step_Z_GPIO_Port, Step_Z_Pin, GPIO_PIN_RESET);
		}
		HAL_GPIO_WritePin(Sleep_Z_GPIO_Port, Sleep_Z_Pin, GPIO_PIN_RESET);
	break;
 
	case 219:
		htim3.Instance -> CCR1 = ki;
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
		Delay(150);
		HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
	break;
 
	case 210:
		htim3.Instance -> CCR1 = be;
		HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
		Delay(150);
		HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
	break;
	default:
	break;
	}
 
	for(i=0; i<7; i++){
		rx_buffer[i] = 0;
	}
 
	HAL_UART_Receive_IT(huart, rx_buffer, 6);
 
	step = 1;
 
	sum_rx = 0;
	sum_step = 0;
}
 
void Delay(uint8_t ms){
	HAL_TIM_Base_Start(&htim14);
	while(htim14.Instance -> CNT < ms){
 
	}
	htim14.Instance -> CNT = 0;
	HAL_TIM_Base_Stop(&htim14);
}
 
int power(int x, int y){
	int i;
	int eredm = x;
	if(y != 0){
		for(i=1; i<y; i++){
			eredm *= x;
		}
	}
	else
		eredm = 1;
	return eredm;
}

I also tried not to call the HAL_UART_Receive_IT() inside the callback function, nothing else happened. I also checked the UART registers and everything seems the same as when I call the function the first time.

Thank you in advance!

********

Edit:

Thank you for the answers but today I was able to find the solution, yet I still don’t know why.

So Inoticed that the EIE bit in CR3 register don’t set to 1 after the second call of the HAL_UART_Receive_IT() function, but if I set it to 1 by hand before the function it works just fine.

1 ACCEPTED SOLUTION

Accepted Solutions
BBara.1
Associate II

Thank you for the answers but today I was able to find the solution, yet I still don’t understand.

So Inoticed that the EIE bit in CR3 register don’t set to 1 after the second call of the HAL_UART_Receive_IT() function, but if I set it to 1 by hand before the function it works just fine.

View solution in original post

11 REPLIES 11
KnarfB
Principal III

Your Delay uses an interrupt for advancing the time and if the priorities are not correct, that won't work in an interrupt handler. Set a break point in the handler and step through the code to find where it stops.

Generally, using delays and doing "excecssive" stuff in interrupt handlers is not recommended, but may work for your use case.

hth

KnarfB

I am not fully understand how my is delay using an interrupt. It only starts a timer, counts, and after a time stops again. Also if I don't use my delay function, the same thing happens.

The handler seems to run smoothly, no error or exceptional thing happens.

You're right, my fault, I was still thinking of HAL_Delay().

Check the registers, maybe the UART got an overrun error while you were processing the data.

hth

KnarfB

Karl Yamashita
Lead II

You should not do any comparing, for loops in the interrupt. Because you do, you're blocking other interrupts from firing like system tick, etc. Set a flag instead and get out quickly. Check the flag in main while loop, then call a function to do your for loop and switch/case statements. But you're main problem is that you don't check the HAL status when you call HAL_UART_Receive_IT.

Check this post i replied to to see how I set a flag if HAL_UART_Receive_IT returns HAL_BUSY and try to enable it again in main while loop.

https://community.st.com/s/question/0D53W000022Hi9ySAC/stm32-hal-uart-receive-interrupt-stops-receiving-at-random-times

If you find my answers useful, click the accept button so that way others can see the solution.

Yes, rookie thing I don't check the HAL_Status, but unfortunatelly it doesn't help me. Anyway Hal statusr returns OK. I also rewrote the program, now I only have one quick check in the callback and than I have the switch-case in the while loop. But even if I call the HAL_UART_Receive_IT() after I am done with everything It still don't works.

I am trying to look at registers with little success. I was able to find that the following exception happens:

  • When I first call the UART_Receive_IT(), the EIE in CR3 set to 1
  • After firing the interrupt EOBF is set to 1 (which is not even documented in RM0360, which looks like a Read only, so I can't reset it.
  • When the interrupt fires the EIE is set to 0, and after calling the UART_Receive_IT() again, it isn't set to 1. So i am setting it by hand with no succes.

The only solution right now if call the MX_USART1_UART_INIT() again before calling the UART_Receive_IT(), because it sets the EOBF register to 0 again.

void zeroing(void){
 
	for(i=0; i<6; i++){
		rx_buffer[i] = 0;
	}
 
	sum_rx = 0;
	sum_step = 0;
	MX_USART1_UART_Init();
	HAL_UART_Receive_IT(&huart1, &rx_buffer, 6);
}

Karl Yamashita
Lead II

What device are you receiving from and how often is it sending data?

If you find my answers useful, click the accept button so that way others can see the solution.

Hi @BBara.1​ 

When you consider that you are not able to receive anymore (so after the second call of HAL_UART_Receive_IT), what is the content of the ISR Status register of your Uart instance ? Especially, could you have a look at ORE bit ?

If overrun error is detected, reception chain is blocked until ORE is cleared.

I already edited the post at the end. I was finally able to find the solution. the EIE bit was the impostor :D