我使用Code of Dan Royer作为基础在Arduino Mega 2560上实现了一个缓冲区。代码在Mega上完美运行,但我想使用Arduino Due的增强功能和功能(它使用ARM而不是标准的Atmel微处理器)。
On Due在处理缓冲区内容时总是进入无限循环,因为它在到达缓冲区末尾时不会退出。有谁知道为什么会这样?你对如何防止这种情况有什么想法吗?
给出的命令是GCodes,例如:“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()然后调用一个函数,在缓冲区中搜索特定字符并返回直接在该字符后面的float:
/**
* 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上运行得非常好,但是由于某些原因,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打印内存地址。
有谁知道什么?
答案 0 :(得分:0)
我发表评论以允许关闭问题:
使用ptr=strchr(ptr,' ')+1;
递增指针是未定义的行为,因为strchr找不到返回NULL
的char。
您应该先检查strchr
返回,然后再将其分配给ptr。
可能在Atmel平台上,0x00
地址为NULL+1
,可使您的代码运行良好。
另一种可能性(我在Arduino上非常棒),如果找不到char,Atmel库中的strchr
实现不会返回NULL
。我看到strchr
实现,如果找不到char,返回的值是字符串的最后一个字符。
答案 1 :(得分:0)
确保buffer
是while循环之前的有效字符串。 (也许arduino默认情况下将值初始化为0 - IDK。C不会,并且可能导致无限循环并导致“while循环永远不会退出”。)
char buffer[MAX_BUF];
// int sofar;
int sofar = 0; // Initialize to 0.
buffer[0] = 0; // Add
在while循环期间,每次附加字符后附加一个空字符。如果找不到;
或缓冲区很长,这一点尤为重要。未发布buffer
循环后while
发生的情况。
if (sofar<MAX_BUF-1) {
buffer[sofar++] = c;
buffer[sofar] = 0; // Add
}