UART 接收中断检查数据结束

Posted

技术标签:

【中文标题】UART 接收中断检查数据结束【英文标题】:UART Receive Interrupt checking end of data 【发布时间】:2018-10-04 22:38:33 【问题描述】:

我想使用 RX 中断通过 UART 从我的 ESP2866 接收数据,因此我不需要轮询数据。

代码运行良好,我可以在调试时看到 rx_buffer 中的响应,但是如何检查我的 ESP 何时完成发送?

ESP 发送的最后一个字符是 \r\n,但它在传输过程中也会这样做几次,所以我不能真正依赖它。

我知道我应该以某种方式检查缓冲区中是否存在 '\0' 终止符,但处理程序会在收到最后一个字符时停止。所以在处理程序中检查 '\0' 不起作用。

这可能是我想念的一些简单的东西,但我希望有人能帮助我。

int main(void)

  /* USER CODE BEGIN 1 */
    char* msg = "AT+GMR\r\n";
  /* 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_USART2_UART_Init();
  MX_USART1_UART_Init();

  /* Initialize interrupts */
  MX_NVIC_Init();
  /* USER CODE BEGIN 2 */

    // Send AT+GMR to ESP module
    HAL_UART_Transmit(&huart1, (uint8_t *)msg, strlen(msg) + 1, HAL_MAX_DELAY); 

    // Receive character (1 byte)
    HAL_UART_Receive_IT(&huart1, &rx_data, 1);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */


  while (1)
  

  /* USER CODE END WHILE */
  /* USER CODE BEGIN 3 */

  
  /* USER CODE END 3 */



/**
  * @brief  Retargets the C library printf function to the USART.
  * @param  None
  * @retval None
  */
PUTCHAR_PROTOTYPE

  /* Place your implementation of fputc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
  HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, HAL_MAX_DELAY); 

  return ch;


GETCHAR_PROTOTYPE

  /* Place your implementation of fgetc here */
  /* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
    char ch;
    HAL_UART_Receive(&huart2,(uint8_t*)&ch,1, HAL_MAX_DELAY);
  return ch;


/**
  * @brief  Rx Transfer completed callback
  * @param  UartHandle: UART handle
  * @note   This example shows a simple way to report end of DMA Rx transfer, and 
  *         you can add your own implementation.
  * @retval None
  */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  
    if(huart->Instance == USART1)

        if(rx_index == 0)
            memset(&rx_buffer, 0, sizeof(rx_buffer));
        

        rx_buffer[rx_index] = rx_data;      

        if(rx_buffer[rx_index] == '\0')
            printf("%s", rx_buffer);
        

        rx_index++;

        // Receive next character (1 byte)
        HAL_UART_Receive_IT(&huart1, &rx_data, 1);

    
       

【问题讨论】:

如果您正在传输文本,您可以使用 EOT(值 4)来终止。 “我知道我应该以某种方式检查缓冲区是否有 '\0' 终止符,但处理程序会在收到最后一个字符时停止。”您必须传输'\0' @WeatherVane 更改 rx_buffer[rx_index] == 4 也不起作用。我也不能告诉 ESP 发送那个 '\0'? 我不明白为什么你不能发送最终的04。另一种方法是在收到换行符时处理输入。由于发布的代码不完整,因此不容易看到您在做什么。但是如果从中断处理程序中调用HAL_UART_RxCpltCallback,那么在其中使用printf 是一个非常糟糕的主意。通常,中断处理程序应缓冲传入的数据,并在准备好完整消息时为上层设置一个标志。如果您使用环形缓冲区,则中断可以在处理先前缓冲的输入时继续接收。 @WeatherVane 仅供参考:ESP 需要 AT 命令并为其输出固定格式的响应,因此无法添加 40。不幸的是,没有命令可以更改命令行终止字符。 :) @BenceKaulics 谢谢你,所以回到我的建议来回应换行符,也许重新组织代码。 【参考方案1】:

当您将size of 视为char* msg = "AT+GMR\r\n"; 时,它会将\0 视为一个字符。

因此您无需在Transmit 函数中添加+1

【讨论】:

你的回答错了,sizeof msg 只会给你指针的大小。如果要获取大小,则需要将其设为数组:char msg[] = "AT+GMR\r\n"; OP 的方式适用于两种变体,并且适用于作为函数参数给出的字符串。

以上是关于UART 接收中断检查数据结束的主要内容,如果未能解决你的问题,请参考以下文章

如何额在lwip在不嵌入系统的情况下使用串口中断接收数据

STM32F4 在中断时从UART接收数据的问题

STM8S单片机串口UART2接收中断一直在运行,出不来,怎么回事?

STM32 cube接收中断数据

AVR的UART接受中断问题,中断老是不能正常触发

novoton-usart使用