由于Arduino到期指针的无限循环

时间:2015-07-16 10:02:56

标签: c pointers arduino arduino-due

我使用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打印内存地址。 有谁知道什么?

2 个答案:

答案 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
 }