缓冲 UART RX 传入数据的最佳方式是什么?

which is the best way to buffering UART RX incoming data?

我正在使用连接到我的微控制器的 GSM 调制解调器来执行 send/receive AT 命令,而且我正在使用 MQTT 执行与远程服务器的连接。

经过一些研究,我制作了自己的 UART AT 命令解析器实现来接收和发送命令,它几乎一直工作正常,但我想要质量更好的代码,我认为我实现它的方式可能是有点粗糙

我在下面的代码中添加了一个模拟 "UART" 以便更好地理解我在做什么,它不能 100% 正常工作因为是一个模拟

我的问题是:如何改进下面的代码?使用 UART 接收传入数据并创建自己的缓冲区的最佳做法是什么?

代码

 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>

 static void at_wait_msg(char text);
 static char _rx_data[512];
 static uint16_t _rx_index = 0;

 enum messagetype
 {
     CommandReceived = 0,
     Buffering,
     ReceivingMQTT
 };
 messagetype type;

 int main()
 {
     char text[] = "\nAT\nOK\nAT\n0...readertesttagsample1000"; //example data getting from UART1
     //0...readertesttagsample1000(hex format for MQTT 30 18 00 09 72 65 61 64 65 72 74 73 74 74 61 67 73 61 6D 70 6C 65 31 30 30 30
     //pub:30
     //total len 24
     //topic len 9
     //data the remaining bytes
     for (int i = 0; i < strlen(text) + 1; i++)
         at_wait_msg(text[i]); //to simulate getting data from UART1 byte per byte
     return 0;
 }

 static void at_wait_msg(char text)
 {
     if (text == 0x0A)
     {
         type =CommandReceived;
     }

     if (text != 0x0A && type == Buffering)
     {
         type = Buffering;
     }

     if (text == 0x30)
     {
         type = ReceivingMQTT;
     }

     switch (type)
     {
         case Buffering:
              _rx_data[_rx_index++] = text;
              break;

         case CommandReceived:
              printf(" buffer[%s]\r", _rx_data);
              memset(_rx_data, 0, _rx_index);   
              _rx_index = 0;
              type = Buffering;
              break;

         case ReceivingMQTT:
              printf(" buffer[%s]\r", _rx_data);
              memset(_rx_data, 0, _rx_index);   
              _rx_index = 0;
              type = Buffering;
              break;
     }  
 }

实现循环缓冲区 循环缓冲区、循环队列、循环缓冲区或环形缓冲区是一种数据结构,它使用单个固定大小的缓冲区,就好像它是端到端连接的一样。这种结构很容易用于缓冲数据流。

那是来自维基百科。如何实施?您需要一个指向队列头的指针或索引,另一个指向队列尾部。您还可以跟踪队列的长度和头部或尾部。然后头部或尾部离开缓冲区,它更改为它的开头