Вспомнил, что когда-то, что-то подобное делал на библиотеке Serial. Тогда только начинали учится с другом, вот это чудо, целиком - http://arduino.ru/forum/proekty/kontrol-peredachi-dannykh#comment-60939. Программа на удивление работает, работает иначе, чем Вам нужно, но там есть парсинг. Строки типа - ?NumberPacket(Номер пакета);XXX(Длина пакета);XXX(Тип операции);XXX(Параметр);XX(Тип данных);XXXXXXXXXX(Значение)!\n Залейте, и киньте строку ?0;14;7;0;1;1!, с передачей конца строки. Вот кусочки, той забавной программы. Получение данных. Код (C++): /// <summary> /// Получение данных с Serial порта /// </summary> void GetReceiveDataFromSerial() { // TODO: Добавить описание while(Serial.available()) { /// <summary> /// Переменная хранящая последний полученный char /// </summary> char incomingChar = (char)Serial.read(); if(incomingChar != newLine && incomingChar != clearChar) { receiveCharArrayCOM[indexCharInArray] = incomingChar; indexCharInArray++; } else { receiveCharArrayCOM[indexCharInArray] = '\0'; finishReceiveData = true; } } } Парсинг Код (C++): /// <summary> /// Парсинг полученных данных /// </summary> void ParseReceiveData() { // Завершено ли получения данных if (finishReceiveData) { // Получаем длину пакета receiveLength = strlen(receiveCharArrayCOM); // Пробегаемся по массиву хранящий пакет данных for (int i = 0; i < receiveLength; i++) { switch (receiveCharArrayCOM[i]) { case beginChar: // Получаем индекс символ начала пакета в пакете indexBeginCharInPackage = i; break; case endChar: // Получаем индекс символ конца пакета в пакете indexEndCharInPackage = i; break; case breakChar: // Получаем кол-во символов разделителя блоков данных в пакете breakCharCountInPackage++; break; default: // В зависимости от номера блока данных в пакете, заполняем переменные блоков switch (breakCharCountInPackage) { case 0: // Номер пакета в системе numberPacket += receiveCharArrayCOM[i]; break; case 1: // Длина пакета lenPacket += receiveCharArrayCOM[i]; break; case 2: // Тип операции пакета operationTypePacket += receiveCharArrayCOM[i]; break; case 3: // Тип операции пакета parametrPacket += receiveCharArrayCOM[i]; break; case 4: // Тип данных параметра пакета dataTypePacket += receiveCharArrayCOM[i]; break; case 5: // Значение параметра пакета valuePacket += receiveCharArrayCOM[i]; break; } break; } } if (breakCharCountInPackage != 5) { ErroreDataReceived("2",1); return; } // Номер пакета в системе, Int receiveNumberIntPacket = numberPacket.toInt(); // Номер пакета в системе, Int receiveLenIntPacket = lenPacket.toInt(); // Тип операции пакета, Int receiveOperationTypeIntPacket = operationTypePacket.toInt(); //SerialPrintLine(String(indexBeginCharInPackage)); //SerialPrintLine(String(breakCharCountInPackage)); //SerialPrintLine(String(indexEndCharInPackage)); //SerialPrintLine(String(receiveLength)); //SerialPrintLine(String(receiveLenIntPacket)); // Проверка корректности полученного пакета if (indexBeginCharInPackage == 0 && breakCharCountInPackage == 5 // Индекс символа начала пакета, должен быть равен 0, кол-во блоков данных должно быть 5 && indexEndCharInPackage == (receiveLength - 1) // Индекс символа конца пакета, должен быть равен значению блока длины пакета - 1 && receiveLenIntPacket == receiveLength // Реальная длина пакета должна быть равна значению блока длины пакета ) { // Определяем тип операции пакета switch(receiveOperationTypeIntPacket) { case OT_StartTPA: // Старт ТПА SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt()); // Устанавливаем состояние программы запущена beginWorkTPA = true; break; default: int globalNumberPacketAndOne = globalNumberPacket;//globalNumberPacket + 1; if (receiveOperationTypeIntPacket != OT_CheckReturnFromPC && receiveNumberIntPacket == globalNumberPacketAndOne) { SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt()); } else { if (receiveNumberIntPacket == globalNumberPacketAndOne) { switch(receiveOperationTypeIntPacket) { case OT_StopTPA: // Стоп ТПА SendConfirmationDataFromSerial(valuePacket, parametrPacket.toInt(), dataTypePacket.toInt()); //globalNumberPacket = 0; // Устанавливаем состояние программы остановлена beginWorkTPA = false; break; } } else { ErroreDataReceived("3",0); } } break; } } else { ErroreDataReceived("4",0); } } } Программа не оптимальна и сейчас бы и в голову не пришло делать на строках, но саму идею можно понять. Уже поздно, завтра если буду вопросы пишите, удачи!
Код (C++): #define led 13 String input_string = ""; const String Led_off = "switch led off"; const String Led_on = "switch led on"; void setup() { Serial.begin(9600); } void loop() { while (Serial.available() > 0) { char c = Serial.read(); if (c == '\n') { //считается, что команда завершена, если пришел символ перевода строки Serial.print("Input_string is: "); Serial.println(input_string); switch ( parse(input_string, Led_off, Led_on) ) { case 10: digitalWrite(led, LOW); Serial.println("Switching off is done"); break; case 11: digitalWrite(led, HIGH); Serial.println("Switching on is done"); break; case 9: Serial.println("invalid String"); break; } input_string = ""; } else { input_string += c; } } } byte parse(String input_string, const String Led_off, const String Led_on) { if (input_string.compareTo(Led_off) == 0) { return 10; } else if (input_string.compareTo(Led_on) == 0) { return 11; } else return 9; } Спойлер: COM Только вот светодиод почему-то не отрабатывает..
Я Вас не правильно понял, подумал, что надо именно парсить строку, разбирать команды, параметры команд и т.д. Извините за мои пять копеек, удачи!
Да нет, ваши пять копеек вполне в тему. Но пока что у меня не горит практическое использование этого кода, поэтому написанное выше - только прототип, который потом будет дорабатываться и дорабатываться.
Раз так, вот упрощенный вариант. Код (C++): // Скорость Serial порта. #define SERIAL_SPEED 115200 // Символ новой строки. #define NEW_LINE '\n' // Символ признак конца строки. #define CLEAR_CHAR '\0' // Символ начала пакета. #define beginChar '?' // Символ разделитель параметров пакета. #define breakChar ';' // Символ конца пакета. #define endChar '!' // Константа хранящая мак. размер массива хранящего пакет данных #define receiveSizeArrayCOM 40 // Массив хранящий полученый пакет данных. char receiveCharArrayCOM[receiveSizeArrayCOM]; // Переменная хранящая завершено ли получения данных. boolean finishReceiveData = false; // Переменная хранящая индекс текущего char в массиве хранящего пакет данных. int indexCharInArray; // Переменная хранящее номер символа начала пакета в пакете int indexBeginCharInPackage; // Переменная хранящее номер символа конца пакета в пакете int indexEndCharInPackage; // Кол-во символов разделителя блоков данных в пакете int breakCharCountInPackage; // Переменная хранящая ошибку длины полученных данных. boolean errorLengthReceiveData = false; // Массив хранящий команду. String receiveCommandCOM; // Массив хранящий аргумент команды. String receiveArgumentCommandCOM; /// <summary> /// Предварительная настройка. /// </summary> void setup () { // Настраиваем Serial. Serial.begin(SERIAL_SPEED); } /// <summary> /// Основной цикл. /// </summary> void loop() { // Получение данных с Serial порта GetReceiveDataFromSerial(); // Ошибка длинны данных. if (errorLengthReceiveData) { Serial.println("Error_0"); // Очистка переменных получения данных, после получения данных. ClearReceiveDataVariable(); // Обнуляем переменую errorLengthReceiveData. errorLengthReceiveData = false; } else if (finishReceiveData) { // Парсинг полученных данных. ParseReceiveData(); Serial.print("Command - '"); Serial.print(receiveCommandCOM); Serial.print("' Argument Command - '"); Serial.print(receiveArgumentCommandCOM); Serial.println("'"); // Очистка переменных получения данных, после получения данных. ClearReceiveDataVariable(); } } /// <summary> /// Получение данных с Serial порта /// </summary> void GetReceiveDataFromSerial() { // Крутимся в цикле, до тех пор пока есть данные для чтения. while(Serial.available()) { // Объявляем переменную и сохрянем 1 char нее. char incomingChar = (char)Serial.read(); // Проверяем, если пришел символ новой строки или символ конца строки. if(incomingChar != NEW_LINE && incomingChar != CLEAR_CHAR) { // Заполняем массив. receiveCharArrayCOM[indexCharInArray] = incomingChar; // Проверяем индекс массива. if ((indexCharInArray+1) < receiveSizeArrayCOM) { // Увеличеваем индекс массива. indexCharInArray++; } else { // Данных больше, чем можем вместить. // Очень коварная ситуация, если мы выдем за пределы массива, отладка будет очень тяжелая. errorLengthReceiveData = true; break; } } else { // Увеличеваем индекс массива. receiveCharArrayCOM[indexCharInArray] = '\0'; // Взводим флаг, данные получены. finishReceiveData = true; } } } /// </summary> /// Парсинг полученных данных. /// </summary> void ParseReceiveData() { // Переменная хранящее реальную длину пакета, проверка после получения. // Получаем длину пакета. int receiveLength = strlen(receiveCharArrayCOM); // Пробегаемся по массиву хранящий пакет данных for (int i = 0; i < receiveLength; i++) { switch (receiveCharArrayCOM[i]) { case beginChar: // Получаем индекс символ начала пакета в пакете indexBeginCharInPackage = i; // Идекс начального пакет не равен 0; if (indexBeginCharInPackage) { Serial.println("Error_1"); } break; case endChar: // Получаем индекс символ конца пакета в пакете indexEndCharInPackage = i; // Идекс конца пакета равен receiveLength. if (indexEndCharInPackage == receiveLength) { Serial.println("Error_2"); } break; case breakChar: // Получаем кол-во символов разделителя блоков данных в пакете breakCharCountInPackage++; // Разделителей больше одного. if (breakCharCountInPackage > 1) { Serial.println("Error_3"); } break; default: switch (breakCharCountInPackage) { case 0: // Команда. receiveCommandCOM += receiveCharArrayCOM[i]; break; case 1: // Аргумент команды. receiveArgumentCommandCOM += receiveCharArrayCOM[i]; break; } break; } } } /// </summary> /// Очистка переменных получения данных, после получения данных. /// </summary> void ClearReceiveDataVariable() { indexCharInArray = 0; memset(receiveCharArrayCOM,CLEAR_CHAR,receiveSizeArrayCOM); indexBeginCharInPackage = indexEndCharInPackage = breakCharCountInPackage = 0; receiveArgumentCommandCOM = receiveCommandCOM = ""; finishReceiveData = false; } Понимает команды типа: ?Команда;Аргумент команды! Пример: ?analogWrite;180! Вернет в Serial мониторе Вообще передача данных через Serial (UART), SPI и т.д., тема обширная и вариантов реализации очень много, со своими плюсами и минусами. На мой взгляд в идеале найти готовую библиотеку, в сети много вариантов, чем самому делать велосипед, в крайнем случае дописать ее. Вот они к примеру - http://playground.arduino.cc/Main/InterfacingWithHardware#Communication. Так я пришел к 3 варианту передачи данных по Serial (UART), взяв библиотеку от Multiwii, вот он - http://arduino.ru/forum/ishchu-ispo...a-podvodnogo-apparata-za-voznag#comment-93457. Правда пришлось его немного модернизировать. Его можно использовать если есть начальные познания в AVR и СИ.