Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с COM-портом, алгоритм(+) 
:(
    Опции темы
Гость_Бегемот
Дата 27.12.2005, 20:13 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Всем здравствуйте.
Необходимо читать и писать в COM-порт данные. Устройство - сотовый телефон, подключен через USB, но эмулируется com-порт. Данные нужно отправлять и принимать только с телефона. Порт работает в синхронном режиме и есть несколько вопросов:
1. Хочу прочитать данные с телефона, пишу в порт команду WriteFile("ATxxx"...) - команда записалась. Теперь надо прочитать данные - ReadFile(...). Какой указывать буфер? Сколько байт читать, если заранее ответ не известен? Можно указать заранее буфер размером в мегабайт, потом посмотреть сколько байт было реально прочитано и уже из буфера получить это количество байт - правильно ли это? И как вообще получать данные из порта после записи в него AT-команды?
2. После WriteFile сразу необходимо сделать ReadFile, о таймаутах будет заботится драйвер порта? Я имею в виду - структуру COMMTIMEOUTS я заполню, все остальное - уже не моя забота?
Заранее спасибо за ответы!
  Вверх
Dreamer_0x01
Дата 27.12.2005, 22:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата
После WriteFile сразу необходимо сделать ReadFile, о таймаутах будет заботится драйвер порта? Я имею в виду - структуру COMMTIMEOUTS я заполню, все остальное - уже не моя забота?

Я еще на всякий случай сразу после WriteFile делаю PurgeComm.

Цитата
Сколько байт читать, если заранее ответ не известен? Можно указать заранее буфер размером в мегабайт, потом посмотреть сколько байт было реально прочитано и уже из буфера получить это количество байт - правильно ли это?


Сколько прочитно байт, ты посмотришь в переменной LPDWORD lpNumberOfBytesRead, адрес которой тыпередаешь в функцию ReadFile.

НО!!! Я бы не использовал такой подход по той причине, что ВСЕГДА у тебя функция будет завершаться по таймауту, так как ты хочешь запрашивать заведомо больший буфер, чем будет реально считан, поэтому при каждом вызове этой фунции ты будешь дожидаться таймаута, а это сильно придаст тормозов твоей программе.
Я бы поместил функцию чтения в отдельный поток, в котором все время считывал бы по несколько символов (например, по 128, зависит от скорости порта, если болшая и стабильная, то можно и поболее) с небольшим таймаутом, и считанные символы помещал бы в специальный буфер-очередь, который сдвигал бы по мере забора из него символов уже твоим рабочим потоком. Естественно, не забыв про синхронизацию.
Тогда ожидание по таймауту будет происходить в отдельном потоке, не затормаживая твой основной поток при каждом вхождении в функцию ReadFile.





--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 27.12.2005, 22:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



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



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Гость_Бегемот
Дата 27.12.2005, 22:59 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











1. Понял. Т.е. читать или побайтово или небольшими партиями в заведомо большой буфер. Так?
2. Все же тайм-ауты. После WriteFile сразу делаю ReadFile (Purge чтобы очистить буфферы порта), о задержках будет заботиться драйвер?
И тогда уж еще вопрос smile Данные, которые читаются из порта, содержат как саму информацию, так и управляющие коды (ОК, \r и т.д.) Как их отделять - по символам \r\n? Т.е. заранее надо знать, в какой форме придет ответ (считаем, эхо для порта выключено). Или этот формат стандартный, насколько я посмотрел, это вот такой вид: _\r\n_ _Данные_ _\r\n_ _OK_. Такой формат сохраняется всегда? Или все же парсить полученные данные и выделять служебные символы?
  Вверх
JoyEx
Дата 27.12.2005, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



1) Да, если читаешь по 1 байту, то и буфер бери 1 байт или 2=1+1(для '\0')
2) Да.
3) Хз. Пути господни неисповедимы ;)



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 27.12.2005, 23:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Парсить надо обязательно. Дело в том,что никто не защищен от возникновения на линии "левых" символов, а также паразитных "эхо-символов", и хоть в случае с телефоном это может и маловероятно, но ты получишь хороший опыт реализации помехоустойчивого протокола. А если ты еще потом будешь эти функции на RS-485 использовать, то там "лишние" символы фильтровать надо обязательно!


Цитата
Все же тайм-ауты. После WriteFile сразу делаю ReadFile (Purge чтобы очистить буфферы порта), о задержках будет заботиться драйвер?

Да. Точнее,не знаю, то именно - драйвер, или ядро Виндоус, или какие-то dll но не ты =)

Совет: если есть сомнения в работе с портами - не полинись купить/сделать перекрестный шнурок, и законнектить по нему два компа. Тогда на одном из них хапускаешь терминалку, на другом - свою прогамму, и имеешьудовольствие ;)
Потому что твой телефон - устройство "слепое", и может быть так, что ты все напишешь правильно, но будет дело в каких-нибудь мелочах. А купив шнурок, ты всегда сможешь смоделирвать ту или иную ситуацию, и отладить программу по шагам.

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




--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
JoyEx
Дата 28.12.2005, 02:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата
Все же тайм-ауты. После WriteFile сразу делаю ReadFile (Purge чтобы очистить буфферы порта), о задержках будет заботиться драйвер?

Ты немного не так спросил или я не так понял.
Если ты имел в виду события посл. порта, то тогда ты сам должен "заботиться" и вот тебе простой пример чтения данных из порта (hComm).
Код

    OVERLAPPED o;
    o.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    HANDLE Handles[2] = {o.hEvent, g_hEventQuit};
    DWORD dwEvtMask = 0;
    BYTE Buffer[4096] = {0};
    COMSTAT csStat;

    while (1)
    {
        ResetEvent(o.hEvent);

        if (!WaitCommEvent(hComm, &dwEvtMask, &o))
        {
            if (WaitForMultipleObjects(2, Handles, FALSE, INFINITE) == WAIT_OBJECT_0+1)
                break;
        }

        if(dwEvtMask & EV_BREAK)
            break;

        if(dwEvtMask & EV_RXCHAR)
        {
            DWORD dwError = 0;
            ClearCommError(hComm, &dwError, &csStat);

            ResetEvent(o.hEvent);
            DWORD dwBytes = 0;

            if (!ReadFile(hComm, Buffer, csStat.cbInQue, &dwBytes, &o))
            {
                if (WaitForMultipleObjects(2, Handles, FALSE, INFINITE) ==
                    WAIT_OBJECT_0+1)
                    break;
            }

            for (int i = 0; i < csStat.cbInQue; i++)
            {
                TRACE("%c", Buffer[i]);
            }
        }
    }//while

ПисАть в порт можно WriteFile и синхронно, без OVERLAPPED.


smile
А то у тебя, Гость_Бегемот, получается как в жизни
Цитата

- Девушка, можно рядом сесть (присесть)?
- Нет!
- Дура, а почему тут этот сидит?
- А он меня не спрашивал.


Мораль: не спрашивай как делать, делай и всё тут! Сначало бери smile задаток за прогу.



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Бугемот
Дата 28.12.2005, 06:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Цитата(JoyEx @ 28.12.2005, 02:25)
Сначало бери  задаток за прогу.

Я для себя пишу smile
А код, который ты привел - это разве не асинхронный режим? У меня случай простой: послал команду - получил данные. Следующая команда - следующие данные, т.к. я буду не только в телефон передавать, но и получать данные вперемежку.
Цитата(Dreamer_0x01 @ 27.12.2005, 23:17)
Парсить надо обязательно. Дело в том,что никто не защищен от возникновения на линии "левых" символов, а также паразитных "эхо-символов", и хоть в случае с телефоном это может и маловероятно, но ты получишь хороший опыт реализации помехоустойчивого протокола.

Спасибо! Попробую сначала получить результат (вернее, уже все заработало), а потом уже буду пробовать парсить. Дело в том, что в данных тоже могут встречаться символы \r\n. Ну, это уже буду смотреть конкретно применительно к AT-командам своего телефона, там как-то хитро сделано получение SMS сообщений из него.
Еще раз всем большое спасибо! Поднял бы вам рейтинги, но не дают, говорят, 100 сообщений надо smile
PM MAIL   Вверх
takedo
Дата 28.12.2005, 08:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



JoyEx
парочка замечаний и вопрос.
во первых, не понятна конструкция (WaitForMultipleObjects(2, Handles, FALSE, INFINITE), если INFINITE, то значит не выйдем по таймауту=> зачем асинхронная передача. Во-вторых, у меня при чтении по событию EV_RXCHAR зачастую очередь была нулевая! То есть событие взвелось(EV_RXCHAR), а очередь не обновилась. Порыскал по паутинке, оказалось, что это не только у меня и что толком проблему не решили(был только способ с синхронных чтением). Вот по этой проблеме нет ли соображений?
Добавлено @ 08:10
Бугемот
Цитата
_\r\n_ _Данные_ _\r\n_ _OK_.
Очевидно, что _\r\n - начало кадра, а _\r\n_ _OK_ - конец. Это может значить, что все пакеты передаются с такими символами в начале и конце. Следовательно, кто-то подумал о протоколе, а значит, при передаче у тебя никогда не должны встретиться в данных _\r\n или _\r\n_ _OK_. Лучше как и было сказано, заведи буфер и читай туда побайтово синхронно и анализируй (ставь меточку начала _\r\n и конца _\r\n_ _OK) и обрабатывай. smile Но! Если ты будешь не только передавать, но и получать данные - ты просто обязан знать протокол передачи, иначе нет смысла пыркаться. А если ты его знаешь, то к чему некоторые вопросы? smile


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
JoyEx
Дата 28.12.2005, 11:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Цитата
А код, который ты привел - это разве не асинхронный режим? У меня случай простой: послал команду - получил данные. Следующая команда - следующие данные, т.к. я буду не только в телефон передавать, но и получать данные вперемежку.


Да, асинхронный. Не забудь про SetCommMask

Цитата(takedo @ 28.12.2005, 08:01)
парочка замечаний и вопрос.
во первых, не понятна конструкция (WaitForMultipleObjects(2, Handles, FALSE, INFINITE), если INFINITE, то значит не выйдем по таймауту=> зачем асинхронная передача. Во-вторых, у меня при чтении по событию EV_RXCHAR зачастую очередь была нулевая! То есть событие взвелось(EV_RXCHAR), а очередь не обновилась. Порыскал по паутинке, оказалось, что это не только у меня и что толком проблему не решили(был только способ с синхронных чтением). Вот по этой проблеме нет ли соображений?

1) Если что, то выйдем из WaitForMultipleObjects по Handles[1], т.е. по g_hEventQuit
2) Хз. Может быть буфер у тебя был большой и ты выходил из ф-ции через час (по таймауту)?!


--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
takedo
Дата 28.12.2005, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



JoyEx
Цитата
2) Хз. Может быть буфер у тебя был большой и ты выходил из ф-ции через час (по таймауту)?!

Нет. Просто когда данные приходили, я считывал из очереди количество символов, которое там находилось. И снова ждал, когда придет символ. И вот когда он приходит, длина очереди равна нулю.
Добавлено @ 11:31
http://forum.vingrad.ru/index.php?showtopi...=clearcommerror


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
JoyEx
Дата 28.12.2005, 11:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


Профиль
Группа: Участник
Сообщений: 323
Регистрация: 21.6.2005
Где: Москва, РФ

Репутация: 5
Всего: 12



Ответил тебе в твоей теме. Ты не проверяешь *lpEvtMask на EV_RXCHAR.



--------------------
Если ты уже никого не боишься, значит ты самый страшный 
PM IM ICQ AOL YIM MSN   Вверх
Dreamer_0x01
Дата 28.12.2005, 14:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Терминатор
**


Профиль
Группа: Участник
Сообщений: 780
Регистрация: 14.4.2005
Где: Санкт-Петербург

Репутация: 9
Всего: 12



Цитата(takedo @ 28.12.2005, 08:01)
Очевидно, что _\r\n - начало кадра, а _\r\n_ _OK_ - конец. Это может значить, что все пакеты передаются с такими символами в начале и конце. Следовательно, кто-то подумал о протоколе, а значит, при передаче у тебя никогда не должны встретиться в данных _\r\n или _\r\n_ _OK_.


Именно, но в добавок к этому нужно внимательно прочитать, в каком формате передаются данные, и собственно, что передается. Если ты будешь знать количество байт, которое будет передано между этими символами, то проблема отпадет сама собой, а эти символы ты сможешь ловить в качестве подтверждения правильности получения пакета.
Опять же, если у тебя информация в пакетах представлена в виде ASCII-символов (а такое очень часто делают), то у тебя действительно не встретятся эти символы в данных и все будет нормально.
Так что мой тебе совет, еще раз тебе говорю - отдельно разберись и с мануалом к телефону, чтобы четко понимать его протокол, и отдельно с ком-портом, чтобы при разборе протокола уже четко быть веренным, что сам ком-порт ты обслуживаешь правильно. Не торопись решать сразу все задачи, решай их по отдельности, и все получится.



--------------------
Нет ничего невозможного. Есть цели, и есть время и силы на их достижение.
PM ICQ   Вверх
takedo
Дата 28.12.2005, 15:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 501
Регистрация: 1.6.2005

Репутация: нет
Всего: 3



Dreamer_0x01 А вдруг у него HDLC? smile


--------------------
я не гольфист - я хоккеист
PM MAIL   Вверх
Бугемот
Дата 28.12.2005, 21:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 66
Регистрация: 27.12.2005

Репутация: 1
Всего: 1



Цитата(Dreamer_0x01 @ 28.12.2005, 14:18)
и отдельно с ком-портом, чтобы при разборе протокола уже четко быть веренным, что сам ком-порт ты обслуживаешь правильно.

Хм, тогда я не понимаю, откуда брать настройки (четность, биты и т.д.) - из мануала к модему? Сдается мне - все же для COM-порта. Откуда брать эти настройки? С учетом того, что ком-порт у меня эмулируется, т.к. физическое подключение телефона через usb.
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Visual C++/MFC/WTL | Следующая тема »


 




[ Время генерации скрипта: 0.1243 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.