Search code examples
stm32uart

HAL_UART_Receive_IT will only run once


I am sending some data to ESP8266 over UART1. The ESP8266 receives the data and sends a code '10001' back to STM32. The problem is that I receive it only once, while the STM32 keeps sending the data and ESP8266 is also receiving the data correctly but the data that the ESP8266 sends to STM32 is only received one time. Here is my code :

int main(void)
{

  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_SPI2_Init();

  HAL_UART_Receive_IT(&huart1, &rx_data, 5);

  while (1)
  {
      HAL_Delay(1000);
      card_data_string[0] = 0x45;
      card_data_string[1] = 0x46;
      card_data_string[2] = 0x47;
      card_data_string[3] = 0x48;
      card_data_string[4] = '\0';
      HAL_UART_Transmit(&huart1, (uint8_t*)card_data_string, strlen(card_data_string), 1000);
}
}


static void MX_USART1_UART_Init(void)
{
  huart1.Instance = USART1;
  huart1.Init.BaudRate = 74880;
  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;
  if (HAL_UART_Init(&huart1) != HAL_OK)
  {
    Error_Handler();
  }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart == &huart1) {
    printf("Received : %s \n", rx_data);

        // Enable reception for the next character
    HAL_UART_Receive_IT(&huart1, &rx_data, 5);
    }
   
}

I have checked on the ESP end and the transmit function returns a non-zero response so there is no problem there, it will always send 5 bytes to the STM32. What can I do about this?


Solution

  • Your callback function is called from an interrupt service routine (ISR). It is rarely a good idea to call complex functions from inside an ISR. An ISR should do whatever it needs to do as quickly as possible and return.

    More normal would be to set a flag, give a semaphore, put something in a message queue etc, then handle the complex processing from non-interrupt context.

    If you remove the printf() and just (say) increment a counter it should work.

    static volatile uint32_t int_ctr;
    
    void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
        if (huart == &huart1) {
            ++int_ctr;
    
            // Enable reception for the next character
            HAL_UART_Receive_IT(&huart1, &rx_data, 5);
        }
    }