Arduino 1 没有正确读取串口监视器的字符串

Arduino 1 not reading correctly the string from Serial Monitor

Arduino Uno 上的串行监视器有问题。

基本上我想在串口监视器上写一些命令,读取字符串并根据字符串做一些事情。

问题如下:假设我在串行监视器中键入命令 'read 4',有时字符串被正确读取,有时它被读取为:'ead 4',缺少第一个字符。 我什至在串行监视器的两个读数之间设置了延迟。有人有解释吗?

为了完整性,我 post 我的代码(基本上是 reads/writes from/to EEPROM:例如 'read 5' 将读取 EEPROM 的第 5 块,'write 4 5' 会将值 5 写入第 4 个内存块)。

#define MAX_STRING_LENGTH 14
#include <ctype.h>
#include <EEPROM.h>


//The function initializes the string to spaces
void initString(char* mystr, char strLength);

//The function returns true if it is a read operation, false otherwise
boolean isReadEEPROM(char *myStr, char strLength);

//The function returns true if it is a write operation, false otherwise
boolean isWriteEEPROM(char *myStr, char strLength);

//The function returns the EEPROM address from the string
unsigned int findAddress(char *myStr, char strLength);

char findValue(char *myStr, char strLength);

//Check the address range
boolean isAddressOk(unsigned int address);



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);


}

void loop() {

  char pos = 0; 
  bool newDataFound = false;
  char serialStr[MAX_STRING_LENGTH];
  unsigned int address = 0;
  char val = 0;
  while(Serial.available()){
    val = Serial.read();

  }
  val = 0;
  initString(&serialStr[0], (char) MAX_STRING_LENGTH);
  while(Serial.available() && pos < MAX_STRING_LENGTH){
    serialStr[pos] = Serial.read();
    pos ++;
    newDataFound = true;
    delay(200);
  }
  if (newDataFound){
    Serial.print("New Command found: ");
    Serial.println(serialStr);
    address = 0;
    address = findAddress(&serialStr[0], MAX_STRING_LENGTH);

    if (isReadEEPROM(&serialStr[0], MAX_STRING_LENGTH) && isAddressOk(address)){
      Serial.println("Reading from EEPROM");
      Serial.print("Address is ");
      Serial.println(address);
      val = EEPROM.read(address);
      Serial.print("Value is: ");
      Serial.println( (uint8_t) val );
      Serial.println(" ");

    }
    else if (isWriteEEPROM(&serialStr[0], MAX_STRING_LENGTH) && isAddressOk(address)){
      Serial.println("Writing to EEPROM");
      Serial.print("Address is ");
      Serial.println(address);
      Serial.println(" ");

      val = findValue(&serialStr[0], MAX_STRING_LENGTH);
      EEPROM.write(address, val);

    }
    else{
      if (!isAddressOk(address)){
        Serial.write(address);
        Serial.println("Address out of range");
        Serial.println("");
      }
      Serial.println("Not recognized operation\n");
    }

   delay(2000);
    }
}

void initString(char* mystr, char strLength){
  for(char ii=0; ii<strLength; ii++){
    (*mystr) = ' ';
    mystr++;
  } 
}

//The function returns true if it is a read operation, false otherwise
boolean isReadEEPROM(char *myStr, char strLength){
  //The string should contain first the 'read' operation
  char expected[] = "read";

  int ii =0;

  while (ii<4){
    if ( *(myStr + ii) !=  expected[ii]){
      return false;
      Serial.println("Not a Read Operation\n");
    }
    ii++;
  }
  return true;
  Serial.println("Read Operation");
}

//The function returns true if it is a write operation, false otherwise
boolean isWriteEEPROM(char *myStr, char strLength){
  //The string should contain first the 'read' operation
  char expected[] = "write";
  int ii =0;

  while (ii<5){
    if ( *(myStr + ii) !=  expected[ii]){
      return false;
    }
    ii++;
  }
  return true;
}

//The function returns the EEPROM address from the string
unsigned int findAddress(char *myStr, char strLength){
    unsigned int address;
    char tmpStr[strLength];
    char strAddress[] = "    ";
    int ii = 0;
  while(ii< strLength){
   tmpStr[ii] = *(myStr+ii);
   ii++;
  }
  Serial.print("The address found is: ");
  Serial.println(strAddress);
  ii= 0;

  if (isReadEEPROM(myStr, strLength)){
      while (ii<=4){
          if (isdigit(*(myStr + 5 + ii))){
            strAddress[ii] = *(myStr + 5 + ii);
          }
          else{
            break;
          }
          ii++;
      }
      address = atoi(strAddress);
  }

else if(isWriteEEPROM(myStr, strLength)){
        while (ii<=4){
          if (isdigit(*(myStr + 6 + ii))){
            strAddress[ii] = *(myStr + 6 + ii);
          }
          else{
            break;
          }
          ii++;
        }
        address = atoi(strAddress);
}

else{
  address = 0;
  //Serial.println("Address not available in function 'findAddress'");
}
 return address;
}

//The function returns the value to be written to the EEPROM from the string
char findValue(char *myStr, char strLength){
  char val;
  char tmpStr[strLength];
  char strVal[] = "   ";
  int ii, idx = 0;
  while(ii< strLength){
   tmpStr[ii] = *(myStr+ii);
   ii++;
  }
  ii= 0;
 // first found the first digits corresponding to the address
  while (ii<=4){
      if (isdigit(*(myStr + 6 + ii))){
        ;//strAddress[ii] = *(myStr + 6 + ii);
      }
      else{
        ii++;
        break;
      }
      ii++;
  }
  // now find the value
  while (ii<=4+3){
      Serial.println(*(myStr + 6 + ii));

      if (isdigit(*(myStr + 6 + ii))){
        strVal[idx] = *(myStr + 6 + ii);
      }
      else{
        break;
      }
      ii++;
      idx++;
  }          
 Serial.print("original string: ");
 Serial.println(tmpStr);
 Serial.print("Value found: ");
 Serial.println(strVal);
 val = (char)atoi(strVal);
 return val;
}

boolean isAddressOk(unsigned int address){
  if (address < 1024 && address >= 0){
    return true;
  }
  else{
    return false;
  }
}

这段代码:

char val=0;
while(Serial.available()){
  val = Serial.read();
}
val = 0;

正在消耗可能留在输入缓冲区中的任何字符。你也可以这样做:

while (Serial.avaialble())
  Serial.read();

下一个while循环不会等待整个命令。有时,它获得了 'r',然后没有及时获得 'ead...'。下次 loop 执行时它们会在那里,所以看起来 'r' 不见了。之前loop.

刚消耗完

通过 USB(从串行监视器 window)发送的内容可能会有奇怪的延迟。

要收集 完整的 行,您应该保存字符直到收到“\n”:

for (;;) {
  if (Serial.available()) {
    char c = Serial.read();
    if (c == '\n')
      break;
    if (pos < MAX_LINE_LENGTH) {
      serialStr[pos] = c;
      pos ++;
    }
    newDataFound = true;
  }
}

delay 调用完全没有必要,因为 for 循环会一直等待,直到接收到 '\n' 字符(确保在串行监视器下拉菜单中 'New Line' 或 'both NL & CR' 被选中)。那么您就知道您已经阅读了该行中的所有字符。