Перейти к содержанию
    

Здравствуйте!

 

Надо ли преобразовывать как-то ASCII коды, которые получаю по USART, (типичная последовательность NMEA $GPZDA,102433.00,28,12,2011,,*6A, из которой мне нужны только 2-5 поля)?

(я так понимаю, что не надо)

 

Не подскажите более удачный алгоритм считывания символов с USARTa, кроме как перечисление if'ов?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я 3 раза перечитал, но так и не понял сути вопроса.

Надо ли преобразовывать как-то ASCII коды, которые получаю по USART

Ну если начальство сказало, что надо, то преобразовывайте.

Не подскажите более удачный алгоритм считывания символов с USARTa, кроме как перечисление if'ов?

Более удачный алгоритм - считывать с юсарта без ифов. Я вот считываю и перечисления ифов нет. Делаю я это так: считываю байт, если приёмник не пуст, повторяю в цикле.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Повышаем градус абстракции!

От GPS-модуля ведь приходят текстовые строки, не правда ли? Значит и принимаем их с UART посимвольно, собирая из символов строки.

 

Когда строка полностью принята переходим к разбору той строки.

Отдельные поля в строке, как видим отделяются друг от друга запятой. Поле может быть пустым либо содержать число (целое или float), либо некое имя.

По науке этот этап называется лексическим анализом, а сами поля - лексемы. Множество терминальных символов (разделители лексем) состоит из запятой и конца строки.

 

Следующий этап - синтаксический анализ. В этом случае он тривиален, из входного потока лексем просто лишние выбрасываются, нужные сохраняются.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я 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 строчек кода.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ты ЩО дурный (С) Без обид :)

 

У тебя сообщение начинается с $ , заканчивается * +2 символа контрольной суммы.

 

Вот и начинай запись в буфер с $ , а когда * прилетает - обрабатывай сообщение из буфера. Сколько * прилетело столько и сообщений обработать надо, т.е. счётчик сообщений ещё надо инкрементить в прерывании.

 

Вот и всё - 2 if, флаговая переменная и счётчик сообщений в прерывании - обработчик в цикле основной программы завязан на if (флаговая переменная){парсер}

Изменено пользователем MKdemiurg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 MarYuriy

Там кстати не всё железо даёт sentence с дробными секундами: 33.00

есть железяки что дают с только один знак после запятой, есть - что вообще без дробных.

 

Так же есть железяки что выдают формат так:

$GPZDA,10,24,33.00,28,12,2011,....

(то есть запятые после часов и минут)

 

Так что советую вам сделать более полный разбор полётов :biggrin: (ну и как то учесть CRC, потоум как всякое может быть на линии, хотя если прибор не военный, то .... ;) )

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Потому я такие вопросы и задаю, что новичок как в С++, так и в программировании контроллеров. Занимаюсь ими месяцев 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? Некоторые поля могут иметь фиксированный фориат (и при этом иногда отсутствовать в строке - быть пустуми).

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Непонятен алгоритм, который вы пытаетесь реализовать.

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

 

// и т.д.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я ошибся, просто быстро накидал часть кода, как вижу решение. Должно быть

 

while (!CharNum==32)

 

Понятно

32 символа передаётся в одном пакете $GPZDA.

 

Далеко не факт: зависит от реализации протокола производителем приёмника - некоторые поля могут быть пустыми, если нет этих данных.

Например, попадались строки RMC с пустыми полями времени/даты и тп(наверное потому что они не были еще определены на тот момент).

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

while (!CharNum==32)

Во-первых, такой код вообще работать не будет. У ! приоритет больше, чем у сравнения, поэтому цикл не выполнится ни разу.

А сам вопрос звучит так: как вычленить только определённые символы из этой последовательности: время без десятых и сотых, и дату?

Самое простое решение для вас: читать все символы с юарта в буфер. Когда обнаружится символ *, чтение прекратить, а буфер отправить на обработку. Буфер можно обрабатывать как строку - тут надо смотреть, есть ли у вас возможность пользоваться стандартной библиотекой си для работы со строками. Если можно, то есть функция поиска подстроки в строке: ищете подстроку $GPZDA в буфере - так вы определите начало строки с NMEA. Потом от начала NMEA ищете подстроку - запятую (или просто проверяете посимвольно в цикле). Таким образом отсчитываете нужное количество запятых. Так вы попадете на поле с нужными данными. Их читаете вплоть до следующей запятой (или любого нечитаемого символа) и уже дальше думаете, как конвертировать полученные символы в число.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

_Артём_, я использую Trimble Resolusion-T. Если данных нет, то он посылает поля заполненные нулями, т.е. вмсето каждого символа нуль - по документации.

 

andrewlekar, спасибо, буду разбираться!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Посмотрите LPC1768. Установка времени. (WEB&GPS&Manual). . Я там как раз баловался GPS, usart и прочим. Может что будет полезным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как организовать буфер я нашёл. А вот как работать со строкой я так и не понял, тем более что библиотека 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 ";"

...

 

Что делать с принятой строкой, чтобы извлечь из неё нужную мне информацию?

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как организовать буфер я нашёл. А вот как работать со строкой я так и не понял, тем более что библиотека iostream не подключается, а выдаёт ошибки при компиляции, поэтому невозможно использовать фунцию типа strcpy(s1,s2)..

Причём тут iostream если речь идёт о Си, не Си++ ? Подключайте string.h там strcpy объявлена

функция поиска подстроки в строке: ищете подстроку $GPZDA в буфере

Чудовищно тяжёлая операция для МК. На длинных строках умрёт.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чудовищно тяжёлая операция для МК. На длинных строках умрёт.

 

Та ладна, чё там тяжелого.Гляньте исходник в вашем компиляторе.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...