Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Алгоритм получения строки с СИМХХХ
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > Сотовая связь и ее приложения
zebrox
Всем привет.
Может вопрос глупый конечено, и никакой проблемы нет.

Есть вопрос такого плана.
Как правильно получать строку (ответа) от сима.
\r\nMessage\r\n

Я вижу два возможных варианта.

Вариант 1.
1.При первом прерывании от юарта, уходим в него, выключаем прерывания, выставляем флаг пришедьших данных, выходим из прерывания.
2.В основном цикле, если видим флаг читаем строку, и обрабатываем ее (тут получается небольшая проблема, т.к. нужно делать некий автомат состояний и нужно постоянно помнить какое было последнее сообщение). После обработки сообщения включаем прерывания от юарта.

Вариан 2, извращенный smile.gif
1.При первом прерывании от юарта, получаем символ, записываем в буффер, запускаем таймер на 0.4сек скажем.
2.при следующем прерывании от юарта (до истечения таймера), записываем следующий символ в буффер, перезапускаем таймер.
3.так делаем до тех пор, пока таймер 0,4 сек не истечет или буфер не заполнится.
4.Когда таймер истек, имеем в буффере все сообщение от сима, обрабатываем его.

А как Вы получаете данные с сима?
Палыч
Что-то не пойму: в чём проблема?
Принимайте символы и складывайте в буфер до тех пор, пока не встретите символы окончания строки "\r\n". Обрабатываете ответ.
Зачем таймер, запрет прерываний? Наверное, Вы плохо обозначили проблему...
zebrox
если ли по \r\n обрабатывать, то можно начало следующей строки потерять (пока обрабатываешь).
может можно каким то образом заставить сим делать паузу между строками, 0,5 сек например?
rx3apf
Цитата(zebrox @ Nov 22 2010, 17:51) *
если ли по \r\n обрабатывать, то можно начало следующей строки потерять (пока обрабатываешь).
может можно каким то образом заставить сим делать паузу между строками, 0,5 сек например?

Используйте буфер достаточного размера и правильные установки порогов для управления потоком, с тем, чтобы обрабатываемая строка заведомо помещалась в буфер и не перекрывалась поступающими данными в процессе обработки. Никаких сложностей, на самом деле...
zebrox
А какие правильные установки порогов управления потоком? Что это за пороги и как их изменить?
skripach
Цитата
если ли по \r\n обрабатывать, то можно начало следующей строки потерять (пока обрабатываешь).

Обработка фоном.
Растасовка пакетов в прерывании.
В чем проблема не пойму. смущает то что на стыке двух пакетов встретится "\r\n\r\n" ?
Палыч
Цитата(zebrox @ Nov 22 2010, 17:51) *
если ли по \r\n обрабатывать, то можно начало следующей строки потерять (пока обрабатываешь).
Сколько времени Вам нужно, чтобы обработать строку?
Если ОЗУ не жалко, то можно использовать два буфера: в один принимается строка; как только строка принята - из первого буфера быстро переписываем во второй буфер; программа разбора строки медленно разбирает строку во втором буфере, а в это время первый буфер заполняется новой строкой... Время разбора не должно превышать времени приёма следующей строки.
Цитата(zebrox @ Nov 22 2010, 17:51) *
может можно каким то образом заставить сим делать паузу между строками, 0,5 сек например?
Можно. Используйте сигналы управления потоком.

P.S. Осторожнее с признаком конца ввода ответа: не все ответы модуля заканчиваются парой "\r\n" (например, приглашение ввода смс).
zebrox
пока я это смутно представляю.

правилен ли следующий алгоритм?
имеем N буфферов, b1,b2,b3...bn, скажем по 100 байт каждый, активный буффер b1.

- по прерывании, загружаем символы в ативный буффер, получили \р\н, выставляем флаг что даннанные в буффере b1 готовы.
- в основном цикле, если видим флаг, делаем активным буффер b+1 , обрабатываем данные из буффера b1, если в это время идут симфолы по юарту, они будут загружаться в b+1.
- по окнчанию обработки данных из b1, делаем его как пустой.

Что-то мне это не очень нравится, много памяти нужно.
Повторю вопрос, можно ли заставить сим деалать паузу между выдаваемыми строками?
rx3apf
Цитата(zebrox @ Nov 22 2010, 18:44) *
пока я это смутно представляю.

правилен ли следующий алгоритм?
имеем N буфферов, b1,b2,b3...bn, скажем по 100 байт каждый, активный буффер b1.
....
Что-то мне это не очень нравится, много памяти нужно.

И правильно не нравится, совершенно извращенный алгоритм. Делается программный кольцевой FIFO (я использую 64 байта на rx и tx), управление потоком (порог 32 байта в моем случае, анализируемый ответ должен заведомо помещаться в эти 32 байта, иначе надо увеличить "по вкусу", ну и учесть возможный "выбег", после деактивации сигнала может еще что-то поступить, один-два байта типично). Получили "конец строки" - обрабатываем. Если не успеваем обработать - то все равно обработчик прерываний UART приостановит прием деактивацией сигнала управления потоком.

Цитата
Повторю вопрос, можно ли заставить сим деалать паузу между выдаваемыми строками?

Запретить прием деактивацией RTS. Естественно, надо включить аппаратное управление потоком для модема.
zebrox
ок, если паузу установить нельзя, тогда вопрос по сигналам управления потоком.

Правильно ли я понимаю назначение сигналов?

DTR-выставляем всегда при включении питания (после загрузки модуля), и далее им не дергаем, или дергаем, то когда?
RTS-выставляем когда проц готов получать данные от сима, если проц занят и не готов, нужно держать низкий уровень?

CTS-ничего симу не передаем, пока не увидим там высокий уровень?
RI-если видим RI, готовимся получать данные от сима (реально ничего не делаем по ри, т.к. прием данных завязан на прерывание по юарту)?
rx3apf
Цитата(zebrox @ Nov 22 2010, 19:00) *
Правильно ли я понимаю назначение сигналов?

DTR-выставляем всегда при включении питания (после загрузки модуля), и далее им не дергаем, или дергаем, то когда?
RTS-выставляем когда проц готов получать данные от сима, если проц занят и не готов, нужно держать низкий уровень?

CTS-ничего симу не передаем, пока не увидим там высокий уровень?
RI-если видим RI, готовимся получать данные от сима (реально ничего не делаем по ри, т.к. прием данных завязан на прерывание по юарту)?

Да, только полярности другие - активные уровни "0". А по "RI" можно определять, например, приход SMSки, но для этого надо обрабатывать, измеряя длительность.
zebrox
Ок, товарищ из третьего района, спасибо большое smile.gif
только ведь приход смски можно опять-же сообщением от сима определить вроде он должен выдавать +CMTI: и что-то там еще, куда сохранил вроде.

Всем спасибо за участие, буду дальше курить этот процесс smile.gif
rx3apf
Цитата(zebrox @ Nov 22 2010, 19:09) *
только ведь приход смски можно опять-же сообщением от сима определить вроде он должен выдавать +CMTI: и что-то там еще, куда сохранил вроде.

Можно. Но я, например, использую прозрачный режим и типично в состоянии постоянной связи по GPRS, так что служебные сообщения от модема не вижу. Короче, от задачи зависит...
ArtemKAD
Цитата
RTS-выставляем когда проц готов получать данные от сима, если проц занят и не готов, нужно держать низкий уровень?

Где-то так. Но при этом не забывать,что внутри модуля такой-же один маленький буфер. И если за время пока "проц занят" буфер успеет переполниться, часть данных от модуля будет просто потеряна.
MKdemiurg
А не проще без прерывания принимать по флагу приёма? Правда возможны зависания МК, для этого таймер использовать.
M_Z
Цитата(MKdemiurg @ Nov 22 2010, 22:21) *
А не проще без прерывания принимать по флагу приёма? Правда возможны зависания МК, для этого таймер использовать.

такой вариант я бы точно никому не посоветовал. тем более вполне вероятно что проц должен еще нибудь заниматься. прием должен быть в прерывании. вот обработчик может находится в основном цикле. а так буфер фифо, как выше писали, то что надо.
Решил добавить. кроме приема по прерыванию, еще возможен прием по ДМА. тогда просто нужно периодически просматривать приемный буфер. но мне кажется это тоже сложновато будет.
MKdemiurg
А если линейная программа , направлена ТОЛЬКО на приём -передачу? Можно уйти от зависания(ожидания приёма) по таймеру. Также набил буфер только в теле программы обработал и погнал дальше.
andrewlekar
Я делал так, что по прерыванию заполняется буфер, а второй буфер обрабатывается задачей. Когда прерывание отработало и задача освободилась, то буферы меняются местами и работа продолжается. По сути аналог FIFO, но чуть попроще на мой взгляд и прерывания достаточно запрещать на время смены буферов, а не при каждом обращении к FIFO. Размеры буферов настраиваются исходя из времени переключения задач и скорости UART. Бывает ещё, что FIFO встроенный в процессор, но я даже не знаю как можно хорошо эту фичу применить.
mempfis_
Цитата(zebrox @ Nov 22 2010, 17:02) *
А как Вы получаете данные с сима?


При разборе ответом от модема поступаю таким образом:
1. модем отвечает эхом на команду - это можно детектировать как начало ответа
2. ответ на команду содержит специфические сообщения которые можно использовать как признак завершения ответа.
3. любая команда имеет ограниченный таймаут ответа оговоренный в документации

Пример команды AT+CREG?\r\n, таймаут ответа по докам - мгновенно (т.к. не связано с запросами в сеть) - реально даю 1 секунду

AT+CREG?\r\n CMD


AT+CREG\r\n ANS
\r\n
+CREG: 0,1\r\n
\r\n
OK\r\n

Ответ на команду начинается с эха, далее идёт ключевое слово +CREG и завершается команда OK.
В итоге чтобы найти ответ на команду достаточно выловить +CREG и OK в ответе.
Другие команды имеют больше вариантов ответов.


Для приёма ответов от модема у меня есть специальный буффер и задача которая выбирает символы из fifo uarta отвечающего за работу с модемом. Задача не анализирует сам ответ а только следит за тем тем чтобы таймаут с последнего принятого символа превышал определённое время (напр. 50 мС). Как только превысится это время вызывается задача которая послала ат-команду в модем а сам буффер переходит в режим ожидания. Если задача пославшая ат-команду нашла все ответы которые ожидала она переводит буффер в ждущий режим что даёт возможность другим задачам получить доступ к модему. Если ответ не найден то буффер переводится в режим ожидания данных - т.е. пытаемся дополучить ответ от модема на конкретную команду. И так до тех пор пока не получим полный ответ или не выйдет максимальный таймаут ожидания.
Alechek
Цитата(mempfis_ @ Nov 23 2010, 21:35) *
При разборе ответом от модема поступаю таким образом:
1. модем отвечает эхом на команду - это можно детектировать как начало ответа

Ну зачем же эхо ждать и разбирать. Не проще ли его отключить при иницализации модема. ATE0

Можно и еще интересней поступить... ATV0.
mempfis_
Цитата(Alechek @ Nov 25 2010, 17:39) *
Ну зачем же эхо ждать и разбирать. Не проще ли его отключить при иницализации модема. ATE0

Можно и еще интересней поступить... ATV0.


Можно и ATE0 подать smile.gif И ответ упростить с помощью ATV0 smile.gif
Я вообще пример расписывал. В своих программах эхо не отключаю (ну не напрягает оно вообще smile.gif ) А ответы обрабатываю по ключевым словам для каждой ат-команды (+CREG: , +CMGL: и т.д.).
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.