【问题标题】:Arduino : Check byte array for chars one at a timeArduino:一次检查一个字符的字节数组
【发布时间】:2013-03-20 14:26:04
【问题描述】:

我使用发送一系列字节的程序通过串行与 Arduino 通信。

为了让 Arduino 意识到它正在接收消息而不是垃圾,我用字符 'S' 'T' 'A' 'R' 'T' 标记了我的字节数组的开头。在这之后最终将遵循一系列将分配给内部变量的字节(尚未实现)。

Arduino 必须按顺序读取每个字节并将其与字节数组进行比较,如果所有字节都以正确的顺序出现,它将继续程序的下一部分,否则它将丢弃当前字节并等待更多字节到了。

我试图以最有效和最易读的方式来实现它,而不是使用一系列嵌套的 if 语句。

到目前为止,我得到了:

byte inByte = 0;
byte handShake[] = {'S','T','A','R','T'};

void setup() {
  Serial.begin(9600);

}

void loop() 
{
  while (Serial.available()) 
{
  for (int x =0; x < sizeof(handShake) ; x++)
    {
    inByte = Serial.read();
    Serial.println(x);
    if (inByte == handShake[x]) 
     {
        if (x == (sizeof(handShake)-1)) {setArduino();}  
      }
       else break;
   }
  }
}


void setArduino () {
  Serial.println("Ready To Set Parameters");
}

然而,这似乎没有超过第二个字节,我不知道为什么。

【问题讨论】:

  • 更常见的是简单地使用控制字符(例如:*)来表示消息的结束。除非您的设置做一些不寻常的事情,否则接收垃圾序列字符的可能性很小。
  • 我在连接时似乎确实收到了一些垃圾字符,所以这样我可以确定这是正确的信息。仅在一个字符上触发读取的概率为 1/256 或 0.3%,但每秒读取 100 次的概率为每秒 30% 的错误机会,而使用我的 5 个字符为 1/1099511627776 或 9x10^-11% 读取每秒 100 次是每秒 9X10-9%,我可以忍受。
  • 只是尝试使用带和大括号的方法,我还将在数据包的末尾添加错误检查字节以防止不良数据。是的,这可能有点过头了,但为了练习,想象一下这个微控制器正在运行一个基本系统,你真的不希望错误的信息通过。
  • 我发现如果我添加延迟(5),它会起作用;在第二个 if 语句之后允许下一个字节到达,但是我认为这是最好的方法。我真的需要程序在第一个字节之后暂停并等待下一个字节,而不是等待任意长度的时间。有什么想法吗?

标签: serial-port bytearray arduino handshake


【解决方案1】:

解决了:

答案如下:

byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};

void setup() {
  Serial.begin(9600);

}

void loop() 
{
  while (Serial.available()) 
  {
  for (int x =0; x < sizeof(handShake) ; x++)
    {
    inByte = Serial.read();
    Serial.println(x);
    if (inByte == handShake[x]) 
      {
       if (x == (sizeof(handShake)-1)) {setArduino();}  
       while(!Serial.available()) {delay(1);}
      }
       else {break;}
    }
  }
}


void setArduino () {
  Serial.println("Ready To Set Parameters");
}

这可能不是最有效的方法,但我目前看不出有什么问题。

【讨论】:

  • 好的,这有一个问题:如果它只收到“ST”,它将无限期地等待下一个字节,而不是执行 loop() 中的其他代码,最终将包含引脚检查。所以这不好。
  • 你确定吗?我手头没有 Arduino 来检查这个,但我不认为它会阻塞。
【解决方案2】:

更好的答案:这允许循环的其余部分在等待消息完成时进行迭代,如果未收到完整的握手消息,则计数器将重置。

byte inByte = 0;
char handShake[] = {'S','T','A','R','T'};
int messageIndex = 0;

void setup() {
  Serial.begin(9600);

}

void loop() 
{
  while (Serial.available()) 
  {
    inByte = Serial.read();
    Serial.println(messageIndex);
    if (inByte == handShake[messageIndex]) 
      {
        messageIndex++;
        if (messageIndex == sizeof(handShake)) {messageIndex = 0; setArduino();}  
      }
       else {messageIndex=0;}
  }
// Other code while waiting for message to finish
Serial.println("tick");
}


void setArduino () {
  Serial.println("Ready To Set Parameters");
}

【讨论】:

    【解决方案3】:

    您可以尝试计算您的消息。 CRC 是旧的很好的解决方案。我使用它,它非常适合我。我不确定您使用的是哪种设备。

    //define
    const uint32_t Polynomial = 0xEDB88320;
    const uint16_t NumBytes = 256;
    uint8_t data[NumBytes];
    
    /// compute CRC32
    uint32_t crc32_bitwise(const void* data, uint16_t length, uint32_t previousCrc32 = 0)
    {
      uint32_t crc = ~previousCrc32; // same as previousCrc32 ^ 0xFFFFFFFF
      uint8_t* current = (uint8_t*) data;
    
      while (length--)
      {
        crc ^= *current++;
        for (uint8_t j = 0; j < 8; j++)
        {
          uint8_t lowestBit = crc & 1;
          crc >>= 1;
          if (lowestBit)
            crc ^= Polynomial;
        }
      }
      return ~crc; // same as crc ^ 0xFFFFFFFF
    }
    void setup() {
      // put your setup code here, to run once:    
    }
    
    void loop() {
      // put your main code here, to run repeatedly:    
    }
    

    当你需要计算CRC时

    uint32_t crc = crc32_bitwise(data_bytes, sizeof(data_bytes));

    data_bytes 是字节数组。

    然后你就可以得到byte data[x]中的所有设置或消息并计算CRC。然后你可以在消息中添加CRC并发送消息byte data[x+sizeof(CRC)]

    附:使用byte 而不是int。例如。 for(byte x =0; x&lt;sizeof(handShake); x++)

    【讨论】:

      猜你喜欢
      • 2014-02-15
      • 2016-04-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多