Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: COM порт в win98 и winXP
Форум разработчиков электроники ELECTRONIX.ru > Интерфейсы > Форумы по интерфейсам > RS232/LPT/USB/PCMCIA/FireWire
Freeze Anti
Здравствуйте.

Я написал программу в СиБилдере 6-ом, передающую на ком-порт некоторую информацию. Программа довольно сносно работает в win98... Но в winXP почему-то принимает только последние фразы сообщений (я передаю просто текст)...

Так вот вопрос... Чем отличается работа с RS-232 в 98 и ХР?..

P.S. порт работает в асинхронном режиме, так как микроконтроллер, с которого передаются сообщения, не работает в синхронном режиме...
ALexx
Цитата(Freeze Anti @ Jun 20 2007, 07:56) *
Здравствуйте.

Я написал программу в СиБилдере 6-ом, передающую на ком-порт некоторую информацию. Программа довольно сносно работает в win98... Но в winXP почему-то принимает только последние фразы сообщений (я передаю просто текст)...

Так вот вопрос... Чем отличается работа с RS-232 в 98 и ХР?..

P.S. порт работает в асинхронном режиме, так как микроконтроллер, с которого передаются сообщения, не работает в синхронном режиме...


Какими средствами осуществляете доступ к порту(открытие, передача/прием)?
Прямой записью в регистры? Или используя специальную компоненту под Билдер?

Дело в том, что в 98-й прямой доступ к портам возможен, а в ХР - увы sad.gif
Freeze Anti
Я пользуюсь WinAPI.

Ну, разумеется, команды CreateFile, WriteFile, ReadFile, BuildCommDCB, SetCommState, SetCommTimeouts. Вроде и все...

Сам-то порт открывается, даже пересылает что-то... Но большая часть информации где-то теряется...

Если надо, могу код прислать...
ALexx
Цитата(Freeze Anti @ Jun 20 2007, 09:50) *
Я пользуюсь WinAPI.

Ну, разумеется, команды CreateFile, WriteFile, ReadFile, BuildCommDCB, SetCommState, SetCommTimeouts. Вроде и все...

Сам-то порт открывается, даже пересылает что-то... Но большая часть информации где-то теряется...

Если надо, могу код прислать...


Может тут "собака и порылась"? WinAPI не пользовался - точно сказать не могу, но может то, что работает в 98-й не может работать или работает криво в ХР.
Четвертый год пользуюсь компонентой ComPort Library (одна из последних версий прилагается). Программы, созданные с ее использованием работают и под 98-й и под 2000-й и под ХР.
Warlord
WinAPI с COM-портом под Билдером работает корректно - опробовано на практике. Так что код в студию!
Freeze Anti
Попробовал эту библиотеку.

Уже гораздо лучше.

Спасибо огромное.

Принимаю почти то, что и хотел, правда есть еще два вопроса.

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-ой принимает более-менее нормально (Начальство довольно), а в ХР - только несколько несвязных фраз, почти все проглатывает.
ALexx
Цитата(Freeze Anti @ Jun 20 2007, 14:53) *
Попробовал эту библиотеку.

Уже гораздо лучше.
Спасибо огромное.
Принимаю почти то, что и хотел, правда есть еще два вопроса.

1. Почему-то проглатывается несколько последних строчек.

2. Не очень понял, как программно выбрать порт. Когда я пытаюсь набрать

Код
cPort->Port = "COM1"


мне выдается ошибка линковщика.


1.1 Поиграйте с таймаутам
1.2 Управление потоком какое? Аппаратное, программное, или вообще его нет? Не попадаются ли среди смволов XON или XOFF

2. СОМ1 не русским буквами случаем набрано 07.gif Ну и точка с запятой отсутствует :-)
А вообще, если надо менять только номер порта (оставляя все настройки) можно использовать
ComComboBox. На прилагаемом рисунке пояснение как его использовать.
Freeze Anti
1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать.
1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить?

2. Попробовал использовать ComComboBox. Все равно вылетает ошибка линкера.
ALexx
Цитата(Freeze Anti @ Jun 21 2007, 07:53) *
1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать.
1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить?

2. Попробовал использовать ComComboBox. Все равно вылетает ошибка линкера.


Киньте кодом мне на ящик dealex77<гав>ukr.net - посмотрю
Warlord
Глянул я код, чот ничо не понятно, кто кому и чего шлет?? Зачем сначала порт открывается, записывается, а потом закрывается снова открывается считывается?? Потом в порт пишется всего 1 байт 0x5A, где же текст?? Потом если используется аснхронный режим, то прежде чем закрыть порт н.б. уверенным что данные все же успешно туда записаны, т.е. использовать WaitForSingleObject. Потом какое-то странное считывание порта, вслед за асинхронным считыванием вызывается функция очистки буферов порта, а потом удивляемся - данные куда-то пропадают... Рекомндую порыться в инете (или MSDN) и добыть несколько рабочих примеров работы с COM-портом
Freeze Anti
Спасибо большое за помощь в решении моего вопроса.

Задача уже решена.

Почему не получилось с API, я так и не понял, но с библиотекой все отлично работает (даже лучше и проще, чем с API).

В программе, написанной с использованием библиотеки была ошибка не в пересылке данных, а в выводе данных на экран. Я немного неправильно инкрементировал счетчик итераций в цикле, поэтому и вывод на экран был соответственным.
oran-be
Есть еще бааальшой нюанс. В ХР с СОМ портом лучше всего работать в асинхронном режиме. То есть в синхронном он может и будет работать, но при установке софта на другой комп могут возникнуть такие глюки, что мама дорогая. Для этого при вызове

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[i], 1, &bc, &ovr);

идут уже асинхронные. Необходимо проверить возврат. Если запускается асинхронная операция на порту в асинхронном режиме, функция не будет дожидаться пока уйдут все данные, она вывалится с возвратом типа произошла ошибка( непомню точно идентификатор), хотя на самом деле это и не ошибка. Тогда надо вручную дожидаться конца асинхронной операции.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.