Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Работа с 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   Вверх
takedo
Дата 29.12.2005, 08:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


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

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



Бугемот
Цитата
Хм, тогда я не понимаю, откуда брать настройки (четность, биты и т.д.) - из мануала к модему?
Определя, что модем отвечает "_\r\n - начало кадра, а _\r\n_ _OK_ - конец" ты и определил настройки, такие как четность, стоповые биты. Вернее сказать, что ты удачно подобрал параметры Com порта, так как если они бы не совпадали с телефонными, ты би ничего не определил так точно. А Com порт настраивать надо тому, кто с ним работает. Ты со своего компьютера настраиваешь порт на компьютере, телефон - порт на телефоне.


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


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


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

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



Это ноутбук?


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


Шустрый
*


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

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



Цитата(Dreamer_0x01 @ 29.12.2005, 18:36)
Это ноутбук?

Нет, обычный компьютер. Сотовый телефон подключен через USB-порт. COM-порт виртульаный. Формат вывода я определил терминальной программой - шлю AT-команду и смотрю ответ smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 09:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Поздравляю всех с Новым Годом!
Год прошел, но вопросы остались smile
Цитата(Dreamer_0x01 @ 27.12.2005, 22:09)
Я бы поместил функцию чтения в отдельный поток, в котором все время считывал бы по несколько символов (например, по 128, зависит от скорости порта, если болшая и стабильная, то можно и поболее) с небольшим таймаутом, и считанные символы помещал бы в специальный буфер-очередь, который сдвигал бы по мере забора из него символов уже твоим рабочим потоком

Т.е. все же читать кусками, но выставить небольшой таймаут. Т.к. если, например, взял я буфер 128 байт, а пришло данных меньше - все равно функция чтения завершится по таймауту?

Цитата(takedo @ 29.12.2005, 08:14)
А Com порт настраивать надо тому, кто с ним работает. Ты со своего компьютера настраиваешь порт на компьютере, телефон - порт на телефоне.

Где можно взять настройки для COM-порта? Он у меня виртуальный smile Открыл device manager, посмотрел какие там настройки, корректно ли их будет выставить и в моей программе через SetCommState?
Ну и остался вопрос по таймаутам - где их взять? Нашел доку к модему на AT-команды, про таймауты там ни слова smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 11:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Вот открываю порт:
Код

BOOL CMyCOMPort::OpenPort(LPCSTR strPortName)
{
    m_handlePort = CreateFile(strPortName, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, 
            NULL, NULL);
    ClearPort();
    GetCommState(m_handlePort, &dcb);
    dcb.DCBlength = sizeof(dcb);
    dcb.StopBits = 1;
    dcb.BaudRate = 57600;
    dcb.Parity = 0;
    dcb.ByteSize = 8;
    SetCommState(m_handlePort, &dcb);

    GetCommTimeouts(m_handlePort, &ct);
    ct.ReadIntervalTimeout = MAXDWORD;
    SetCommTimeouts(m_handlePort, &ct);

    return m_handlePort != INVALID_HANDLE_VALUE;
}


Вот пытаюсь прочитать данные:
Код

void ReadData()
{
        CServCOMPort::Instance()->OpenPort("COM3");
        CString cscommand;
        cscommand = "ATE0V0Q1\r";
        DWORD dwlength = cscommand.GetLength(), dwwrite = 0;
        BOOL bresult = CServCOMPort::Instance()->WritePort(cscommand, dwlength, dwwrite);
        if(!bresult)
            return;

        cscommand = "ATI0\r"; //Информация о модеме
        dwlength = cscommand.GetLength();
        dwwrite = 0;
        bresult = CServCOMPort::Instance()->WritePort(cscommand, dwlength, dwwrite);
        if(!bresult)
            return;

        CServCOMPort::Instance()->ClearPort();
        DWORD dwread = 0;
        dwlength = 127;
        char cData[128];
        memset(cData, 0, sizeof(cData));
        bresult = CServCOMPort::Instance()->ReadPort(cData, dwlength, dwread);
        CString gg;
        gg.Format("Прочитано байт: %d\r\nДанные: %s", dwread, cData);
        AfxMessageBox(gg);
}

В результате программа виснет, т.е. по таймауту чтение не завершается smile
Если прочитать 5-10 байт, то читается последняя записанная в порт команда, хотя ATE0, ATQ1 - выполнил. В терминальной программе все нормально работает, у меня - нет.
Подскажите, пожалуйста, что не так?
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 12:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


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

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



Попробуй
ReadIntervalTimeout = MAXDWORD
ReadTotalTimeoutConstant = 0
ReadTotalTimeoutMultiplier = 0


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


Шустрый
*


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

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



Цитата(JoyEx @ 1.1.2006, 12:29)
ReadTotalTimeoutConstant = 0
  ReadTotalTimeoutMultiplier = 0

Посмотрел в отладчике - значения 0.
Поставил вручную - ничего не изменилось smile
Как-то странно и непонятно все работает smile
В принципе, рассчитал значения:
На чтение 80 байт (хочу в такой буфер читать) при скорости 57600 б/с надо ~14мс. Межсимвольный интервал 0.0875мс
Пробовал выставить вручную - тот же эффет, программа виснет надолго smile
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 13:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Если читать заведомо меньшее количество байт (меньше чем придет), то все читается. Если выставить буфер больше - виснет smile
Вроде и таймауты выставлены smile что еще делать, не пойму smile
Добавлено @ 13:16
Если читать заведомо меньшее количество байт (меньше чем придет), то все читается. Если выставить буфер больше - виснет smile
О! Виснет не намертво, но таймаут - минуты три smile
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 14:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


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

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



Тогда ReadIntervalTimeout ~= 0


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


Шустрый
*


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

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



Да, сделал:
Код

ct.ReadIntervalTimeout = 0;
ct.ReadTotalTimeoutMultiplier = 1;
ct.ReadTotalTimeoutConstant = 21;

и вроде нормально работает.
Большое спасибо! smile
Добавлено @ 15:12
Вот только иногда после открытия посылаю команду, а выбираю оттуда всякий мусор, хотя вроде
PurgeComm(m_handlePort, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT|PURGE_RXABORT);
Делаю.
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 15:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


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

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



А что PurgeComm() возвращает? Если FALSE, то тогда поможет GetLastError.



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


Шустрый
*


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

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



GetLastError рекомендуется делать после любой операции с портом?
PM MAIL   Вверх
Бугемот
Дата 1.1.2006, 16:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Так, с таймаутами разобрался.
Стандартный для большинства модемов AT-команды нормально проходят. Ответ получаю.
Но как только посылаю команду для своего модема (например, получить производителя), в ответ - пусто smile
PM MAIL   Вверх
JoyEx
Дата 1.1.2006, 20:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


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

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



Цитата
Но как только посылаю команду для своего модема (например, получить производителя), в ответ - пусто smile


У тебя OEM? smile

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

- это про твой модем smile

C Новым 2006 Годом!


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


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


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

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



JoyEx

Да вы я тоже вижу фанатеете от текстов, произносимых Жуковым ;)

"Ты едешь туда, где закат такой малиновый, ты видел его дома лишь наполовину..." smile




Цитата
Т.е. все же читать кусками, но выставить небольшой таймаут. Т.к. если, например, взял я буфер 128 байт, а пришло данных меньше - все равно функция чтения завершится по таймауту?


Именно. Причем, как я уже говорил, лучше выставлять не междусимвольный таймаут, а общий.
Прочем, вижу, ты уже и сам это понял.

Цитата
GetLastError рекомендуется делать после любой операции с портом


Нет. Как правило, операции типа ReadFile, SetCommTimeOut. PurgeComm имеют какой-то возвращаемый результат, это либо BOOL, либо UINT,либо int, либо DWORD, ну либо там еще что-то. Так вот во всех инх в случае успеха возвращаются отличные от нуля значения, в случае неуспеха - 0.
То есть все подобные операции желательно заключать в следующие конструкции:

Код


if(Твоя_операция1(....))
{
//продолжаем работу
if(Твоя_операция2(....))
{
//продолжаем работу
//////
//..........
//и т.д.
}
else
{
int err=GetLastError(....);
//выдать сообщение об err;
return 0;//либо другой код ошибки для твоей функции
}

}
else
{
int err=GetLastError(....);
//выдать сообщение об err;
return 0;//либо другой код ошибки для твоей функции
}



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

Это сообщение отредактировал(а) Dreamer_0x01 - 2.1.2006, 23:40


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


Дядя
**


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

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



Цитата(Dreamer_0x01 @ 2.1.2006, 23:30 Найти цитируемый пост)

Да вы я тоже вижу фанатеете от текстов, произносимых Жуковым ;)

Да. Олег Жуков классный был человек.

Бугемот, а куда Вы пропали? У Вас всё получилось?


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


Шустрый
*


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

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



Всем здравствуйте.
Цитата(JoyEx @ 4.1.2006, 23:05 Найти цитируемый пост)

Бугемот, а куда Вы пропали? У Вас всё получилось?

Частично - с общим таймаутом на чтение работает с такими интерваллами:
ct.ReadTotalTimeoutMultiplier = 2;
ct.ReadTotalTimeoutConstant = 1;
Это, если честно, многовато. Но при меньших значениях данные не читаются. Придется подбирать все же таймауты, в документации я не нашел этого значения.
Ну а в остальном - все работает smile Порт опрашиваю по событию WM_TIMER с определенным интервалом.
Вам очень большое спасибо за советы !!!

Это сообщение отредактировал(а) Бугемот - 5.1.2006, 03:14
PM MAIL   Вверх
Бугемот
Дата 10.1.2006, 18:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем снова здравствуйте.
Программе мне была нужна для отправки SMS сообщений, по работе приходится много отсылать, вот и хочу сделать для себя небольшой терминал. Вот так отправляю:
Вот PDU:
07919732929090F0110B0B919732426654F70000A703D36110, программа pduspy раскодирует корректно.
пишу отправку:
AT+CMGS=24 (пробовал и макс. длину 140 - ничего)
07919732929090F0110B0B919732426654F70000A703D361101A (1A - это Ctrl+Z)
И ничего (
Что неправильно? и как по-другому можно сформировать Ctrl-z?

Попробовал просто сохранить сообщение в памяти, тоже не получается. Похоже, Ctrl-Z я неправильно посылаю.
Читаю сообщения и любую доступную служебную информацию с телефона через АТ-команды - без проблем
PM MAIL   Вверх
Dreamer_0x01
Дата 11.1.2006, 10:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



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


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


Эксперт
****


Профиль
Группа: Эксперт
Сообщений: 2304
Регистрация: 12.10.2003
Где: Поезд №21/22 ( ст . Прага )

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



Бугемот
посмотри здесь: codeproject.com.
Или здесь: Поиск. Ввведи Serial и нажми Search


--------------------
user posted image — регистрация доменов от 150 руб.
PM MAIL WWW ICQ   Вверх
Бугемот
Дата 11.1.2006, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А какие таймауты для записи примерно будут для порта со скоростью 57600Кб. На конце порта - сотовый телефон.
я выставил вот такие
Код

    ct.WriteTotalTimeoutMultiplier = 2;
    ct.WriteTotalTimeoutMultiplier = 100;

но результат все равно никакой smile
PM MAIL   Вверх
Бугемот
Дата 12.1.2006, 09:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Все, со всем разобрался. SMS не мог отправить потому что у моего телефона какой-то нестандартный режим отсылки сообщений smile Во всех доках написано по-другому, когда уже начал экспериментировать - наткнулся. Вобщем, все работает всем большое спасибо!
Остался один вопрос: я отсылаю команду и мне надо дождаться отклика, как его ждать? Я сейчас поставил sleep, т.е. просто тупо жду какое-то время, т.к. после отправки в порт команды отклик приходит с задержкой. А как правильно будет его получать, как отслеживать эту задержку? Ждать какое-то время до получения этого символа, но не больше определенного промежутка?

PM MAIL   Вверх
Dreamer_0x01
Дата 12.1.2006, 15:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Таймауты на то и созданы, чтобы грамотно ждать отклика. Но если уж не хочется переделывать - лучше не Sleep использовать, так ты поток усыпляешь намертво, а это не есть хорошо, лучше в цикле делай ReadFile, пока не прочитает то, что тебе нужно, либо пока не кончется установленное тобой количество попыток чтения. (оно соответственно будет равно твоему нужному времени, деленному на твой таймаут, установленный для чтения. )

Но вообще...Не понимаю, чем же тебе не понравились установки вида

Код

    COMMTIMEOUTS ctm;
//....................
    ctm.ReadIntervalTimeout=0;
    ctm.ReadTotalTimeoutConstant=ТВОЙ_TIMEOUT;//в миллисекундах
    ctm.ReadTotalTimeoutMultiplier=0;
    SetCommTimeouts(ТВОЙ_ХЕНДЛ,&ctm);


И усе, никаких проблем!
Устанавливаешь вместо ТВОЙ_TIMEOUT твое время, в течение которого нужно ждать приема, и все!
Функция ReadFile будет ждать приема указанного тобой количества символов в течение времени ТВОЙ_TIMEOUT (в миллисекундах). Очень удобно!




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


Шустрый
*


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

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



ctm.ReadTotalTimeoutConstant=ТВОЙ_TIMEOUT; - влияет на все операции чтения.
А отклик мне надо ждать только на команду перед записью, поэтому тормозить все чтение общим тайм-аутом не очень хочется. У меня сейчас стоит межсимвольный - 2мс, но 5Кб считываются не 10 секунд, а меньше. Если выставить межсимвольный в 0, а Constant'ный - например в 100, то чтение визуально выполняется быстрее. Поэтому я им не воспользовался константным. Sleep мне тоже не нравится smile
О, проверил сейчас константный - работает! Осталось один нюанс уточнить - сколько же ждать smile
Большое спасибо!
Добавлено @ 18:36
Причем если выставить константу заведомо больше, чем надо. То и ожидание будет длиться все это время, хотя данные уже точно пришли в порт smile
Добавлено @ 18:37
Вобщем, или это не так уж удобно, или я чего-то не понимаю smile
PM MAIL   Вверх
Бугемот
Дата 12.1.2006, 18:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Проверил только что: если перед моей командой на запись (сначала команда, жду отклик, запись) отправить какую-нибудь другую - все, отклика с таймаутом в 100мс я дождусь. Если же сразу после открытия отправить эту команду - не дожидаюсь, т.е. отклик не приходит, ну и как тут быть smile
PM MAIL   Вверх
Dreamer_0x01
Дата 12.1.2006, 19:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Бугемот @ 12.1.2006, 18:36 Найти цитируемый пост)

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

А менять таймауты в процессе работы не пробовал? smile


Цитата(Бугемот @ 12.1.2006, 18:36 Найти цитируемый пост)

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


1. А откуда ты знаешь, что данные пришли?
2. Поверь, у меня это все работает, ведь это моя работа, и с ожиданием все в порядке, как только в приемном буфере порта накопится нужное количество символов, ожидание прекращается.
3. Ты случаем не в дебаггере это смотришь? ;)



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


Шустрый
*


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

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



Цитата(Dreamer_0x01 @ 12.1.2006, 19:29 Найти цитируемый пост)

А менять таймауты в процессе работы не пробовал?

Если честно - нет, такое практикуется вообще? У меня раз в 15 секунд из порта принимаются данные. Теперь проблема - в записи.
Цитата(Dreamer_0x01 @ 12.1.2006, 19:29 Найти цитируемый пост)

3. Ты случаем не в дебаггере это смотришь? ;)

нет smile этот совет я уже проверил - в дебаггере не работает корректно smile
Т.е. рекомендуете для команд записи выставлять таймаут на чтение - больше чем на обычное чтение? Т.е. отправляется запрос на передачу данных (вот тут я и жду отклика), и в данном случае - изменить время ожидания?
PM MAIL   Вверх
Бугемот
Дата 13.1.2006, 10:12 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Всем еще раз здравствуйте. Никак не могу получить нормально отклик. ВОт код:

Код

CString CSMSDoc::SendSMS(CString csDA, CString csText)
{
    COMMTIMEOUTS ctCurrent = CSMSCOMPort::Instance()->GetCommSettings();
    ctCurrent.ReadTotalTimeoutMultiplier = 1; 
    ctCurrent.ReadTotalTimeoutConstant = 3000; // таймаута в 3 секунды 100% должно хватить для получения отклика
    CSMSCOMPort::Instance()->SetCommSettings(ctCurrent); // устанавилваю новые таймауты

    // Выполняем отправку
    CString cscommand, csresult;
    cscommand.Format("AT+CMGS=%d\r", icommand_length);

    BOOL bresult = FALSE;
    CSMSCOMPort::Instance()->ClearPort();
    DWORD dwcommand_length = cscommand.GetLength();
    DWORD dwwritten_bytes = 0;
    bresult = CSMSCOMPort::Instance()->WritePort(cscommand, dwcommand_length, dwwritten_bytes);
    if(dwwritten_bytes == 0 || !bresult)
        return ("\r\nError write SMS-send command");

    char buffer[50]; // Должен прийти отклик в виде символа >
    DWORD dwnumber_to_read_bytes = 50;
    DWORD dwnumber_read_bytes = 1;
    bresult = TRUE;
    memset(buffer, 0, sizeof(buffer));
    while(dwnumber_read_bytes != 0)
        bresult = CSMSCOMPort::Instance()->ReadPort(buffer, dwnumber_to_read_bytes, dwnumber_read_bytes);
    for(DWORD i = 0; i < dwnumber_read_bytes; i++)
        csresult += buffer[i];
    return csresult;
}

Вот, собственно, и все. Отклика я не дождался smile
Чего-то я не понимаю smile
PM MAIL   Вверх
Dreamer_0x01
Дата 13.1.2006, 16:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Бугемот @ 12.1.2006, 20:12 Найти цитируемый пост)

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


Зачем вообще выставлять таймаут на запись? Я все таймауты, начинающиеся со слова Write, присвоил нулю, и все прекрасно работает.

Код

while(dwnumber_read_bytes != 0)    
        bresult = CSMSCOMPort::Instance()->ReadPort(buffer, dwnumber_to_read_bytes, dwnumber_read_bytes);


Может быть, ты хотел сделать так:
Код

while(dwnumber_read_bytes == 0)
//......


? smile


Я бы посоветовал не использовать подобные конструкции. Даже если все работает - во время работы выдергиваешь кабель, получаешь жуткие тормоза, и предложение отправить отчет в микрософт.
обязательно в таих конструкциях используй счетчик попыток.
То есть, например, так:
Код

unsigned short nPopitok=1000;
while((dwnumber_read_bytes == 0)&&(nPopitok))
{    
        bresult = CSMSCOMPort::Instance()->ReadPort(buffer, dwnumber_to_read_bytes, dwnumber_read_bytes);
nPopitok--;
}
if(!nPopitok)
{
//Например, вот так:
AfxMessageBox(_T("Количество попыток чтения исчерпалось"));
}


Вот так ты свою программу не завесишь.

Впрочем, это так, лирическое отступление, поделился печальным опытом, так сказать ;)
А еще...Ты параметр dwnumber_read_bytes в функцию CSMSCOMPort::Instance()->ReadPort как передаешь?
В фунции что у тебя принимается - сам параметр, или указатель, или ссылка, с этим усе в порядке? ;)

Это сообщение отредактировал(а) Dreamer_0x01 - 13.1.2006, 16:45


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


Шустрый
*


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

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



"Количество попыток" - а зачем же тогда таймаут на чтение ??? Разве смысл не один и тот же - в течение какого-то времени опрашивать порт?
Цитата(Dreamer_0x01 @ 13.1.2006, 16:39 Найти цитируемый пост)

В фунции что у тебя принимается - сам параметр, или указатель, или ссылка, с этим усе в порядке? ;)
- передается ссылка, с этим все в порядке smile
Проблема в том, что я не могу получить отклик, хотя таймаут на чтение выставлен заведомо бОльший. Зато через некоторое время, после отпарвки какой-нибудь "левой" команды - получаю отклик smile
PM MAIL   Вверх
Бугемот
Дата 13.1.2006, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Цитата(Dreamer_0x01 @ 13.1.2006, 16:39 Найти цитируемый пост)

Может быть, ты хотел сделать так:
код C++
while(dwnumber_read_bytes == 0)

Почему - так? я перед циклом выставляю dwnumber_read_bytes = 1 и соответственно - жду первого пришедшего символа.
Хотя, я тогда вообще перестал что-то понимать: как считать данные из порта, в цикле? Данные я запрашиваю порциям - в разных случаях по-разному. От 20 до 200 байт, в зависимости от того, что должен получить. И таймауты теперь уже меняю в процессе работы smile
Для чтения большого объема выделяю общий буфер в 8Кб и заполняю его порциями по примерно 200 байт, чтение - в цикле.
Dreamer_0x01, если Вас не затруднит, напишите, пожалуйста, как правильно получить данные из порта после отсылки команды? С учетом того что может прийти большой объем и чтение - порциям в цикле while?
Заранее большое спасибо!

Это сообщение отредактировал(а) Бугемот - 13.1.2006, 21:32
PM MAIL   Вверх
Dreamer_0x01
Дата 13.1.2006, 21:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



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


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


Шустрый
*


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

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



Цитата(Dreamer_0x01 @ 13.1.2006, 21:30 Найти цитируемый пост)

Еще раз. Если ты устанавливаешь таймаут заведомо больший, чем время, необходимое тебе для того, чтобы дождаться отклика, то и цикл тебе здесь никакой не нужен.

Соответственно, операция чтения повесит поток на время таймаута?
Цитата(Dreamer_0x01 @ 13.1.2006, 21:30 Найти цитируемый пост)

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

ну это равносильно тому, что выставить таймаут. Причем мне кажется - с таймаутом надежнее.
Цикл я использую для того, чтобы получить большой объем данных маленькими порциями

PM MAIL   Вверх
Dreamer_0x01
Дата 14.1.2006, 00:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(Бугемот @ 13.1.2006, 21:34 Найти цитируемый пост)

Соответственно, операция чтения повесит поток на время таймаута?

В общем, да. Именно поэтому я и предлагала анализировать количество попыток, а не делать одним единым большим таймаутом.
Цитата(Бугемот @ 13.1.2006, 21:34 Найти цитируемый пост)

Причем мне кажется - с таймаутом надежнее.
Цикл я использую для того, чтобы получить большой объем данных маленькими порциями

Я понимаю.
надежность...не факт. Мне вот как раз кажется, что чем чаще контролиреушь ситуацию, тем лучше.

Цитата(Бугемот @ 13.1.2006, 21:08 Найти цитируемый пост)

Dreamer_0x01, если Вас не затруднит, напишите, пожалуйста, как правильно получить данные из порта после отсылки команды? С учетом того что может прийти большой объем и чтение - порциям в цикле while?

Не затруднит, но пожалуйста, четко ответь на вопрос - ты знаешь, сколько символов должно прийти после запроса, или нет? От этого и будет зависеть алгоритм.


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


Шустрый
*


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

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



Цитата(Dreamer_0x01 @ 14.1.2006, 00:01 Найти цитируемый пост)

Не затруднит, но пожалуйста, четко ответь на вопрос - ты знаешь, сколько символов должно прийти после запроса, или нет? От этого и будет зависеть алгоритм.

Нет, не знаю. Есть два варианта:
1. Когда запрашиваю смс-сообщения из телефона. Здесь теоретически до 20-25Кб данных может прийти
2. Когда посылаю сообщение - надо дождаться отклика. Максимум 50-70 символов.
НО точно - не знаю
PM MAIL   Вверх
Dreamer_0x01
Дата 14.1.2006, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



хорошо, тогда вопрос такой - как ты определяешь конец ответа твоего телефона?


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


Шустрый
*


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

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



Есть два варианта:
1. я знаю, что объем ожидаемых данных не превышает, например, 100 байт. ТОгда делаю так:
Код

    ctCurrent = CServCOMPort::Instance()->GetCommSettings();
    ctCurrent.ReadTotalTimeoutMultiplier = 0;
    ctCurrent.ReadTotalTimeoutConstant = 5000; // таймаут в 5 секунд
    CServCOMPort::Instance()->SetCommSettings(ctCurrent);

    memset(buffer, 0, READ_RESPONCE_BUFFER_SIZE); //  READ_RESPONCE_BUFFER_SIZE - указан 100
    DWORD dwnumber_to_read_bytes = READ_RESPONCE_BUFFER_SIZE;
    DWORD dwnumber_read_bytes = 0;
    BOOL bresult = FALSE;
    memset(buffer, 0, sizeof(buffer));
    bresult = CServCOMPort::Instance()->ReadPort(buffer, dwnumber_to_read_bytes, dwnumber_read_bytes);

соответственно я жду 100 байт в течение 5 секунд. Кстати, попутно вопрос: если данные придут раньше - чтение завершится, или все же будет ждать 100 байт и завершится по таймауту?
2. Заранее не знаю, сколько придет данных, может и 100 байт, а может и больше. Тогда читаю блоками по 200 байт (максимальная длина одного сообщения + служебная информация)
Код

    char buffer[200];
    DWORD dwnumber_to_read_bytes = 200;
    DWORD dwnumber_read_bytes = 1;
    BOOL bresult = FALSE;
    memset(buffer, 0, sizeof(buffer));
    memset(m_pBuffer, 0, READ_BUFFER_SIZE); // Буфер для всего объема данных, у меня 20Кб
    int itotal_read_bytes = 0;
    while(dwnumber_read_bytes != 0)
    {
        bresult = CServCOMPort::Instance()->ReadPort(buffer, dwnumber_to_read_bytes, dwnumber_read_bytes);
        if(dwnumber_read_bytes != 0)
        {
            for(DWORD i = 0; i < dwnumber_read_bytes; i++)
                m_pBuffer[itotal_read_bytes + i] = buffer[i];
            itotal_read_bytes += dwnumber_read_bytes;
        }
        memset(buffer, 0, sizeof(buffer));
    }

ну и читаю данные до тех пор, пока они читаются.
Вот так делаю
PM MAIL   Вверх
JoyEx
Дата 15.1.2006, 08:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Дядя
**


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

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



Бугемот
У тебя только один выход из сложившейся ситуации - WaitCommEvent, и будешь знать что-как с уст-вом


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


Шустрый
*


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

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



Цитата(JoyEx @ 15.1.2006, 08:32 Найти цитируемый пост)

Бугемот
У тебя только один выход из сложившейся ситуации - WaitCommEvent, и будешь знать что-как с уст-вом

это уже асинхронный режим. Мне он не подойдет: я отправляю sms-сообщение через телефон, т.е. реально оно в телефоне не сохраняется. Когда приходит ответ - в нем информация только о том, что сообщение отправлено. Ну и как теперь угадать - какое-же из двух моих отправленных сообщений - действительно отправлено? Вот и приходится ждать отлик сразу же после отправки!
PM MAIL   Вверх
Dreamer_0x01
Дата 15.1.2006, 13:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



WaitCommEvent можно и для ожидания отклика тоже использовать.
Ладно, погоди, щас до работы доеду, и оттуда напишу свой вариант.


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


Шустрый
*


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

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



Посмотрел еще раз ветку. Действительно, воспользуюсь вариантомDreamer_0x01, т.е. буду опрашиват порт 7 раз с таймаутом в секунду (например), ну или с таймаутом в полсекунды. И вынесу запись в отдельный поток. Получится отправка в среднем 10-15 сообщений в минуту, вроде пока должно хватить, хотя на пике явно будет нагрузка больше. Ну, это уже с заделом на будущее smile
Мне смысла нет использовать WaitCommEvent, т.к. пока не придет отклик, следующее сообщение посылать нет смысла. Я просто отклики друг от друга не отличу и не буду знать, какое же из двух сообщений действительно отправилось.
PM MAIL   Вверх
Dreamer_0x01
Дата 16.1.2006, 00:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



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


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


 




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


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

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