В общем не хочу использовать библиотеку, пишу свой парсер на текущий момент имеется: Код (C++): int cnt = 0; int heshtemp,heshfix = 0; char nmea[82]; void loop() { if(gps.available()) //проверяю буфер порта ЖПС { char ch=gps.read(); // Serial.print(ch); if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,0,sizeof(nmea)); } /*начало строки/**/ else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp ; heshtemp ^= ch; } if(ch == '\n'){//конец строки - разбор данных if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/ Serial.println(nmea); Serial.print("hesh:"); Serial.println(heshfix,HEX); if(nmea[sizeof(nmea)-3]==heshfix){ /*проверка хеша строки/**/Serial.println("hesh VIN!!!!"); /******************** разбор данных на блоки ******************/ /* GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62 */ /**************************************************************/ } } } } } по сути все данные в массиве чар теперь надо его разобрать на части, но чтото не хочется использовать "строковые" функции типа подстроки... отсюда 2 вопроса: 1) что можно оптимизировать в данном коде для его облегчения в плане скорости выполнения и потребляемой памяти? 2) как более правильно брать из массива символов их часть?
да чтото совсем запутал всё sizeof(nmea) дает размер массива = 82 а не фактическому числу заполненных ячеек его
Код (C++): char tmp[5];itoa(heshfix,tmp,16); Serial.println(tmp); if(atoi(nmea+67)==atoi(tmp)){ понимаю, что чтото перемудрил, но так работает --- на остальные вопросы поможете?
вот что вышло: Код (C++): if(gps.available()) //проверяю буфер порта ЖПС { char ch=gps.read(); // Serial.print(ch); if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,0,sizeof(nmea)); } /*начало строки/**/ else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp; heshtemp ^= ch; } if(ch == '\n'){//конец строки - разбор данных if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/ Serial.print(nmea); //Serial.print("hesh:"); Serial.println(heshfix,HEX); char tmp[5];itoa(heshfix,tmp,16); // Serial.println(tmp); if(atoi(nmea+67)==atoi(tmp)){ /*проверка хеша строки/**///Serial.println("hesh VIN!!!!"); /******************** разбор данных на блоки ******************/ /* 0 6 17 19 29 31 42 44 50 56 62 /* GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62 */ memset(data,0,sizeof(data)); for(int i=0; i<=4; i++) {data[i]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=6; i<=15; i++) {data[i-6]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=17; i<=17; i++) {data[i-17]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=19; i<=27; i++) {data[i-19]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=29; i<=29; i++) {data[i-29]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=31; i<=40; i++) {data[i-31]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=42; i<=42; i++) {data[i-42]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=44; i<=48; i++) {data[i-44]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=50; i<=54; i++) {data[i-50]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=56; i<=61; i++) {data[i-56]=nmea[i];} Serial.print("parse:"); Serial.println(data); /**************************************************************/ } } } } результат в общем результат меня устраивает, но код явно перегружен и совсем нубский Подскажите как можно его оптимизировать? а то почти 20мс занимает исполнение кода
if(atoi(nmea+67)==atoi(tmp)){ Там не обязано всегда быть 67, там может быть и другое смещение, так что так делать стопудово нельзя. Вообще, проблема-то выеденного яйца не стоит - разодрать строку по разделителю-запятой. Вот здесь это делается в три строки, только не по запятой и по пробелу. Разберись с поменяй на запятую.
спс это то понятно я просто делаю под определенный ЖПС модуль - в нем отдается фиксированная длинна строки, поэтому указал так но для не выполнения разбора строки . если она не верная, надо вначале проверить хош строки - 2 последних символа но какбрать 2 последних не пустых (не 0) символа из массива чар я не нашел пока простого решения
Не бывает таких модулей. См. протокол. Там может не быть какой-то цифири или ещё чего. Длина строки в протоколе NMEA не фиксирована.
да, по стандарту не фиктирована но это не значит, что какой - либо производитель не сделает фиксированным какую-либо строку в конкретном моем случае на имеющемся у меня примнике, именно нужный мне набор данных имеет фиксированную длину ----- можно сделать так strlen(nmea)-4 но это +150кб кода....всего из за одного действия
Как ты собираешься это делать не прочитав всю строку? Ты знаешь чему равны эти последние два символа? Или "в твоём мире строк фиксированной длины" они всегда одинаковые? Эти два символа - шестнадцатиричное число равное XOR-сумме всех символов строки. Т.е. тебе по любому надо прочитать сначала всю строку, просуммировать её, а потом уж сравнивать полученную сумму с этими символами.
я же код приложил - там читаются все приходящие символы и сразу ссумируются просто при приходе символа '$' идет обнуление (это начало строки), а при нахождении '*' хор сумма запоминается в отдельную переменную
Код (C++): #define gps Serial1 int cnt = 0; //int spd,crs; //double lat,lng,latp,lngp; //int year, month, day, hour, minute, second; //String date,time; //bool gps_valid; //long dist,dist_o = 0; //путь int heshtemp,heshfix = 0; /*************************************/ char nmea[83]; //буфер строки nmea сообщения char data[12]; //буфер подстрок /*************************************/ void setup() { Serial.begin(115200); gps.begin(9600); Serial.println("-- start --"); } void loop() { // Serial.print("start:");Serial.println(millis()); if(gps.available()) //проверяю буфер порта ЖПС { char ch=gps.read(); // Serial.print(ch); if(ch == '$') { cnt = 0; heshtemp = 0; memset(nmea,"\0",sizeof(nmea)); } /*начало строки/**/ else { nmea[cnt++] = ch; /* сбор буфера символов /**/ if(ch == '*')heshfix=heshtemp; heshtemp ^= ch; } if(ch == '\n'){//конец строки - разбор данных if(strncmp(nmea,"GPRMC",5)==0){ /*ищем нужный блок по заголовку/**/ Serial.print(nmea); //Serial.print("hesh:"); Serial.println(heshfix,HEX); char tmp[5];itoa(heshfix,tmp,16); // Serial.println(tmp); if(atoi(nmea+(strlen(nmea)-4))==atoi(tmp)){ /*проверка хеша строки/**///Serial.println("hesh VIN!!!!"); /******************** разбор данных на блоки ******************/ /* 0 6 17 19 29 31 42 44 50 56 62 /* GPRMC,080725.447,A,5432.3355,N,03618.1771,E,000.0,201.2,030418,,,A*62 */ memset(data,0,sizeof(data)); for(int i=0; i<=4; i++) {data[i]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=6; i<=11; i++) {data[i-6]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=17; i<=17; i++) {data[i-17]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=19; i<=27; i++) {data[i-19]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=29; i<=29; i++) {data[i-29]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=31; i<=40; i++) {data[i-31]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=42; i<=42; i++) {data[i-42]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=44; i<=48; i++) {data[i-44]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=50; i<=54; i++) {data[i-50]=nmea[i];} Serial.print("parse:"); Serial.println(data); memset(data,0,sizeof(data)); for(int i=56; i<=61; i++) {data[i-56]=nmea[i];} Serial.print("parse:"); Serial.println(data); /**************************************************************/ } } } } //Serial.print("stop:");Serial.println(millis()); } /***************************************************************************************************/ /*double distance_between (double lat1, double long1, double lat2, double long2) { // returns distance in meters between two positions, both specified // as signed decimal-degrees latitude and longitude. Uses great-circle // distance computation for hypothetical sphere of radius 6372795 meters. // Because Earth is no exact sphere, rounding errors may be up to 0.5%. // Courtesy of Maarten Lamers double delta = radians(long1-long2); double sdlong = sin(delta); double cdlong = cos(delta); lat1 = radians(lat1); lat2 = radians(lat2); double slat1 = sin(lat1); double clat1 = cos(lat1); double slat2 = sin(lat2); double clat2 = cos(lat2); delta = (clat1 * slat2) - (slat1 * clat2 * cdlong); delta = sq(delta); delta += sq(clat2 * sdlong); delta = sqrt(delta); double denom = (slat1 * slat2) + (clat1 * clat2 * cdlong); delta = atan2(delta, denom); return delta * 6372795; //6367445; //6372795; } /* void gps_info(){ // if (dist==0){ Serial.print("."); // }else{ Serial.println(""); Serial.print("GPS Valid SIGNAL!"); Serial.print(" "); Serial.print("Tim: "); Serial.print(time); Serial.print(" "); Serial.print("Lat: "); Serial.print(lat,6); Serial.print(" "); Serial.print("Lon: "); Serial.print(lng,6); Serial.print(" "); Serial.print("spd: "); Serial.print(spd,4); Serial.print(" "); Serial.print("crs: "); Serial.print(crs); Serial.print(" "); Serial.print("dist: "); Serial.print(dist); Serial.print(" "); Serial.print("Dat: "); Serial.print(date); Serial.print(" "); Serial.println("------------"); // } }*/ результат