cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive_IT only receives the first element

stm32bero
Associate II

Hi, I'm trying to use HAL_UART_Receive_IT with a fixed size buffer, but only the first element changes its value.

I'm using CubeMX over NUCLEO-STM32F446RE

The only things I do:

main.c

I declare the buffer like this:

uint8_t rx_buffer[5];

The UART initilization:

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 = 115200;
  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;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */
 
  /* USER CODE END USART2_Init 2 */
 
}

and inside the main function, just before the while loop:

HAL_UART_Receive_IT(&huart2, rx_buffer, sizeof(rx_buffer));

stm32f4xx_it.c

I declare the extern variable:

extern uint8_t rx_buffer[5];

and the ISR:

void USART2_IRQHandler(void)
 
{
 
 /* USER CODE BEGIN USART2_IRQn 0 */
 
 
 
 /* USER CODE END USART2_IRQn 0 */
 
 HAL_UART_IRQHandler(&huart2);
 
 /* USER CODE BEGIN USART2_IRQn 1 */
 
 HAL_UART_Receive_IT(&huart2, rx_buffer, sizeof(rx_buffer));
 
 /* USER CODE END USART2_IRQn 1 */
 
}

stm32f4xx_hal_msp.c

void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  if(huart->Instance==USART2)
  {
  /* USER CODE BEGIN USART2_MspInit 0 */
 
  /* USER CODE END USART2_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_USART2_CLK_ENABLE();
  
    __HAL_RCC_GPIOA_CLK_ENABLE();
    /**USART2 GPIO Configuration    
    PA2     ------> USART2_TX
    PA3     ------> USART2_RX 
    */
    GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    /* USART2 interrupt Init */
    HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(USART2_IRQn);
  /* USER CODE BEGIN USART2_MspInit 1 */
 
  /* USER CODE END USART2_MspInit 1 */
  }
 
}

I'm using Docklight to transmit the characters 'abcde' but debugging and watching rx_buffer,

only the first element changes, 'a', the rest remains to '\0' and therefore HAL_UART_RxCpltCallback is never called, the ultimate objective.

What's wrong with my code? Thanks!

4 REPLIES 4
Piranha
Chief II

The HAL_UART_Receive_IT() in interrupt handler restarts the reception...

S.Ma
Principal

Don't use HAL function inside the IT.

Just read your incoming data byte, put in your buffer and increase the index for the next come back byte.

There should be some nucleo project uart examples in cube.

I've seen that if not in the interrupt handler, the ISR was called just the first time I transmit data because of the initial HAL_UART_Receive_IT of the main function and never again.

I guess HAL_UART_Receive_IT()  should be inside the callback, but the callback never gets called.

I think that makes sense but then I don't understand why HAL_UART_Receive_IT() needs the size of the buffer if I have to go byte by byte.

The problem also is that the IRQHandler is called just once, it changes the first element of the buffer and then nothing... How could I read the different incoming data with just one iteration?