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

Есть ли классика обработки ответов от GSM модуля на стороне МК ?

Задался вопросом, а существует ли классический алгоритм обработки ответов модуля на стороне микроконтроллера?

Лично я пробую обрабатывать на лету:

Временный буфер (50 байт, например), он до начала приема заполнен значениями 0А, это для обработки двух-символьных ответов 30 0D и 34 0D.

Указатель - переменная на последний принятый байт в буфере, по умолчанию = 1.

В основном цикле отправляю команду в модуль и в цикле жду изменения переменной результата.

По прерыванию на UART:

- пополняю временный буфер принятым байтом (пополнение начинается не с нулевого байта, а с первого, опять же, для обработки двух-символьных ответов);

- если указатель >= 2, проверяю три последних символа буфера на соответствие маске (0A 30 0D, 0A 34 0D etc.);

- если соответствие есть - записываю в переменную результата (соответственно 30, 31, 34 etc.);

- инкрементирую указатель на последний принятый байт и опять жду прерывания.

 

Думал просто искать ответ во временном буфере, выдержав какую-то паузу после отправки команды в модуль, но время выполнения команд может быть очень разное...

В общем, это мой дебютный алгоритм опроса модулей, по этому и задался вопросом, а как пишут бывалые?

 

 

 

 

 

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


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

Я сделал структуру для ответа с собственно массивом строки (довольно большим - 500 байт) и длиной.И таких структур штук 5-6. Отсекая строки по 0D 0A отправляю в Очередь сообщений FreeRTOS указатель на заполненную структуру и в самой структуре еще ставлю флаг что она не обработана. Это все в прерываний.

В основном потоке - собственно ожидание указателя на Очередь со свежими данными и после обработки ставлю флаг освобождения в структуре.

Что это дает: удобство в том, что строки обрабатываются в том же порядке в каком они приходят, фрагментация не имеет значение. Минус - откусывается кусок RAM в несколько кБ, но у меня 96к, могу позволить себе такую роскошь:-)

 

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


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

Отсекая строки по 0D 0A...
Так не все же ответы заканчиваются 0D 0A, некоторые только 0D.

 

У каждой структуры свой обработчик? Т.е. например ожидание соединения обрабатывается индивидуально?

 

в Очередь сообщений FreeRTOS
А бинарный поток, я так понимаю, отдельно обрабатывается?

 

откусывается кусок RAM в несколько кБ
Ну да, если приложение не ресурсоемкое, то использование камня среднего или старшего семейства будет иметь сомнительное оправдание :)

 

Еще минус вижу в сложности написания стандартной библиотеки.

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

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

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


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

Классики нет, особенно если требуется принимать данные в режиме CSD или работать с Simcom TCP стеком. Лично у меня все принятые данные проверяются на наличие CR, LF и если есть перенос строки, то обрабатывается строка от начала буфера до переноса. Обработка вынесена из прерывания с помощью двойной буферизации (пока обрабатываем первый буфер, второй заполняется в прерывании). Алгоритм требует модификации для команды CMGR, CMGL, приёма данных по символу > и для проприетарных симковоских команд.

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

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


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

В общем, это мой дебютный алгоритм опроса модулей, по этому и задался вопросом, а как пишут бывалые?

 

Применяю всегда RTOS для этих целей.

 

В прерываниях просто записываются символы в кольцевой буфер и отправка события в задачу модема о приеме символа.

 

Задача модема извлекает символы из кольцевого буфера в свой линейный буфер и ищет в нем заданный при вызове функции чтения терминатор строки.

Терминатором может быть и 0D 0A или '>' или что угодно, зависит от того что в данный момент приложение ожидает от модема.

Ожидание получения строки длится определенное заданное время.

Если в течении этого времени терминатор не обнаружен, то принятый буфер данных дополнительно сканируется

на асинхронные сообщения по их строчным шаблонам и если и их не обнаружено, то буфер обнуляется.

Асинхронные сообщения могут иметь иметь каждое свою задачу назначения. Задачи приемники заранее регистрируют свои обработчики в задаче модема.

 

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


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

Применяю всегда RTOS для этих целей.

 

В прерываниях просто записываются символы в кольцевой буфер и отправка события в задачу модема о приеме символа.

Не выгодно каждый символ передавать - я делаю по концу строки или по установленным маскам. Бинарные данные просто записываются и по счетчику передается событие и готовности.

 

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


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

Так не все же ответы заканчиваются 0D 0A, некоторые только 0D.

0D 0A всегда, если отправляешь например AT\r то эхо все равно будет AT\r\n

тут еще AlexandrY правильно подметил, что по ">" тоже нудно отсекать - все верно, для SMS по нему отсекаю так же. В другое время этот символ никогда не появляется.

У каждой структуры свой обработчик? Т.е. например ожидание соединения обрабатывается индивидуально?

Я описал как бы сам механизм отлова строк, а сама функция подачи АT команд выглядит примерно так: как у printf неограниченно количество аргументов в виде строк с возможными ответами и выход из функции либо по таймауту либо по успешному нахождению одной из строк в аргументах

А бинарный поток, я так понимаю, отдельно обрабатывается?

Да, отдельно, после команды ATD*99# используется просто буфер в виде той же очереди FreeRTOS, а уж TCP стек забирает оттуда данные - тут совсем все просто.

Ну да, если приложение не ресурсоемкое, то использование камня среднего или старшего семейства будет иметь сомнительное оправдание :)

Соглашусь.

Еще минус вижу в сложности написания стандартной библиотеки.

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

Код достаточно переносимый.

Я еще не стал уподробняться, что у меня не просто прерывание по RX, а используется DMA, так как STM32 и поверх еще прослойка в виде CMUX, но сути это не меняет. Кстати CMUX очень рекомендую: я допиливаю трекер, так что очень приятно иметь виртуальные порты: один для GPRS, другой для SMS и звонков, третий для качества сигнала и определения видимых сот.

Еще в эту систему для полного счастья следует добавить поддержку спящего режима модема (с линией DTR как правило). Кстати, модемы SierraWireless мне в этом плате понравились - дополнительных сигналов не требуется. В общем вроде простая задача, а можно зайти очень далеко :-)

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


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

Не выгодно каждый символ передавать - я делаю по концу строки или по установленным маскам. Бинарные данные просто записываются и по счетчику передается событие и готовности.

 

Немного не понял ваш механизм, разъясните куда данные записываются, что за счетчик и каким образом передается событие.

 

В моем варианте из процедуры прерывания в задачу RTOS передаются не символы, а асинхронные сообщения о приеме символов.

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

Задача-приемник же может забрать и посимвольно и большим блоком в зависимости от того как она успевает.

 

Формировать же строки имеющие разные терминаторы в процедуре прерывания означает слишком усложнить процедуру прерывания и перенести в нее часть логики прикладного приложения.

А если учесть еще, что приходится работать и с протоколом PPP и с мультиплексированием, то вообще неприемлемо втягивать в это процедуру прерывания.

 

Я еще не стал уподробняться, что у меня не просто прерывание по RX, а используется DMA, так как STM32...

 

DMA? Очень интересно.

А как вы задаете для DMA размер пересылаемого блока? На основе чего его определяете?

И почему DMA только по RX?

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


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

DMA? Очень интересно.

А как вы задаете для DMA размер пересылаемого блока? На основе чего его определяете?

И почему DMA только по RX?

Прерывание IDLE line USARTа приходит на помощь. В нем хвост забирается и ресетится DMA. Буфер DMA при этом может быть довольно большим - 128 или 256 например, при этом практически все АТ строки забираются из этого прерывания.

TX тоже по DMA, кстати тоже неприятный момент, что DMA работает с блоками выровненными на 4, это не позволяет решать задачу в лоб.

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


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

...записываются символы в кольцевой буфер и отправка события в задачу...
С кольцевым буфером это интересно, нужно попробовать, меньше "телодвижений" должно получиться...

 

Не выгодно каждый символ передавать...
Тогда не выполнится условие RTOS.

 

Кстати CMUX очень рекомендую...
Очень круто, но я так понимаю это исключительно Telit`овская фича?

 

...добавить поддержку спящего режима модема (с линией DTR как правило). ...модемы SierraWireless мне в этом плате понравились - дополнительных сигналов не требуется.
SIMы так же работают.
Изменено пользователем vassabi

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


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

Я сделал структуру для ответа с собственно массивом строки (довольно большим - 500 байт) и длиной.И таких структур штук 5-6. Отсекая строки по 0D 0A отправляю в Очередь сообщений FreeRTOS указатель на заполненную структуру и в самой структуре еще ставлю флаг что она не обработана. Это все в прерываний.

У меня похожая реализация.

Добавлю:

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

- перед отправкой команды модему убеждаюсь что модем некоторое время (у меня 50 мс) молчал (для приема всех unsolicited)

- после отправки команды и до получением эха все принятые строки парсятся как uslolicited

- тайм-аут получения эха команды например в 1 секунду позволяет не тратить много времени на ожидание результата выполнения команды в случае если модем аварийно отвалился, что особенно актуально на командах для которых заявлено длительное время выполнения

 

Очень круто, но я так понимаю это исключительно Telit`овская фича?

Нет, стандартная (3GPP TS 07.10), но не обязательная. Кроме Telit'ов встречал в Quectel'aх

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


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

Очень круто, но я так понимаю это исключительно Telit`овская фича?

Нет, стандартная (3GPP TS 07.10), но не обязательная. Кроме Telit'ов встречал в Quectel'aх

Тю, оказывается в SIM`ах это тоже есть (AT+CMUX Multiplexer Control), когда доку штудировал наверное не обратил внимания.

Надергал апнотов, буду впитывать...

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


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

И после всего этого еще ругают OCPU, EAT etc. :) На сколько же все становится проще...

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


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

И после всего этого еще ругают OCPU, EAT etc. :) На сколько же все становится проще...

А что это за звери такие "OCPU" и "EAT"? Где почитать?

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


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

И после всего этого еще ругают OCPU, EAT etc. :) На сколько же все становится проще...

Ну да, ну да. Особенно если учесть, что часть функционала и там приходится извлекать AT-командами...

 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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