Com-порт. Потеря Последних Байтов Посылки.

Тема в разделе "Общие вопросы по С и С++", создана пользователем decay, 17 янв 2013.

  1. decay

    decay Member

    Регистрация:
    15 апр 2008
    Сообщения:
    6
    Симпатии:
    0
    Пишу консольную программу-терминалку. Предназначена для обмена данными по COM-порту между компьютером и устройством.
    Режим работы порта - асинхронный (при помощи структуры типа OVERLAPPED). Приложение - двухпоточное.
    Для записи в порт используется основной поток, для чтения из порта - поток ReadThread (написал свой класс UniThread).
    Для синхронизации между потоками использую мьютекс hMutex.

    Проблема состоит в следующем: соединяю Rx и Tx порта и при передаче на малых скоростях (например, 600, 1200 бод и т.д.) обнаруживаю, что теряются последние несколько байт. Однако при увеличении скорости до 115200 бод потерь нет. Увидел закономерность: число потерянных байт напрямую связано со скоростью и числом байт в тестовом пакете, например: при передаче (X*8) байт на скорости 600 бод теряется 8 байт, при передаче (X*8 + 1) байт на скорости 600 бод теряется 1 байт, при передаче (X*8+2) байт - 2 байт и т.д., т.е. число потерянных байт на скорости 600 бод не превышает 8. Причем они не исчезают бесследно, при повторной передаче они всплывают, т.е., очевидно, что эти байты задерживаются в каком-то внутреннем буфере COM-порта. В то же время значение поля cbInQue структуры COMSTAT равно нулю, так что тупо дочитать их с помощью ReadFile(...) я не могу. Пробывал в диспетчере задач отключать FIFO COM-порта или уменьшать его - не помогает. Чувствую ведь, что какая-то тупая ошибка. ОС Win7. Есть у кого какие идеи, отчего такое происходит и как это исправить?


    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Инициализация порта"</div></div><div class="sp-body"><div class="sp-content">ComPort::itsDCB.BaudRate = 600; //задаём скорость передачи 9600 бод
    ComPort::itsDCB.fBinary = TRUE; //включаем двоичный режим обмена
    ComPort::itsDCB.fOutxCtsFlow = FALSE; //выключаем режим слежения за сигналом CTS
    ComPort::itsDCB.fOutxDsrFlow = FALSE; //выключаем режим слежения за сигналом DSR
    ComPort::itsDCB.fDtrControl = DTR_CONTROL_DISABLE; //отключаем использование линии DTR
    ComPort::itsDCB.fDsrSensitivity = FALSE; //отключаем восприимчивость драйвера к состоянию линии DSR
    ComPort::itsDCB.fNull = FALSE; //разрешить приём нулевых байтов
    ComPort::itsDCB.fRtsControl = RTS_CONTROL_DISABLE; //отключаем использование линии RTS
    ComPort::itsDCB.fAbortOnError = FALSE; //отключаем остановку всех операций чтения/записи при ошибке
    ComPort::itsDCB.ByteSize = 8; //задаём 8 бит в байте
    ComPort::itsDCB.Parity = NOPARITY; //отключаем проверку чётности
    ComPort::itsDCB.StopBits = ONESTOPBIT; //задаём один стоп-бит
    if (!SetCommState(ComPort::itsHandle, &itsDCB))
    {
    CloseHandle(ComPort::itsHandle);
    goto PortFail;
    }


    //if ComPort::InitSettings()
    ComPort::itsTimeouts.ReadIntervalTimeout = 100; //таймаут между двумя символами
    ComPort::itsTimeouts.ReadTotalTimeoutMultiplier = 100; //общий таймаут операции чтения
    ComPort::itsTimeouts.ReadTotalTimeoutConstant = 100; //константа для общего таймаута операции чтения
    ComPort::itsTimeouts.WriteTotalTimeoutMultiplier = 100; //общий таймаут операции записи
    ComPort::itsTimeouts.WriteTotalTimeoutConstant = 100;

    <div class="sp-wrap"><div class="sp-head-wrap"><div class="sp-head folded clickable">"Читающий поток ReadThread"</div></div><div class="sp-body"><div class="sp-content">DWORD ReadThread::MainFunc()
    {
    //int cnt = 0;
    char i=0;
    DWORD dwWaitMutex;
    DWORD dwWaitPort;

    OVERLAPPED ReadOL;
    DWORD Mask;
    DWORD RealRead;
    DWORD BytesTrans;
    DWORD Err;
    char Buffer[20];
    int AvaibleBytes;

    memset(&ReadOL,0,sizeof(ReadOL));
    ReadOL.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
    SetCommMask(itsOwner->itsHandle , EV_RXCHAR);

    while(!m_bTerminated)
    {
    //dwWaitMutex = WAIT_OBJECT_0;
    dwWaitMutex = WaitForSingleObject(itsOwner->hMutex,INFINITE);
    switch (dwWaitMutex)
    {
    case WAIT_OBJECT_0:
    __try
    {
    //cout << ReadThread::itsLabel ;
    __try
    {
    if (itsOwner->Connected)
    {
    WaitCommEvent(itsOwner->itsHandle, &Mask, &ReadOL);
    dwWaitPort = WaitForSingleObject(ReadOL.hEvent, INFINITE);
    if (dwWaitPort == WAIT_OBJECT_0)
    {

    if ( GetOverlappedResult(
    itsOwner->itsHandle,
    &ReadOL,
    &BytesTrans,
    FALSE
    ) )
    {
    if ((Mask & EV_RXCHAR))
    {
    ClearCommError(
    itsOwner->itsHandle,
    &Err,
    &itsOwner->itsState
    );

    AvaibleBytes = itsOwner->itsState.cbInQue;
    ReadFile(
    itsOwner->itsHandle,
    &Buffer,
    AvaibleBytes,
    &RealRead,
    &ReadOL
    );
    i=0;
    while (i<RealRead)
    {
    RcvTemp[RcvCnt + i] = Buffer;
    i++;
    }

    RcvCnt += RealRead;


    }
    }
    }
    }
    }
    __finally
    {
    //
    }
    //cnt++;
    Sleep(1);
    }
    __finally
    {
    if (! ReleaseMutex(itsOwner->hMutex))
    {
    //handle error
    }
    }
    break;
    case WAIT_ABANDONED:
    cout << "aband ";
    //the resource is busy, let's try it again at next time
    break;
    default:
    cout << "default ";
    break;
    }

    }
    return 0;
    }
     
  2. decay

    decay Member

    Регистрация:
    15 апр 2008
    Сообщения:
    6
    Симпатии:
    0
    Неужели никто не сталкивался с этой проблемой?
     
Загрузка...

Поделиться этой страницей