STM32F4 UART HAL驱动程序'将字符串保存在变量缓冲区中'

Posted

技术标签:

【中文标题】STM32F4 UART HAL驱动程序\'将字符串保存在变量缓冲区中\'【英文标题】:STM32F4 UART HAL driver 'save string in variable buffer'STM32F4 UART HAL驱动程序'将字符串保存在变量缓冲区中' 【发布时间】:2021-07-17 03:21:14 【问题描述】:

我正在为 STM32F4 编写软件。 STM32 需要通过 UART 拉入一个字符串。该字符串的长度可变,并且每秒从一个传感器输入。字符串存储在一个固定的缓冲区中,因此缓冲区内容不断变化。

传入的字符串如下所示:"A12941;P2507;T2150;C21;E0;"

UART的设置:

波特率:19200 字长:8Bits 奇偶校验:无 停止投标:1 过采样:16 个样本 全局中断:启用 无 DMA 设置

main.c函数中使用的部分代码:

uint8_t UART3_rxBuffer[25];

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

    HAL_UART_Receive_IT(&huart3, UART3_rxBuffer, 25); //restart interrupt reception mode

    
int main(void)
  
  HAL_UART_Receive_IT (&huart3, UART3_rxBuffer,25);

  while (1)
  
  

stm32f4xx_it.c中的部分代码

void USART3_IRQHandler(void)

  /* USER CODE BEGIN USART3_IRQn 0 */
  /* USER CODE END USART3_IRQn 0 */
  HAL_UART_IRQHandler(&huart3);
  /* USER CODE BEGIN USART3_IRQn 1 */
  /* USER CODE END USART3_IRQn 1 */

以这种方式用可变字符串填充缓冲区确实有效,但由于缓冲区不断被补充,因此很难提取字符串的开头和结尾。例如,缓冲区可能如下所示: [0]'E' [1]'0' [2]'/n' [3]'A' [4]'1' [5]'2' [6]'9' [7]'4' [ 8]'1' [9]';' [10]'P'等...... 但我想要一个从“A”开始的缓冲区。

我的问题是,如何正确处理 uart 上的传入字符串,以便我只有字符串“A12941;P2507;T2150;C21;E0;”?

提前致谢!!

【问题讨论】:

【参考方案1】:

我可以看到三种可能性:

    在中断中完成所有处理。当您到达可变长度消息的末尾时,请执行您需要对信息执行的所有操作,然后更改位置变量以从头开始填充缓冲区。

    并行使用(至少)两个缓冲区。当您在中断上下文中检测到可变长度消息的结尾时,然后开始从位置 0 填充不同的缓冲区并向主上下文发出信号,表明前一个缓冲区已准备好进行处理。

    串联使用两个缓冲区。让中断以循环方式填充环形缓冲区,不注意消息何时结束。在主上下文中从上一条消息的末尾扫描,看看您是否还有整条消息。如果这样做,则将其复制到另一个缓冲区中,使其从缓冲区的开头开始。记录下一次在环形缓冲区中完成的位置,然后在线性缓冲区上进行处理。

选项 1 仅适用于您可以在少于发送器发送下一或两个字节的时间内完成所有处理的情况。其他两个选项使用更多内存并且实现起来有点复杂。只要您足够频繁地轮询新消息,就可以使用循环模式 DMA 实现选项 3,从而避免需要中断。如果您的主上下文可能不够频繁地轮询,选项 2 允许将多条消息排队。

【讨论】:

感谢您回答我的问题。好的,那么选项 3 对我来说似乎是最好的。你碰巧有这方面的示例代码吗?【参考方案2】:

我想分享一个与您的问题相关的示例代码。然而,这并不是您真正想要的。您可以根据需要编辑此代码 sn-p。如果我没记错的话,您也可以根据选项 3 进行编辑。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)

    if (huart->Instance == USART2) 
    HAL_UART_Receive_IT(&huart2,&rData,1);

    rxBuffer[pos++] = rData;
    if (rData == '\n') 
        pos = 0;
    

在开始之前,在 main 函数中,在 while 循环之前,您应该使用“HAL_UART_Receive_IT(&huart2,&rData,1);”启用一个字节的中断。如果您的传入数据有像'\n'这样的限制器,那么您可以保存每个帧可能具有不同长度的整个数据。

如果您希望数据框以某个特定字符开头,则可以等待保存数据,直到获得该字符。在这种情况下,您可以通过将 '\n' 更改为您的字符来编辑此代码,并且在获得该字符后,您应该开始将以下数据保存到缓冲区内。

【讨论】:

以上是关于STM32F4 UART HAL驱动程序'将字符串保存在变量缓冲区中'的主要内容,如果未能解决你的问题,请参考以下文章

带有 HAL 库的 STM32F4-Discovery (STM32F429ZIT6) 上的 RS232 (UART)?

STM32F4 HAL库开发 -- 串口

STM32F4 HAL库开发 -- 串口

STM32F4 HAL库开发 -- 串口

[STM32F4裸机]STM32F4HAL库开发

在 Flash 中为用户数据分配内存(STM32F4 HAL)