kil00 0 28 декабря, 2011 Опубликовано 28 декабря, 2011 · Жалоба Здравствуйте! Надо ли преобразовывать как-то ASCII коды, которые получаю по USART, (типичная последовательность NMEA $GPZDA,102433.00,28,12,2011,,*6A, из которой мне нужны только 2-5 поля)? (я так понимаю, что не надо) Не подскажите более удачный алгоритм считывания символов с USARTa, кроме как перечисление if'ов? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Я 3 раза перечитал, но так и не понял сути вопроса. Надо ли преобразовывать как-то ASCII коды, которые получаю по USART Ну если начальство сказало, что надо, то преобразовывайте. Не подскажите более удачный алгоритм считывания символов с USARTa, кроме как перечисление if'ов? Более удачный алгоритм - считывать с юсарта без ифов. Я вот считываю и перечисления ифов нет. Делаю я это так: считываю байт, если приёмник не пуст, повторяю в цикле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
SSerge 4 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Повышаем градус абстракции! От GPS-модуля ведь приходят текстовые строки, не правда ли? Значит и принимаем их с UART посимвольно, собирая из символов строки. Когда строка полностью принята переходим к разбору той строки. Отдельные поля в строке, как видим отделяются друг от друга запятой. Поле может быть пустым либо содержать число (целое или float), либо некое имя. По науке этот этап называется лексическим анализом, а сами поля - лексемы. Множество терминальных символов (разделители лексем) состоит из запятой и конца строки. Следующий этап - синтаксический анализ. В этом случае он тривиален, из входного потока лексем просто лишние выбрасываются, нужные сохраняются. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kil00 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Я 3 раза перечитал, но так и не понял сути вопроса. Потому я такие вопросы и задаю, что новичок как в С++, так и в программировании контроллеров. Занимаюсь ими месяцев 8-9, периодически отрываясь от основной работы. Ну если начальство сказало, что надо, то преобразовывайте. Начальство тут не при чём, тут дело в непонимании. Мой алгоритм примерно выглядит так: while (!Character==32) { while ( ! (USART1->SR & USART_SR_RXNE) ) ; // ждать, пока символ не получен { CharNum++; if (CharNum==1) { USART1->SR &=~ USART_SR_RXNE;} // пропустить 1-ый символ if (CharNum==3) { Character = (USART1->DR & 0x1FF ) ;} // считать 2-ой символ ..... Получается, что я каждый символ должен посчитать, а их 32, через оператор if. Следующий этап - синтаксический анализ. В этом случае он тривиален, из входного потока лексем просто лишние выбрасываются, нужные сохраняются. Делаю я это так: считываю байт, если приёмник не пуст, повторяю в цикле. Вот я и спрашиваю, как это сделать (на уровне кода)? можно ли это упростить с помощью языка? А не использовать для этого 60 строчек кода. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MKdemiurg 1 29 декабря, 2011 Опубликовано 29 декабря, 2011 (изменено) · Жалоба Ты ЩО дурный (С) Без обид :) У тебя сообщение начинается с $ , заканчивается * +2 символа контрольной суммы. Вот и начинай запись в буфер с $ , а когда * прилетает - обрабатывай сообщение из буфера. Сколько * прилетело столько и сообщений обработать надо, т.е. счётчик сообщений ещё надо инкрементить в прерывании. Вот и всё - 2 if, флаговая переменная и счётчик сообщений в прерывании - обработчик в цикле основной программы завязан на if (флаговая переменная){парсер} Изменено 29 декабря, 2011 пользователем MKdemiurg Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Kuzmi4 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба 2 MarYuriy Там кстати не всё железо даёт sentence с дробными секундами: 33.00 есть железяки что дают с только один знак после запятой, есть - что вообще без дробных. Так же есть железяки что выдают формат так: $GPZDA,10,24,33.00,28,12,2011,.... (то есть запятые после часов и минут) Так что советую вам сделать более полный разбор полётов (ну и как то учесть CRC, потоум как всякое может быть на линии, хотя если прибор не военный, то .... ;) ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Потому я такие вопросы и задаю, что новичок как в С++, так и в программировании контроллеров. Занимаюсь ими месяцев 8-9, периодически отрываясь от основной работы. Начальство тут не при чём, тут дело в непонимании. Мой алгоритм примерно выглядит так: while (!Character==32) { while ( ! (USART1->SR & USART_SR_RXNE) ) ; // ждать, пока символ не получен { CharNum++; if (CharNum==1) { USART1->SR &=~ USART_SR_RXNE;} // пропустить 1-ый символ if (CharNum==3) { Character = (USART1->DR & 0x1FF ) ;} // считать 2-ой символ ..... Получается, что я каждый символ должен посчитать, а их 32, через оператор if. Вот я и спрашиваю, как это сделать (на уровне кода)? можно ли это упростить с помощью языка? А не использовать для этого 60 строчек кода. Непонятен алгоритм, который вы пытаетесь реализовать. while (!Character==32) Не буду утверждат, что символ 32 вообще не встречается в NMEA. мало ли. Но то что не характерен - точно. Типичная NMEA посылка, например: $GPRMC,данные в формате, какие должны быть по стандарту.*КС\r\n КС- контрольная сумма, вычисляемая так; xor всех байт от $ до * (не включая их). \r\n - перевод строки. Получается, что я каждый символ должен посчитать, а их 32, через оператор if. Почему 32? Некоторые поля могут иметь фиксированный фориат (и при этом иногда отсутствовать в строке - быть пустуми). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kil00 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Непонятен алгоритм, который вы пытаетесь реализовать. while (!Character==32)[/code] Почему 32? Некоторые поля могут иметь фиксированный фориат (и при этом иногда отсутствовать в строке - быть пустуми). Я ошибся, просто быстро накидал часть кода, как вижу решение. Должно быть while (!CharNum==32) 32 символа передаётся в одном пакете $GPZDA. Ты ЩО дурный (С) Без обид Я думал, что вчера написал, что мне нужно вычленить только определённые символы из этой последовательности: время без десятых и сотых, и дату. А сейчас не мог понять, зачем мне пишут то, что и так понятно ещё и ругают... Спать надо больше. Извиняюсь. А сам вопрос звучит так: как вычленить только определённые символы из этой последовательности: время без десятых и сотых, и дату? вот. т.е. в моём варианте примерно так(если я опять нигде не ошибся) while (!CharNum==32) { while ( ! (USART1->SR & USART_SR_RXNE) ) ; // ждать, пока символ не получен { CharNum++; if (CharNum==1) { USART1->SR &=~ USART_SR_RXNE;} // пропустить 1-ый символ , // то же для 2,3-7 if (CharNum==8) { Character = (USART1->DR & 0x1FF ) ;} // считать 2-ой символ // то же для 9,10-13 // и т.д. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Артём__ 0 29 декабря, 2011 Опубликовано 29 декабря, 2011 · Жалоба Я ошибся, просто быстро накидал часть кода, как вижу решение. Должно быть while (!CharNum==32) Понятно 32 символа передаётся в одном пакете $GPZDA. Далеко не факт: зависит от реализации протокола производителем приёмника - некоторые поля могут быть пустыми, если нет этих данных. Например, попадались строки RMC с пустыми полями времени/даты и тп(наверное потому что они не были еще определены на тот момент). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
andrewlekar 0 30 декабря, 2011 Опубликовано 30 декабря, 2011 · Жалоба while (!CharNum==32) Во-первых, такой код вообще работать не будет. У ! приоритет больше, чем у сравнения, поэтому цикл не выполнится ни разу. А сам вопрос звучит так: как вычленить только определённые символы из этой последовательности: время без десятых и сотых, и дату? Самое простое решение для вас: читать все символы с юарта в буфер. Когда обнаружится символ *, чтение прекратить, а буфер отправить на обработку. Буфер можно обрабатывать как строку - тут надо смотреть, есть ли у вас возможность пользоваться стандартной библиотекой си для работы со строками. Если можно, то есть функция поиска подстроки в строке: ищете подстроку $GPZDA в буфере - так вы определите начало строки с NMEA. Потом от начала NMEA ищете подстроку - запятую (или просто проверяете посимвольно в цикле). Таким образом отсчитываете нужное количество запятых. Так вы попадете на поле с нужными данными. Их читаете вплоть до следующей запятой (или любого нечитаемого символа) и уже дальше думаете, как конвертировать полученные символы в число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kil00 0 30 декабря, 2011 Опубликовано 30 декабря, 2011 · Жалоба _Артём_, я использую Trimble Resolusion-T. Если данных нет, то он посылает поля заполненные нулями, т.е. вмсето каждого символа нуль - по документации. andrewlekar, спасибо, буду разбираться! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lexanet 0 6 января, 2012 Опубликовано 6 января, 2012 · Жалоба Посмотрите LPC1768. Установка времени. (WEB&GPS&Manual). . Я там как раз баловался GPS, usart и прочим. Может что будет полезным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
kil00 0 10 января, 2012 Опубликовано 10 января, 2012 · Жалоба Как организовать буфер я нашёл. А вот как работать со строкой я так и не понял, тем более что библиотека iostream не подключается, а выдаёт ошибки при компиляции, поэтому невозможно использовать фунцию типа strcpy(s1,s2).. compiling main.c... P:\Keil\ARM\RV31\INC\rw/_defs.h(781): error: #20: identifier "namespace" is undefined P:\Keil\ARM\RV31\INC\rw/_defs.h(781): error: #65: expected a ";" P:\Keil\ARM\RV31\INC\iosfwd(93): error: #20: identifier "namespace" is undefined P:\Keil\ARM\RV31\INC\iosfwd(93): error: #65: expected a ";" P:\Keil\ARM\RV31\INC\iosfwd(117): error: #65: expected a ";" P:\Keil\ARM\RV31\INC\iosfwd(122): error: #65: expected a ";" P:\Keil\ARM\RV31\INC\iosfwd(127): error: #65: expected a ";" ... Что делать с принятой строкой, чтобы извлечь из неё нужную мне информацию? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Cosmojam 0 10 января, 2012 Опубликовано 10 января, 2012 · Жалоба Как организовать буфер я нашёл. А вот как работать со строкой я так и не понял, тем более что библиотека iostream не подключается, а выдаёт ошибки при компиляции, поэтому невозможно использовать фунцию типа strcpy(s1,s2).. Причём тут iostream если речь идёт о Си, не Си++ ? Подключайте string.h там strcpy объявлена функция поиска подстроки в строке: ищете подстроку $GPZDA в буфере Чудовищно тяжёлая операция для МК. На длинных строках умрёт. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
WHILE 0 11 января, 2012 Опубликовано 11 января, 2012 · Жалоба Чудовищно тяжёлая операция для МК. На длинных строках умрёт. Та ладна, чё там тяжелого.Гляньте исходник в вашем компиляторе. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться