uart - STM32F4 UART HAL 驱动程序'将字符串保存在变量缓冲区中'
问题描述
我正在为 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 仅适用于您可以在少于发送器发送下一或两个字节的时间内完成所有处理的情况。其他两个选项使用更多的内存并且实现起来有点复杂。只要您足够频繁地轮询新消息,就可以使用循环模式 DMA 实现选项 3,从而避免需要中断。如果您的主上下文可能没有足够频繁地轮询,选项 2 允许将多条消息排队。
推荐阅读
- python - 循环集成,循环可以三重嵌套吗?
- symfony - 交响乐:
在树枝文件中的字段之间添加 - c# - 如何对不同的 API 请求使用相同的属性
- java - 我已升级到 gradle 7.2,现在我的项目遇到错误
- python - 如何基于包含列名的列表创建数据框?
- c - 在不分配内存的情况下为指针赋值(C)?
- python - 冲突:被其他 getUpdates 请求终止;确保只有一个机器人实例正在运行
- rust - 为什么 mpsc::Sender#send 和 mpsc::Receiver#recv 没有被标记为 mut?
- javascript - 弹出通知面板框不在右侧
- elasticsearch - 嵌套弹性搜索文档上的不同值