Freeze 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба Здравствуйте. Я написал программу в СиБилдере 6-ом, передающую на ком-порт некоторую информацию. Программа довольно сносно работает в win98... Но в winXP почему-то принимает только последние фразы сообщений (я передаю просто текст)... Так вот вопрос... Чем отличается работа с RS-232 в 98 и ХР?.. P.S. порт работает в асинхронном режиме, так как микроконтроллер, с которого передаются сообщения, не работает в синхронном режиме... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ALexx 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба Здравствуйте. Я написал программу в СиБилдере 6-ом, передающую на ком-порт некоторую информацию. Программа довольно сносно работает в win98... Но в winXP почему-то принимает только последние фразы сообщений (я передаю просто текст)... Так вот вопрос... Чем отличается работа с RS-232 в 98 и ХР?.. P.S. порт работает в асинхронном режиме, так как микроконтроллер, с которого передаются сообщения, не работает в синхронном режиме... Какими средствами осуществляете доступ к порту(открытие, передача/прием)? Прямой записью в регистры? Или используя специальную компоненту под Билдер? Дело в том, что в 98-й прямой доступ к портам возможен, а в ХР - увы :( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Freeze 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба Я пользуюсь WinAPI. Ну, разумеется, команды CreateFile, WriteFile, ReadFile, BuildCommDCB, SetCommState, SetCommTimeouts. Вроде и все... Сам-то порт открывается, даже пересылает что-то... Но большая часть информации где-то теряется... Если надо, могу код прислать... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ALexx 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба Я пользуюсь WinAPI. Ну, разумеется, команды CreateFile, WriteFile, ReadFile, BuildCommDCB, SetCommState, SetCommTimeouts. Вроде и все... Сам-то порт открывается, даже пересылает что-то... Но большая часть информации где-то теряется... Если надо, могу код прислать... Может тут "собака и порылась"? WinAPI не пользовался - точно сказать не могу, но может то, что работает в 98-й не может работать или работает криво в ХР. Четвертый год пользуюсь компонентой ComPort Library (одна из последних версий прилагается). Программы, созданные с ее использованием работают и под 98-й и под 2000-й и под ХР. CPort264.zip Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Warlord 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба WinAPI с COM-портом под Билдером работает корректно - опробовано на практике. Так что код в студию! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Freeze 0 20 июня, 2007 Опубликовано 20 июня, 2007 (изменено) · Жалоба Попробовал эту библиотеку. Уже гораздо лучше. Спасибо огромное. Принимаю почти то, что и хотел, правда есть еще два вопроса. 1. Почему-то проглатывается несколько последних строчек. 2. Не очень понял, как программно выбрать порт. Когда я пытаюсь набрать cPort->Port = "COM1" мне выдается ошибка линковщика. На всякий случай код апишной программы. Если получится лучше и быстрей - оставлю этот вариант. if (RadioButton_Com1->Checked) { COMString = "COM1"; } if (RadioButton_Com2->Checked) { COMString = "COM2"; } HANDLE port; int buf_out; char buf_in[255] = ""; AnsiString LogString; int i = 0; OVERLAPPED ovr; DWORD bc; DCB *dcb; COMMTIMEOUTS ct; dcb = (DCB*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DCB)); dcb->DCBlength = sizeof(DCB); BuildCommDCB("baud=2400 parity=N data=8 stop=1", dcb); dcb->fNull = TRUE; ct.ReadIntervalTimeout = 10; ct.ReadTotalTimeoutMultiplier = ct.ReadTotalTimeoutConstant = 100; ct.WriteTotalTimeoutMultiplier = ct.WriteTotalTimeoutConstant = 0; memset(&ovr, 0, sizeof(ovr)); ovr.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); port = CreateFile(COMString, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (port == INVALID_HANDLE_VALUE) { MessageBox(NULL, "Невозможно открыть порт для записи", "Ошибка", MB_OK); return; } SetCommState(port, dcb); SetCommTimeouts(port, &ct); buf_out = 0x5A; WriteFile(port, &buf_out, 1, &bc, &ovr); DWORD ReopenTime = GetTickCount(); CloseHandle(port); port = CreateFile(COMString, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); if (port == INVALID_HANDLE_VALUE) { MessageBox(NULL, "Невозможно открыть порт для чтения", "Ошибка", MB_OK); return; } SetCommState(port, dcb); HeapFree(GetProcessHeap(), 0, dcb); SetCommTimeouts(port, &ct); DWORD StartTime = GetTickCount(); bc = 1; bool StartRead = false; while ((GetTickCount() - StartTime) < 10000) { Application->ProcessMessages(); buf_in[i] = 0; ReadFile(port, &buf_in[i], 1, &bc, &ovr); PurgeComm(port, PURGE_RXCLEAR|PURGE_TXCLEAR); Sleep(1); i++; if (buf_in[i] == buf_in[i - 1] == ' ') buf_in[i] = 0; if (buf_in[i] != 0) LogString += Recode(buf_in[i]); if (i == 246) { Log->Lines->Add(LogString); i = 0; LogString = ""; } } Здесь Log - TMemo В 98-ой принимает более-менее нормально (Начальство довольно), а в ХР - только несколько несвязных фраз, почти все проглатывает. Изменено 20 июня, 2007 пользователем Freeze Anti Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ALexx 0 20 июня, 2007 Опубликовано 20 июня, 2007 · Жалоба Попробовал эту библиотеку. Уже гораздо лучше. Спасибо огромное. Принимаю почти то, что и хотел, правда есть еще два вопроса. 1. Почему-то проглатывается несколько последних строчек. 2. Не очень понял, как программно выбрать порт. Когда я пытаюсь набрать cPort->Port = "COM1" мне выдается ошибка линковщика. 1.1 Поиграйте с таймаутам 1.2 Управление потоком какое? Аппаратное, программное, или вообще его нет? Не попадаются ли среди смволов XON или XOFF 2. СОМ1 не русским буквами случаем набрано :07: Ну и точка с запятой отсутствует :-) А вообще, если надо менять только номер порта (оставляя все настройки) можно использовать ComComboBox. На прилагаемом рисунке пояснение как его использовать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Freeze 0 21 июня, 2007 Опубликовано 21 июня, 2007 · Жалоба 1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать. 1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить? 2. Попробовал использовать ComComboBox. Все равно вылетает ошибка линкера. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ALexx 0 21 июня, 2007 Опубликовано 21 июня, 2007 · Жалоба 1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать. 1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить? 2. Попробовал использовать ComComboBox. Все равно вылетает ошибка линкера. Киньте кодом мне на ящик dealex77<гав>ukr.net - посмотрю Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Warlord 0 21 июня, 2007 Опубликовано 21 июня, 2007 · Жалоба Глянул я код, чот ничо не понятно, кто кому и чего шлет?? Зачем сначала порт открывается, записывается, а потом закрывается снова открывается считывается?? Потом в порт пишется всего 1 байт 0x5A, где же текст?? Потом если используется аснхронный режим, то прежде чем закрыть порт н.б. уверенным что данные все же успешно туда записаны, т.е. использовать WaitForSingleObject. Потом какое-то странное считывание порта, вслед за асинхронным считыванием вызывается функция очистки буферов порта, а потом удивляемся - данные куда-то пропадают... Рекомндую порыться в инете (или MSDN) и добыть несколько рабочих примеров работы с COM-портом Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Freeze 0 21 июня, 2007 Опубликовано 21 июня, 2007 · Жалоба Спасибо большое за помощь в решении моего вопроса. Задача уже решена. Почему не получилось с API, я так и не понял, но с библиотекой все отлично работает (даже лучше и проще, чем с API). В программе, написанной с использованием библиотеки была ошибка не в пересылке данных, а в выводе данных на экран. Я немного неправильно инкрементировал счетчик итераций в цикле, поэтому и вывод на экран был соответственным. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
a_electronic 0 26 июня, 2007 Опубликовано 26 июня, 2007 · Жалоба Есть еще бааальшой нюанс. В ХР с СОМ портом лучше всего работать в асинхронном режиме. То есть в синхронном он может и будет работать, но при установке софта на другой комп могут возникнуть такие глюки, что мама дорогая. Для этого при вызове port = CreateFile(COMString, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); последний аргумент передать не NULL, а адрес предварительно созданной структуры OVERLAPPED. Ну и работать надо с ним немного не так, а погембельнее. В MSDN должны быть примеры. К стати, при ближайшем рассмотрении кода я наблюдаю, что Порт открывается в синхронном режиме, а вызовы WriteFile(port, &buf_out, 1, &bc, &ovr); ReadFile(port, &buf_in, 1, &bc, &ovr); идут уже асинхронные. Необходимо проверить возврат. Если запускается асинхронная операция на порту в асинхронном режиме, функция не будет дожидаться пока уйдут все данные, она вывалится с возвратом типа произошла ошибка( непомню точно идентификатор), хотя на самом деле это и не ошибка. Тогда надо вручную дожидаться конца асинхронной операции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться