Я реализовал буфер на Arduino Mega 2560, взяв за основу Code of Dan Royer. Код отлично работает на Mega, но я хотел использовать расширенные функции и мощность Arduino Due (в котором вместо стандартного микропроцессора Atmel используется ARM).
В Due я всегда попадаю в бесконечный цикл при обработке содержимого буфера из-за того, что он не выходит, когда достигается конец буфера. Кто-нибудь знает, почему это может произойти? И есть ли у вас идеи, как этого избежать?
Данными командами будут G-коды, такие как: «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 по какой-то причине никогда не завершается.
Вот как это работает на Меге:
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;
является поведением undefined, посколькуstrchr
не находитchar
, он возвращаетNULL
. - person LPs   schedule 16.07.2015if(ptr<buffer) break;
послеptr=strchr(ptr,' ')+1;
, и это действительно сработало. Похоже, как писали LP, чтоptr
действительно генерировало неопределенное поведение. Разорвав цикл, когдаptr
больше не было в пределахbuffer
, проблема может быть решена. - person Louis   schedule 16.07.2015