0

我使用 Dan Royer 的代码作为基础在 Arduino Mega 2560 上实现了一个缓冲区。代码在 Mega 上运行得非常好,但我想使用 Arduino Due 的增强功能和功能(它使用 ARM 而不是标准的 Atmel 微处理器)。

在到期时,我总是在处理缓冲区内容时进入无限循环,因为到达缓冲区末尾时它不会退出。有谁知道为什么会发生这种情况?您对如何防止这种情况有想法吗?

给出的命令将是 GCode,例如:“G01 X20.5 Y30;”

这是缓冲区的填充方式:

char buffer[MAX_BUF];  // where we store the message until we get a ';'
int sofar;  // how much is in the buffer

while(Serial.available() > 0) {  // if something is available
  char c=Serial.read();  // get it
  if(sofar<MAX_BUF-1) buffer[sofar++]=c;  // store it
  if(c==';') {
    // entire message received
    // we got a message and it ends with a semicolon
    buffer[sofar]=0;  // end the buffer so string functions work right
    processCommand();  // do something with the command
  }

然后 processCommand() 调用一个函数,该函数在缓冲区中搜索特定字符并返回该字符正后方的浮点数:

/**
 * Look for character /code/ in the buffer and read the float that immediately follows it.
 * @return the value found.  If nothing is found, /val/ is returned.
 * @input code the character to look for.
 * @input val the return value if /code/ is not found.
 **/
float parsenumber(char code,float val) {
  char *ptr=buffer;
  while(ptr && *ptr && ptr<buffer+sofar) {
    if(*ptr==code) { // if /code/ is found
      return atof(ptr+1); // return the float behind it
    }
    ptr=strchr(ptr,' ')+1; // else increment pointer to next char after a space
  }
  return val; // if the end of the buffer is reached, return the default value
} 

现在,这段代码在 Arduino Mega 上运行良好,但在 Due 上,由于某种原因,while 循环永远不会退出。

这是它在 Mega 上的工作方式:

GCode: G1;
Parsenumber: code:F val:288.46
####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 0.00
String at ptr: 
String at buffer end: 
#####
End of Parse: return 288.46

但这就是到期时的情况:

GCode: G1;
Parsenumber: code:F val:288.46
#####
ASCII Code at ptr: 71.00
String at ptr: G1;
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 8.00
String at ptr: 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 128.00
String at ptr: € q 
String at buffer end: 
#####
ptr incremented
ASCII Code at ptr: 113.00
String at ptr: q 
String at buffer end: 
#####

等等...

因此,在我看来,退出条件ptr<buffer+sofar从未得到满足。不幸的是,我无法用 Arduino 打印内存地址。有人知道吗?

4

2 回答 2

0

我发表评论以允许关闭问题:

递增指针ptr=strchr(ptr,' ')+1;是未定义的行为,因为 strchr 找不到它返回的字符NULL

strchr在将其分配给 ptr 之前,您应该检查return。

可能在 Atmel 平台上,有一个0x00at 地址NULL+1可以使您的代码运行良好。

另一种可能性(我对 Arduino 非常陌生)是,如果找不到 char strchr,Atmel 库中的实现不会返回。NULL我看到了strchr实现,如果找不到字符,则返回值是字符串的最后一个字符。

于 2015-07-16T12:06:05.117 回答
0

Insurebuffer是 while 循环之前的有效字符串。(也许arduino默认将值初始化为0 - IDK。C不会,并且可能导致无限循环并导致“while循环永远不会退出”。)

char buffer[MAX_BUF];
// int sofar;
int sofar = 0;  // Initialize to 0. 

buffer[0] = 0;  // Add 

在 while 循环期间,每次追加一个字符后追加一个空字符。;如果找不到a 或缓冲区很长,这一点尤其重要。未发布循环buffer后发生的情况。while

if (sofar<MAX_BUF-1) {
  buffer[sofar++] = c;
  buffer[sofar] = 0; // Add
 }
于 2015-07-16T17:28:26.463 回答