Пойду переваривать... В очередной раз огромное спасибо. Могу сказать я и со strchr понаписал громздко.
по сравнению с Вашей реализацией.
И не смотря, что вторая реализация Ваша (без "лишних" функций) отдаленно напоминает мою, но
У меня просто нагромождение какое то, даже не смотря на попутные мои вычисления.
Для себя уяснил, что я плохо работаю с разыменованием указателей... меня это сильно путает... и путает.
Пойду тренироваться на кошечках ...
boolean prs(char * s, float * latlon) {
int i = 0; //счетчик
int adr[13]; // сюда мы запишем адреса разделителей ','
int checksum = 0; //вычисленная Контрольная сумма
int check = 0; // Контрольная сумма полученная из сообщением NMEA
int k = 0; //счетчик для записи адресов разделителей
while (s[++i] != '*') { //следим за началом контрольной суммы, она начинается после '*'
checksum ^= (int) s[i]; // считаем побитно хор контрольную сумму
if (s[i] == ',') {
adr[k++] = i; //записываем в массив адреса разделителей в исходном массиве
}
s[i] -= '0'; // переводим знаки в цифры
}
while (s[++i] != '\r') {
if (s[i] > 58) {
s[i] -= 55;
} else {
s[i] -= '0';
}
check = check * 0x10 + s[i]; //переводи в НЕХ к каждому следующий разряд прибавляем к предыдущему
}
/*проверка соответствия контрольных */
check = check - checksum; // если не ноль то сумма не совпала...
if (check != 0) {
ERROR_0 //контрольная сумма не верна
return false; //обработка ERROR
}
Да еще в прошлый раз для меня было не ясно зачем вводить такую конструкцию while((sizeof(nmeaStringParts) > nmeaStringPartNo) && *ptrCurrentChar){}
а не так?
С sizeof() я, конечно, наплутал - забыл на размер первого элемента поделить. Но в целом - это чтобы не вылезти за размеры массива указателей и не начать писать куда попало.
С подсчётом CRC у меня так вышло:
const char nmeaFieldSeparator = ',';
const char nmeaSignDataStart = '$';
const char nmeaSignDataEnd = '*';
const char nmeaSignFieldEnd = '\0';
const uint8_t gprmcFieldsNumber = 0x0E;
const uint8_t gprmcFieldNoLatitude = 0x03;
const uint8_t gprmcFieldNoLongitude = 0x05;
const uint8_t gprmcFieldNoCrc = 0x0D;
char nmeaString[] = "$GPRMC,214603.000,A,4634.54557,N,03047.50473,E,0.00,0.00,040617,,,A*6E";
void setup() {
char *ptrCurrentChar, *ptrPartStart;
char* nmeaStringParts[gprmcFieldsNumber];
uint8_t nmeaStringPartNo = 0x00, makeCRC = false, parsingDone, calculatedCRC = 0x00, recivedCRC;
Serial.begin(115200);
Serial.println("NMEA split and CRC calculating example\n");
ptrCurrentChar = ptrPartStart = nmeaString;
// nmeaString can have nothing data
parsingDone = (nmeaSignFieldEnd == *ptrCurrentChar);
// gprmcFieldsNumber => sizeof(nmeaStringParts) / sizeof(nmeaStringParts[0])
while (!parsingDone && (gprmcFieldsNumber > nmeaStringPartNo)) {
if (nmeaSignDataEnd == *ptrCurrentChar) {
// Stopping CRC calculating if '*' detected
makeCRC = false;
}
if (makeCRC) {
// Calculate CRC if allowed
calculatedCRC ^= *ptrCurrentChar;
}
if (nmeaSignDataStart == *ptrCurrentChar) {
// Starting CRC calculating if '$' detected
makeCRC = true;
}
parsingDone = (nmeaSignFieldEnd == *ptrCurrentChar);
if (nmeaFieldSeparator == *ptrCurrentChar || nmeaSignDataEnd == *ptrCurrentChar || parsingDone) {
// Taking chunk of the NMEA string when field separator, data end sign, or end of line was detected
*ptrCurrentChar = '\0';
Serial.print("No: "); Serial.print(nmeaStringPartNo);
Serial.print(",\tchunk: "); Serial.print(ptrPartStart);
nmeaStringParts[nmeaStringPartNo++] = ptrPartStart;
ptrPartStart = ptrCurrentChar + 1;
Serial.print(",\ttail: "); Serial.println(ptrPartStart);
}
ptrCurrentChar++;
}
for (uint8_t i = 0x00; nmeaStringPartNo > i; i++) {
Serial.print(i); Serial.print('\t'); Serial.println(nmeaStringParts[i]);
}
Serial.println();
Serial.print("CRC (recived): "); Serial.println(nmeaStringParts[gprmcFieldNoCrc]);
Serial.print("CRC (calculated): "); Serial.println(calculatedCRC, HEX);
recivedCRC = strtoul(nmeaStringParts[gprmcFieldNoCrc], NULL, 16);
Serial.print("NMEA CRC is "); Serial.println((recivedCRC == calculatedCRC) ? "OK" : "BAD");
float latitude = atof(nmeaStringParts[gprmcFieldNoLatitude]);
float longitude = atof(nmeaStringParts[gprmcFieldNoLongitude]);
Serial.print("latitude: "); Serial.println(latitude, 6);
Serial.print("longitude: "); Serial.println(longitude, 6);
}
void loop() {}
Конечно, в реале ASCIIZ строки не будет, наверное, и завершать цикл разбора придётся по другому терминатору. Надо будет подключить GPS от автомобильного видеорегистратора, посмотреть что там в реальности прёт и с какой скоростью.
если паметь не изменяет мне, NMEA 0183 3 версии 3, ограничивает строку 82 ли 83 симовола... так, что читать дальше смысла нет, значит идет мусор... в реали "детские модули" да и посерьезнее, очень любят зависать и слать мусор... Самое важное это '*' потом два занак контрольной суммы... '/0' может и не прилететь... А может '/0' слать когда не надо... Скоро прибудут из Китая GY-NEO6MV2 потому, что на работе, мои специ ругаются на меня... "Вы вот геодезист, вот и говорите нам, что делать... А програмированием занимаемся Мы", "Если Вы хотите, мы зделаем, оно хоть в космос полетит" "зачем вам ардуино? 32 хотя бы, с вашей математикой 64 ели ели справляются" А мне, не надо чего то конкретного. Я просто хочу своими руками, а не в теории... не по ГОСТам, и стандартам =)))
Завтра буду изучать, вашу программу... На работе в una, загружу... Мне нравится элегантность в Вашем кодинге =)
"раставить" указатели и "занулить" запятые - КРАСИВО, ЧЕРТ ВОЗЬМИ !!!
Пойду переваривать... В очередной раз огромное спасибо. Могу сказать я и со strchr понаписал громздко.
по сравнению с Вашей реализацией.
И не смотря, что вторая реализация Ваша (без "лишних" функций) отдаленно напоминает мою, но
У меня просто нагромождение какое то, даже не смотря на попутные мои вычисления.
Для себя уяснил, что я плохо работаю с разыменованием указателей... меня это сильно путает... и путает.
Пойду тренироваться на кошечках ...
Да еще в прошлый раз для меня было не ясно зачем вводить такую конструкцию
while
((
sizeof
(nmeaStringParts) > nmeaStringPartNo) && *ptrCurrentChar){}
а не так?
while
(
*ptrCurrentChar) {}
попозже сам допетрил...
С sizeof() я, конечно, наплутал - забыл на размер первого элемента поделить. Но в целом - это чтобы не вылезти за размеры массива указателей и не начать писать куда попало.
С подсчётом CRC у меня так вышло:
Конечно, в реале ASCIIZ строки не будет, наверное, и завершать цикл разбора придётся по другому терминатору. Надо будет подключить GPS от автомобильного видеорегистратора, посмотреть что там в реальности прёт и с какой скоростью.
если паметь не изменяет мне, NMEA 0183 3 версии 3, ограничивает строку 82 ли 83 симовола... так, что читать дальше смысла нет, значит идет мусор... в реали "детские модули" да и посерьезнее, очень любят зависать и слать мусор... Самое важное это '*' потом два занак контрольной суммы... '/0' может и не прилететь... А может '/0' слать когда не надо... Скоро прибудут из Китая GY-NEO6MV2 потому, что на работе, мои специ ругаются на меня... "Вы вот геодезист, вот и говорите нам, что делать... А програмированием занимаемся Мы", "Если Вы хотите, мы зделаем, оно хоть в космос полетит" "зачем вам ардуино? 32 хотя бы, с вашей математикой 64 ели ели справляются" А мне, не надо чего то конкретного. Я просто хочу своими руками, а не в теории... не по ГОСТам, и стандартам =)))
Завтра буду изучать, вашу программу... На работе в una, загружу... Мне нравится элегантность в Вашем кодинге =)
NMEA не терминирует конец строки 0. В конце будут CR&LF.
Получилось сделать как Вы говорили, но при помощи strtok таким образом:
вышло: