Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 读取串行端口速度更快_C_Arduino_Serial Port_Embedded_Usb - Fatal编程技术网

C 读取串行端口速度更快

C 读取串行端口速度更快,c,arduino,serial-port,embedded,usb,C,Arduino,Serial Port,Embedded,Usb,我有一个电脑软件,可以使用USB将RGB颜色代码发送到Arduino。当它们被缓慢地发送时,它工作得很好,但当每秒发送几十个时,它就会崩溃。我想发生的是Arduino串行缓冲区填充得太快,处理器无法按我读取的方式处理它 #define INPUT_SIZE 11 void loop() { if(Serial.available()) { char input[INPUT_SIZE + 1]; byte size = Serial.readBytes(input, INPU

我有一个电脑软件,可以使用USB将RGB颜色代码发送到Arduino。当它们被缓慢地发送时,它工作得很好,但当每秒发送几十个时,它就会崩溃。我想发生的是Arduino串行缓冲区填充得太快,处理器无法按我读取的方式处理它

#define INPUT_SIZE 11

void loop() {
  if(Serial.available()) {
    char input[INPUT_SIZE + 1];
    byte size = Serial.readBytes(input, INPUT_SIZE);
    input[size] = 0;

    int channelNumber = 0;

    char* channel = strtok(input, " ");
    while(channel != 0) {
      color[channelNumber] = atoi(channel);

      channel = strtok(0, " ");
      channelNumber++;
    }

    setColor(color);
  }
}

例如,计算机可能发送
255 0 123
,其中数字以空格分隔。如果发送间隔足够慢,或者缓冲区总是只填充一个颜色代码,例如
255
,它是11个字节(
INPUT\u SIZE
)。但是,如果颜色代码不是11字节长,并且立即发送第二个代码,则该代码仍然从串行缓冲区读取11字节,并开始组合颜色并将其弄乱。我如何避免这种情况,同时尽可能保持其效率?

首先,我同意@Thomas Padron McCarthy的观点。发送字符串而不是字节数组(11字节而不是3字节,解析过程也是如此)只会浪费资源。另一方面,您应该遵循的方法取决于您的发件人:

  • 它是周期性的还是非周期性的
  • 大小是否固定
如果是周期性的,您可以检查消息的时间段。如果没有,则需要在缓冲区已满之前检查消息。 如果您认为可打印编码不适合您在任何情况下,我都会在消息中添加校验和。假设您有固定大小的消息结构:

typedef struct MyMessage
{
    // unsigned char id; // id of a message maybe?
    unsigned char colors[3]; // or unsigned char r,g,b; //maybe
    unsigned char checksum; // more than one byte could be a more powerful checksum
};

unsigned char calcCheckSum(struct MyMessage msg)
{
    //...
}

unsigned int validateCheckSum(struct MyMessage msg)
{
    //...
    if(valid)
       return 1;
    else
       return 0;
}
现在,您应该以滑动窗口方式检查每4个字节(MyMessage的大小)是否有效:

 void findMessages( )
 {
     struct MyMessage* msg;
     byte size = Serial.readBytes(input, INPUT_SIZE);
     byte msgSize = sizeof(struct MyMessage);
     for(int i = 0; i+msgSize <= size; i++)
     {
         msg = (struct MyMessage*) input[i];
         if(validateCheckSum(msg))
         {// found a message
             processMessage(msg);
         }
         else
         {
             //discard this byte, it's a part of a corrupted msg (you are too late to process this one maybe)
         }
     }
 }
void findMessages()
{
结构MyMessage*msg;
字节大小=串行.readBytes(输入,输入大小);
字节msgSize=sizeof(struct MyMessage);

对于(int i=0;i+msgSize而言,这不是加快串行端口读取速度的问题,而是当输入数据具有可变长度时,不读取11个字符的固定块的问题

你告诉它一直读到收到11个字符或出现超时,但是如果第一组少于11个字符,第二组紧接着就没有超时,你将部分读第二组。你似乎理解这一点,所以我不确定你如何得出结论说“读得更快”会有所帮助

使用ASCII十进制空格分隔的三元组的现有数据编码,一种解决方案是一次读取一个字符,直到读取整个三元组,但是您可以更简单地使用Arduino
ReadBytesUntil()
函数:

#define INPUT_SIZE 3

void loop()
{
    if (Serial.available())
    {
        char rgb_str[3][INPUT_SIZE+1] = {{0},{0},{0}};

        Serial.readBytesUntil( " ", rgb_str[0], INPUT_SIZE );
        Serial.readBytesUntil( " ", rgb_str[1], INPUT_SIZE );
        Serial.readBytesUntil( " ", rgb_str[2], INPUT_SIZE );

        for( int channelNumber = 0; channelNumber < 3; channelNumber++)
        {
            color[channelNumber] = atoi(channel);
        }

        setColor(color);
    }
}
请注意,我没有测试上面的任何代码,并且在某些情况下,Arduino文档在返回值的描述方面是缺乏的。您可能需要对代码进行一些调整


上述两种方法都不能解决同步问题——即,当颜色值流化时,您如何知道RGB三元组的开始?您必须依赖于获取第一个字段值并在之后保持计数和同步——这很好,直到Arduino在数据流启动后启动,或者重置,或者PC进程以异步方式终止和重新启动。然而,这也是您最初的实现中的一个问题,因此可能需要在其他地方处理。

如果您真正想要的是更快的速度……这有点牵强

我能想到的满足您的需求并提供同步的最快方法是,为每种颜色发送一个字节,并以定义的方式更改奇偶校验位,假设您可以读取具有错误奇偶校验的字符的奇偶校验和字节值


您将不得不处理奇偶校验的变化,大多数字符将无法被人类读取,但这必须是发送三个字节数据的最快方式之一。

您指的是字节,而不是位。但是如果您要读取的数据并不总是11字节长,那么您不能仅读取11个字节,并期望一切正常。如果第一条消息比如说,“1233”,第二个是“1234”,输入中的数据将是“1231434”。在我看来,不可能知道它是指“1233”后接“1234”,还是指“1231”后接“1234”?你能改变格式吗?例如,将三个字节作为二进制字节发送,而不是转换为文本吗?谢谢@ThomasPadron McCarthy!我更改了计算机上的程序以发送十六进制颜色代码。现在我总是收到六个字节,然后需要转换回RGB。我不明白它是如何转换为六个字节的?你应该发送一个字节用于每个通道有三个。另外,使用一个struct将原始输入映射到格式化版本。请参阅下面的文章。Arduino串行类已经进行了缓冲和中断驱动,并且由于没有多线程,因此辅助缓冲区将没有任何用途。+1用于解决同步问题。我从未使用过或甚至从未见过和ar杜尼奥:)感谢您的更正。字符串更易于调试,如果性能不是关键因素,它们可能是更好的选择。@fuzzxl,我不同意您的观点,如果您不将文本作为消息发送。我从未见过发送字符数组而不是结构化消息是更好的选择。@fuzzxl:正在发送的数据“眼睛清晰”可能使调试更容易,但在这种情况下,这是错误的实际原因(试图像处理固定长度的可变长度数据一样处理可变长度数据)。这突出了Arduino的最大问题-没有具有片上调试支持的调试器。在调试器中查看字节变量将是微不足道的。在这种情况下,在Arduino端使用调试打印输出将比不必要地消耗通道带宽更好。如何以三个字节发送颜色?@MikkoP:R、G、B组件。一个字节可以表示0到255的值。您的串行通信需要配置为8个数据帧(正常情况下
void loop()
{
    if( Serial.available() )
    {
        for( int channelNumber = 0; channelNumber < 3; channelNumber++)
        {
            color[channelNumber] = Serial.Read() ;
        }

        setColor(color);
    }
}