[英]Infinite loop due to Pointers on Arduino Due
我以Dan Royer的代码为基础在Arduino Mega 2560上实现了一个缓冲区。 代码在Mega上运行得非常好,但是我想使用Arduino Due(使用ARM而不是标准Atmel微处理器)的增强功能和强大功能。
在Due上,由于在到达缓冲区末端时不退出缓冲区内容,因此在处理缓冲区内容时,我总是陷入无限循环。 有谁知道为什么会这样? 您对如何防止这种情况有想法吗?
给出的命令将是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打印内存地址。 有人知道吗?
我发表评论以结束问题:
用ptr=strchr(ptr,' ')+1;
递增指针 是未定义的行为,因为strchr找不到返回NULL
的字符。
您应先检查strchr
return,然后再将其分配给ptr。
可能在Atmel平台上,地址NULL+1
处有一个0x00
,可以使您的代码正常工作。
另一个可能性(我在Arduino上非常strchr
)是,如果找不到char,Atmel库中的strchr
实现不会返回NULL
。 我看到了strchr
实现,在这种情况下,如果找不到char,则返回的值是字符串的最后一个char。
确保while循环之前的buffer
是有效字符串。 (也许arduino默认将值初始化为0-IDK。C不会,并且可能会导致无限循环并导致“ while循环永不退出”。)
char buffer[MAX_BUF];
// int sofar;
int sofar = 0; // Initialize to 0.
buffer[0] = 0; // Add
在while循环中,每次添加字符后都要添加一个空字符。 这应该特别重要;
找不到或缓冲区很长。 while
循环后不发布buffer
会发生什么。
if (sofar<MAX_BUF-1) {
buffer[sofar++] = c;
buffer[sofar] = 0; // Add
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.