Перейти к содержанию
    

COM порт в win98 и winXP

Здравствуйте.

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте.

 

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

 

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

 

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

 

Какими средствами осуществляете доступ к порту(открытие, передача/прием)?

Прямой записью в регистры? Или используя специальную компоненту под Билдер?

 

Дело в том, что в 98-й прямой доступ к портам возможен, а в ХР - увы :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я пользуюсь WinAPI.

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я пользуюсь WinAPI.

 

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

 

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

 

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

 

Может тут "собака и порылась"? WinAPI не пользовался - точно сказать не могу, но может то, что работает в 98-й не может работать или работает криво в ХР.

Четвертый год пользуюсь компонентой ComPort Library (одна из последних версий прилагается). Программы, созданные с ее использованием работают и под 98-й и под 2000-й и под ХР.

CPort264.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

WinAPI с COM-портом под Билдером работает корректно - опробовано на практике. Так что код в студию!

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал эту библиотеку.

 

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

 

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

 

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

 

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-ой принимает более-менее нормально (Начальство довольно), а в ХР - только несколько несвязных фраз, почти все проглатывает.

Изменено пользователем Freeze Anti

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Попробовал эту библиотеку.

 

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

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

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

 

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

 

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

 

cPort->Port = "COM1"

 

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

 

1.1 Поиграйте с таймаутам

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

 

2. СОМ1 не русским буквами случаем набрано :07: Ну и точка с запятой отсутствует :-)

А вообще, если надо менять только номер порта (оставляя все настройки) можно использовать

ComComboBox. На прилагаемом рисунке пояснение как его использовать.

post-704-1182344032_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать.

1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить?

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1.1 С таймаутами игрался. Все без толку. Доходит до некоторого места и перестает принимать.

1.2 Я вообще не трогал управление потоком. Очень не хочется переделывать программу для микроконтроллера (Это мне прибор таскать в другую комнату, чтобы перепрошить). Если дело в этом, то как следует поступить?

 

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

 

Киньте кодом мне на ящик dealex77<гав>ukr.net - посмотрю

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо большое за помощь в решении моего вопроса.

 

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

 

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

 

В программе, написанной с использованием библиотеки была ошибка не в пересылке данных, а в выводе данных на экран. Я немного неправильно инкрементировал счетчик итераций в цикле, поэтому и вывод на экран был соответственным.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

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);

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

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

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...