Непонятка с активностью окон
Вот такая ситуёвина: есть прога, которая по таймеру общается с COM портом. Когда окно активно - все ОК. Как только окно становится неактивным передача в ком порт обрывается. При том обрывается в любом месте пакета (весь пакет не проходит), и соотв. вылазит ошибка. Как сделать так, что бы работа программы не зависила от состояния активности окна?
Николай.
зы: На другой стороне все нормально.
Hi!
Вот такая ситуёвина: есть прога, которая по таймеру общается с COM портом. Когда окно активно - все ОК. Как только окно становится неактивным передача в ком порт обрывается. При том обрывается в любом месте пакета (весь пакет не проходит), и соотв. вылазит ошибка. Как сделать так, что бы работа программы не зависила от состояния активности окна?
Николай.
зы: На другой стороне все нормально.
Да не должна бы зависеть. Запустите WinSight32, если после деактивизации окна сообщения WM_TIMER перестают поступать, значит где-то у Вас таймер отключается или блокируется. Если сообщения поступают, но передачи в порт нет, то с Вашим алгоритмом работы COM порта что-то неладное.
А какая "вылазит" ошибка и где именно?
Да не должна бы зависеть. Запустите WinSight32, если после деактивизации окна сообщения WM_TIMER перестают поступать, значит где-то у Вас таймер отключается или блокируется. Если сообщения поступают, но передачи в порт нет, то с Вашим алгоритмом работы COM порта что-то неладное.
А какая "вылазит" ошибка и где именно?
Да не должен таймер блокироваться. Никто его не блокирует... Вполне вероятно, что глючит компонент работающий с СОМом (cport). Но почему-то именно при неактивном окне. А ошибка в том, что передача прекращается Алгоритм у меня примерно такой: Передаем 8 байт, ждем пока контроллер ответит, если отвер правильный, выставляем флаг, и посылаем следующие 8 байт и т.д. Это в кратце.
Да не должен таймер блокироваться. Никто его не блокирует... Вполне вероятно, что глючит компонент работающий с СОМом (cport). Но почему-то именно при неактивном окне. А ошибка в том, что передача прекращается Алгоритм у меня примерно такой: Передаем 8 байт, ждем пока контроллер ответит, если отвер правильный, выставляем флаг, и посылаем следующие 8 байт и т.д. Это в кратце.
Поскольку приём-передача производятся по таймеру (насколько я понял), то можно обойтись и без компонента. Сериальные компоненты, как правило, черезчур наворочены, OVERLAPPED и всё такое прочее. Используйте CreateFile, GetCommState, SetCommState, GetCommTimeouts, SetCommTimeouts, SetupComm, PurgeComm, EscapeCommFunction (в таком порядке) для настройки порта, и ReadFile и WriteFile для приёма-передачи в процедуре таймера.
Поскольку приём-передача производятся по таймеру (насколько я понял), то можно обойтись и без компонента. Сериальные компоненты, как правило, черезчур наворочены, OVERLAPPED и всё такое прочее. Используйте CreateFile, GetCommState, SetCommState, GetCommTimeouts, SetCommTimeouts, SetupComm, PurgeComm, EscapeCommFunction (в таком порядке) для настройки порта, и ReadFile и WriteFile для приёма-передачи в процедуре таймера.
К сожалению, я не могу использовать данные функции. По "политическим" соображениям конторы... Придется мучаться с cport. Я вот думаю может запихнуть передачу/прием в поток с максимальным приоритетом?
Всё же мне кажется, что Cport не настроен должным образом. Что за окна у Вас, которые деактивируются не вовремя и гробят порт? А в исходниках CPort поковыряться?
Если хотите, можете проконтролировать активность на порту с помощью программы PortMon: http://www.sysinternals.com
Всё же мне кажется, что Cport не настроен должным образом. Что за окна у Вас, которые деактивируются не вовремя и гробят порт? А в исходниках CPort поковыряться?
Сенькс! Программка зело пользительна. С ее помощью увидел ошибочки и подстроился под них. Но компонент все равно глючный... Оказалось л\дело вовсе не в активности...
Сенькс! Программка зело пользительна. С ее помощью увидел ошибочки и подстроился под них. Но компонент все равно глючный... Оказалось л\дело вовсе не в активности...
А в чём глюкавость? Если не в активности, то в чём (хе-хе - в пассивности), если не секрет?
А в чём глюкавость? Если не в активности, то в чём (хе-хе - в пассивности), если не секрет?
Там есть Event под названием RxChar. Он, вроде как, проявляется когда в порт приходит 1 байт инфы. Так вот как оказалось нифига подобного. Он мог высачить и сразу при 2-х или более байтах. Может так было задумано, но нигде об этом не сказано :( Программкой было данное дело отслежано и был написано 3 строки обработки всех пришедших байт. Вроде так.
Там есть Event под названием RxChar. Он, вроде как, проявляется когда в порт приходит 1 байт инфы. Так вот как оказалось нифига подобного. Он мог высачить и сразу при 2-х или более байтах. Может так было задумано, но нигде об этом не сказано :( Программкой было данное дело отслежано и был написано 3 строки обработки всех пришедших байт. Вроде так.
Насчёт RxChar - это событие говорит о том что по крайней мере один байт получен и находится в приёмном буфере. За подробностями могу отослать к статье Allen'а Denver'а "Serial Communications in Win32" из MSDN, а могу написать и сам, что могут возникнуть проблемы при поступлении нескольких байтов подряд в быстрой последовательности. Вообще, ещё программируя для Windows 3.1 я читал нечто подобное.
Кстати, рекомендую к чтению эту статью, там много полезного.
В процедуре таймера просто читайте из порта, есть данные - Вы их получите, нет данных - запросите снова. А CommEvent'ы не используйте вовсе.
Извините, что долго не отвечал.
В процедуре таймера просто читайте из порта, есть данные - Вы их получите, нет данных - запросите снова. А CommEvent'ы не используйте вовсе.
В данный момент я обошел эту ошибку следующим образом. Я оставил onRxChar и добавил еще один таймер, который прибавляет 1 к переменной каждую 0.1 сек. В onRxChar я обнуляю эту переменную, а в том же таймере проверяю её равенство 10. Как только это равенство случается все обнуляется и запускается заново. На другой стороне я использую микропроцессор у которого программирование USARTa прозрачнее....
Еще вырос вопрос: можно ли вытащить параметры порта для предустановки? Меня интересует только количество COM-портов и их идентификаторы.
Что за компонет такой, у которого нет нормального метода чтения порта! На кой нужен этот CommEvent, да ещё такой ублюдский, как RxChar!
Насчёт предустановки:
Есть такие функции, GetDefaultCommConfig/SetDefaultCommConfig, смотрите в подсказке, там хорошо написано. Примерчик использования (комбинированный список заполнен именами типа ком1 и т.д.):
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
Providers[PST_UNSPECIFIED] = "Неизвестное устройство";
Providers[PST_RS232] = "Порт RS-232";
Providers[PST_PARALLELPORT] = "Параллельный порт";
Providers[PST_RS422] = "Порт RS-422";
Providers[PST_RS423] = "Порт RS-423";
Providers[PST_RS449] = "Порт RS-449";
Providers[PST_MODEM] = "Модем";
Providers[PST_FAX] = "Факс";
Providers[PST_SCANNER] = "Сканер";
Providers[PST_NETWORK_BRIDGE] = "Сетевой мост";
Providers[PST_LAT] = "LAT";
Providers[PST_TCPIP_TELNET] = "PST_TCPIP_TELNET";
Providers[PST_X25] = "X25";
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ComboBox1Change(TObject *Sender)
{
char pname[10];
sprintf(pname,"\\\\.\\Com%d",ComboBox1->ItemIndex+1);
COMMCONFIG ccfg;
ccfg.dwSize = sizeof(ccfg);
unsigned long cbsize = sizeof(ccfg);
if(::GetDefaultCommConfig(pname,&ccfg,&cbsize))
{
StaticText1->Caption = Providers[ccfg.dwProviderSubType].c_str();
}
else
{
StaticText1->Caption = "Устройство отсутствует";
}
}
Обратите внимание на конструкцию "\\\\.\\Com%d", её использование позволяет работать с номерами портов большими 9, когда применяются дополнительные мультипортовые карты или преобразователи USB<->COM.
А в отдельный поток не пробовал?
Пробовал - не помогло...
Пробовал - не помогло...
А в dll выпихнуть? или запустить как скрытый процесс?
не, коллеге такими способами ещё больше головной боли достанется, а задача этого не стоит.
BIGNICK'у:
Коллега, завязывайте с CommEvent, честно Вам говорю.