C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Особенности COM порта  (Прочитано 12728 раз)
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« : 20 Май 2011, 16:33:24 »

Привет всем! Столкнулся со следующей проблемой. Создаю программу для "общения" с прибором через COM порт. Причем общаться можно либо через адаптер (по проводам), либо через инфракрасный порт. И адаптер и инфракрасник обнаруживают себя в компе как COM порт. Когда я "общаюсь" с прибором через адаптер, то все отлично: программа отсылает и принимает команды. Когда же я пытаюсь отправить команду через инфракрасный порт, то ответа нет (однако заводской программой все получается!).
Мне припоминается, что в ВСВ6 все работало, а в XE уже нет. Может кто-то знает в чем причина?
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #1 : 20 Май 2011, 20:40:05 »

для начала
1. берешь телефон
2. включаешь на нем видеокамеру
3. запускаешь длииииииинную передачу данных через инфраред
4. наблюдаешь ее моргание через камеру - значит работает, выбран нужный порт
+ все то же опробовать на штатной заводской программе
далее по результатам
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #2 : 20 Май 2011, 20:58:21 »

Zor, сделал все как ты посоветовал. У меня инфраред обнаруживается в компе как COM3. В заводской программе ставлю в настройках порта COM3, пробую отправить команду. Результат - прибор корректно отвечает, на инфракраснике моргает лампочка. Потом в своей программе открываю COM3 и пробую отправить команду. Результат - прибор молчит, лампочка не моргает...
Может я не правильно открываю COM порт? Вот код:
Код
UnicodeString Msg = "\\\\.\\" + APortName.UpperCase();
ComHandle = CreateFile(Msg.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
Больше всего меня смущает первая строка... Пример мне ты давал 
« Последнее редактирование: 20 Май 2011, 21:14:26 от d7d1cd » Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #3 : 20 Май 2011, 21:27:15 »

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

далее - немного смущает UnicodeString и ".c_str()"...
и примера как настраиваешь порт и пишешь тоже не видно.


Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #4 : 20 Май 2011, 22:05:26 »

Смотрел в диспетчере устройств - там один порт.
Настройка порта:
Код
HANDLE TForm1::OpenAndSetupPort (UnicodeString APortName, int ASpeed, int AByteSize, int AParity, int AStopBits)
{
HANDLE ComHandle;
DCB ComDCB;
COMMTIMEOUTS ComTimes;
UnicodeString Msg = "\\\\.\\" + APortName.UpperCase();
 
ComHandle = CreateFile(Msg.t_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (ComHandle == INVALID_HANDLE_VALUE)
 {
 Msg = "Ошибка при открытии порта " + APortName + ":\n" + GetLastError(); goto OnError;
 }
 
ZeroMemory(&ComDCB, sizeof(ComDCB));
ComDCB.DCBlength = sizeof(ComDCB);
if (!GetCommState(ComHandle, &ComDCB))
 {
 Msg = "Ошибка при получении параметров порта " + APortName + ":\n" + GetLastError(); goto OnError;
 }
ComDCB.BaudRate = ASpeed;
ComDCB.ByteSize = AByteSize;
ComDCB.Parity   = AParity;
ComDCB.StopBits = AStopBits;
ComDCB.fBinary  = 1;
ComDCB.fParity  = (ComDCB.Parity != NOPARITY) ? 1 : 0;
ComDCB.fOutxCtsFlow = 0;
ComDCB.fOutxCtsFlow = false;
ComDCB.fOutxDsrFlow = false;
ComDCB.fDtrControl = DTR_CONTROL_DISABLE;
ComDCB.fDsrSensitivity = false;
ComDCB.fNull = false;
ComDCB.fRtsControl = RTS_CONTROL_DISABLE;
ComDCB.fOutX = 0;
ComDCB.fInX = 0;
ComDCB.fAbortOnError = false;
if (!SetCommState(ComHandle, &ComDCB))
 {
 Msg = "Ошибка при настройке параметров порта " + APortName + ":\n" + GetLastError(); goto OnError;
 }
 
if (!GetCommTimeouts(ComHandle, &ComTimes))
 {
 Msg = "Ошибка при получении таймаутов порта " + APortName + ":\n" + GetLastError(); goto OnError;
 }
ComTimes.ReadIntervalTimeout         = MAXDWORD;
ComTimes.ReadTotalTimeoutMultiplier  = 0;
ComTimes.ReadTotalTimeoutConstant    = 300;
ComTimes.WriteTotalTimeoutMultiplier = 0;
ComTimes.WriteTotalTimeoutConstant   = 0;
if (!SetCommTimeouts(ComHandle, &ComTimes))
 {
 Msg = "Ошибка при настройке таймаутов порта " + APortName + ":\n" + GetLastError(); goto OnError;
 }
 
SetupComm(ComHandle, 1024, 1024);
PurgeComm(ComHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
 
ErrorInfo = "Успешно завершено";
return ComHandle;
 
OnError:
if (ComHandle != INVALID_HANDLE_VALUE) CloseHandle(ComHandle);
 
ErrorInfo = Msg;
return NULL;
}

Отправка в порт:
Код
DWORD temp;
BYTE comanda[4];
comanda[0] = 0x00;
comanda[1] = 0x00;
comanda[2] = 0x01;
comanda[3] = 0xB0;
 
WriteFile(ComHandle, &comanda, 4, &temp, NULL);  //Отправляем команду прибору
ReadFile(ComHandle, &comanda, 4, &temp, NULL);
 

UnicodeString применяю по причине использования Builder XE: функция CreateFile в первом параметре требует wchar_t.
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #5 : 20 Май 2011, 22:15:24 »

тогда кури протокол обмена до просветления.

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


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #6 : 20 Май 2011, 22:42:51 »

Протокол обмена прокурен до дыр. Приведенный код без изменений применялся для тестирования COM порта при подключении не через инфраред, а через проводной интерфейс. Все работает, команды уходят к прибору и приходят от него.
SetCommState пробовал закомментировать после использования стандартной программы - не помогло...
Как же быть? 
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #7 : 20 Май 2011, 23:09:33 »

тогда проверяй что штатная работает именно через этот порт а не как то еще.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #8 : 21 Май 2011, 09:34:57 »

тогда проверяй что штатная работает именно через этот порт а не как то еще.


Как можно это определить? В самой программе есть настройки порта. Там можно выбрать имя порта. Это имя там такое же, как и в моей программе...
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #9 : 21 Май 2011, 10:47:59 »

запусти в работу штатную прогу и при этом запроси список свободных портов.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #10 : 21 Май 2011, 10:50:24 »

запусти в работу штатную прогу и при этом запроси список свободных портов.

А запросить можно через Диспетчер устройств или как-то программно?

P.S. Может тебе что-то подскажет. Сделал скриншоты свойств одного и другого порта. Порт COM3 - это инфракрасник и через него со своей программы я не могу общаться с прибором. Порт COM9 - это проводной адаптер и через него я нормально общаюсь с прибором.
« Последнее редактирование: 21 Май 2011, 11:03:15 от d7d1cd » Записан
Asher
Администратор


Сказали спасибо: +111/-5
Offline

Сообщений: 425


« Ответ #11 : 21 Май 2011, 13:19:59 »

Привет.
DTR поднять.
RTS при передаче поднять, после передачи сбросить.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #12 : 21 Май 2011, 13:42:20 »

Привет.
DTR поднять.
RTS при передаче поднять, после передачи сбросить.

Asher, сделал в настройках порта так:
Код
ComDCB.fDtrControl = DTR_CONTROL_ENABLE;

И все заработало. Вопрос: обязательно ли выполнять манипуляции с RTS? И если да, то как проще всего это сделать. Функция, может, есть?
Записан
Asher
Администратор


Сказали спасибо: +111/-5
Offline

Сообщений: 425


« Ответ #13 : 21 Май 2011, 14:41:18 »

Привет.
Если заработало - ничего больше не трогайте. 
вероятно драйвер сам отрабатывает.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #14 : 22 Май 2011, 15:02:15 »

В процессе отладки программы обнаружилось следующее: иногда при начале передачи лампочка на инфракраснике загорается и не гаснет. Программа зависает. После повторного запуска все нормально. Или еще: компьютер отправляет команду в инфракрасник, а при чтении получает то же, что отправил. Даже в том случае, если ИК-порт направлен "в никуда". В чем может быть причина? Может необходимо как-то правильно настроить порт?

P.S. Прибор сам не может послать команду в инфракрасник, он только отвечает на команды, присланные от компа. Ответ он дает спустя около 15 мс после окончания приема команды.
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #15 : 23 Май 2011, 00:55:14 »

поиграйся с таймаутами
Записан
Mimik
Если ваша проблема не ищется в поиске и гугле, если ее нет в книгах, то я стану на нее тратить время....
Участник


Сказали спасибо: +90/-14
Offline

Сообщений: 661

TestNewOut


« Ответ #16 : 23 Май 2011, 08:27:53 »

Хм, а почему не взять утилиту производителя и не взять PortMon и посмотреть что куда шлется от программы производителя а потом проверить свою м?
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #17 : 23 Май 2011, 21:50:16 »

поиграйся с таймаутами

Кстати о птичках... Нашел сайт http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/str_commtimeouts.htm? прочитал описание структуры, и... не понял... Объясните, пожалуйста назначение 2-х полей структуры: ReadIntervalTimeout и ReadTotalTimeoutConstant.
Записан
Zor
Глобальный модератор


Сказали спасибо: +158/-30
Offline

Сообщений: 2946


« Ответ #18 : 23 Май 2011, 22:23:15 »

ReadIntervalTimeout - если интервал времени с момента приема последнего байта из порта превысит данное значение (в мс), ReadFile отваливается по таймауту.
если = MAXDWORD - не используется.

ReadTotalTimeoutConstant - количество мс, добавляемое к произведению числа запрошенных байт на ReadTotalTimeoutMultipler.
используется для вычисления общего времени до таймаута с начала чтения из порта через ReadFile.
например, если читаем 10 байт и ReadTotalTimeoutConstant = 100, и ReadTotalTimeoutMultipler = 5, таймаут наступит через 150 мс.
 
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #19 : 07 Июль 2011, 21:07:20 »

При чтении из порта обязательно указывать точное значение ожидаемого количества байт? Или можно указать максимальный размер принимающего буфера?
Записан
Rius
Давний друг


Сказали спасибо: +116/-5
Offline

Сообщений: 753


« Ответ #20 : 07 Июль 2011, 21:37:20 »

Можно указать размер буфера.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #21 : 12 Июль 2011, 06:48:27 »

Задам в этом же топике еще один вопрос. Он так же по COM порту.
Читал, что некоторые устройства, подключаемые к COM порту, могут от него получать питание. Понимаю, что под питание конфигурируются определенные выводы. Не подскажите, какие именно выводы и как надо программно сконфигурировать порт?
Записан
Rius
Давний друг


Сказали спасибо: +116/-5
Offline

Сообщений: 753


« Ответ #22 : 12 Июль 2011, 07:56:41 »

Видимо это о выводах DTR и RTS. С них можно снять лишь очень небольшой ток.
Пример: Изолированный интерфейс RS-232. Лучше использовать USB порт.
Записан
d7d1cd
Участник


Сказали спасибо: +59/-24
Offline

Сообщений: 1005


« Ответ #23 : 22 Июль 2011, 06:53:39 »

Работаю с портом, к которому подключен инфракрасный адаптер, и заметил это: при открытии и настройке порта все проходит гладко. Далее я подготавливаю команду, отсылаю функцией WriteFile в порт, читаю ответ функцией ReadFile. И вот тут может произойти одно из двух событий: либо я получаю корректный ответ, либо я получаю абсолютно ту же самую команду, которую отправил в порт. Как будто поток из выходного буфера порта просто скопировался во входной. Причем не важно куда направлен инфракрасный порт. Его можно вообще закрыть - эффект остается.
Пока решаю проблему так: закрываю COM порт и тут же его открываю с абсолютно теми же параметрами, что и раньше. И все начинает работать правильно.
Подскажите, что на чудеса творятся?

P.S. Такой эффект происходит только когда к порту подключен инфракрасный адаптер. С проводным адаптером такого не наблюдается.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  




....

Powered by SMF 1.1.21 | SMF © 2025, Simple Machines
Страница сгенерирована за 0.066 секунд. Запросов: 21.