Вопрос по COM-порту
От: Rom  
Дата: 19.06.02 20:48
Оценка:
Всем привет!
Кто может подсказать, как вывести COM-порт из комы на функции WaitCommEvent(...), чтобы корректно завершить поток, в котором порт работает на приёме? Открываю порт для синхронного чтения. Вот ниже код.
BOOL C_USPDTR::Connect(LPCSTR port)
{
    COMMCONFIG cfg;
    DWORD dwRes;

    Disconnect();

    memset(&cfg,0,sizeof(cfg));
    cfg.dwSize = sizeof(cfg);
    if(::CommConfigDialog(port,NULL,&cfg) != IDOK) return FALSE;

    cfg.dcb.fBinary = TRUE;
    cfg.dcb.XoffLim = 512;
    cfg.dcb.XonLim = 2048;
    cfg.dcb.fParity = TRUE;
    cfg.dcb.fNull = TRUE;
    hComm = ::CreateFile(port,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        0,
        NULL);
    if(hComm == INVALID_HANDLE_VALUE)
    {
        ::MessageBox(NULL,"Âûáðàííûé ïîðò çàíÿò!","Îøèáêà îòêðûòèÿ ïîðòà",MB_OK);
        Disconnect();
        return FALSE;
    }
    ::FlushFileBuffers(hComm);
    if(!::SetCommState(hComm,&cfg.dcb)) 
    {
        dwRes = ::GetLastError();
        ::MessageBox(NULL,"Îøèáêà èíèöèàëèçàöèè ïîðòà!",NULL,MB_OK);
    }
    

    COMMTIMEOUTS to;
    DWORD rttc = 100 * 11 * 1000 / cfg.dcb.BaudRate;
    DWORD rit = 11 * 1000 / cfg.dcb.BaudRate;
    to.ReadIntervalTimeout = rit ? rit : 1;
    to.ReadTotalTimeoutConstant = rttc ? rttc : 1;
    to.ReadTotalTimeoutMultiplier = to.ReadIntervalTimeout;
    to.WriteTotalTimeoutConstant = 0;
    to.WriteTotalTimeoutMultiplier = 0;

    if(!::SetCommTimeouts(hComm,&to))
    {
        dwRes = ::GetLastError();
        ::MessageBox(NULL,"Îøèáêà èíèöèàëèçàöèè ïîðòà!",NULL,MB_OK);
    }
    ::GetCommTimeouts(hComm,&to);
    ::PurgeComm(hComm,PURGE_RXABORT|PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
    connect = TRUE;
    ::AfxBeginThread(RecvThread,(LPVOID)NULL);
    return TRUE;    
}
//////////////////////////////////////////////////////////////////////////
void C_USPDTR::Disconnect()
{
    if(hComm!=INVALID_HANDLE_VALUE)
    {
        connect = FALSE;
        ::EscapeCommFunction(hComm,SETBREAK);
        ::SetCommBreak(hComm);
        ::PurgeComm(hComm,PURGE_RXABORT|PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
        ::SetCommBreak(hComm);
        ::WaitForSingleObject(eStopRecvEvent.m_hObject,INFINITE);
        ::CloseHandle(hComm);        
        hComm = INVALID_HANDLE_VALUE;
    }
}
////////////////////////////////////////////////////////////////////////////////////////
UINT C_USPDTR::RecvThread(LPVOID param)
{
    DWORD dwEvent, dwBytesRead;
    OVERLAPPED ol;
    UART_PACKET    packet;

    memset( (LPVOID)&ol, 0, sizeof(ol) );
    ol.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
    ::SetCommMask( hComm, EV_RXCHAR | EV_BREAK);
    while(connect)
    {
        if( ::WaitCommEvent(hComm, &dwEvent, NULL) )
        {
            if( dwEvent & EV_RXCHAR )
            {
                ::ReadFile( hComm, &packet.head, sizeof(UART_PACKET_HEAD),
                    &dwBytesRead, NULL);
                packet.pBuf = new BYTE[ packet.head.data_size ];
                ::ReadFile( hComm, packet.pBuf, packet.head.data_size, 
                    &dwBytesRead, NULL);
            }
            if(dwEvent & EV_BREAK )
            {
                connect = FALSE;
                break;
            }
            else break;
        }
    }
    ::SetEvent(eStopRecvEvent.m_hObject);
    return 0;
}


В функции Disconnect() (там сейчас полная каша ) ни SetCommBreak(..), ни PurgeComm(..) не приводят к выходу из WaitCommEvent(..) .........

С уважением, Роман.
Re: Вопрос по COM-порту
От: ua1zcl Россия www.alexklm.ru
Дата: 20.06.02 00:58
Оценка:
Здравствуйте Rom , Вы писали:

R>Всем привет!

R>Кто может подсказать, как вывести COM-порт из комы на функции WaitCommEvent(...), чтобы корректно завершить поток, в котором порт работает на приёме? Открываю порт для синхронного чтения. Вот ниже код.
R>
R>BOOL C_USPDTR::Connect(LPCSTR port)
R>{
R>    COMMCONFIG cfg;
R>    DWORD dwRes;

R>    Disconnect();

R>    memset(&cfg,0,sizeof(cfg));
R>    cfg.dwSize = sizeof(cfg);
R>    if(::CommConfigDialog(port,NULL,&cfg) != IDOK) return FALSE;

R>    cfg.dcb.fBinary = TRUE;
R>    cfg.dcb.XoffLim = 512;
R>    cfg.dcb.XonLim = 2048;
R>    cfg.dcb.fParity = TRUE;
R>    cfg.dcb.fNull = TRUE;
R>    hComm = ::CreateFile(port,
R>        GENERIC_READ | GENERIC_WRITE,
R>        0,
R>        NULL,
R>        OPEN_EXISTING,
R>        0,
R>        NULL);
R>    if(hComm == INVALID_HANDLE_VALUE)
R>    {
R>        ::MessageBox(NULL,"Âûáðàííûé ïîðò çàíÿò!","Îøèáêà îòêðûòèÿ ïîðòà",MB_OK);
R>        Disconnect();
R>        return FALSE;
R>    }
R>    ::FlushFileBuffers(hComm);
R>    if(!::SetCommState(hComm,&cfg.dcb)) 
R>    {
R>        dwRes = ::GetLastError();
R>        ::MessageBox(NULL,"Îøèáêà èíèöèàëèçàöèè ïîðòà!",NULL,MB_OK);
R>    }
R>    

R>    COMMTIMEOUTS to;
R>    DWORD rttc = 100 * 11 * 1000 / cfg.dcb.BaudRate;
R>    DWORD rit = 11 * 1000 / cfg.dcb.BaudRate;
R>    to.ReadIntervalTimeout = rit ? rit : 1;
R>    to.ReadTotalTimeoutConstant = rttc ? rttc : 1;
R>    to.ReadTotalTimeoutMultiplier = to.ReadIntervalTimeout;
R>    to.WriteTotalTimeoutConstant = 0;
R>    to.WriteTotalTimeoutMultiplier = 0;

R>    if(!::SetCommTimeouts(hComm,&to))
R>    {
R>        dwRes = ::GetLastError();
R>        ::MessageBox(NULL,"Îøèáêà èíèöèàëèçàöèè ïîðòà!",NULL,MB_OK);
R>    }
R>    ::GetCommTimeouts(hComm,&to);
R>    ::PurgeComm(hComm,PURGE_RXABORT|PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
R>    connect = TRUE;
R>    ::AfxBeginThread(RecvThread,(LPVOID)NULL);
R>    return TRUE;    
R>}
R>//////////////////////////////////////////////////////////////////////////
R>void C_USPDTR::Disconnect()
R>{
R>    if(hComm!=INVALID_HANDLE_VALUE)
R>    {
R>        connect = FALSE;
R>        ::EscapeCommFunction(hComm,SETBREAK);
R>        ::SetCommBreak(hComm);
R>        ::PurgeComm(hComm,PURGE_RXABORT|PURGE_TXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
R>        ::SetCommBreak(hComm);
R>        ::WaitForSingleObject(eStopRecvEvent.m_hObject,INFINITE);
R>        ::CloseHandle(hComm);        
R>        hComm = INVALID_HANDLE_VALUE;
R>    }
R>}
R>////////////////////////////////////////////////////////////////////////////////////////
R>UINT C_USPDTR::RecvThread(LPVOID param)
R>{
R>    DWORD dwEvent, dwBytesRead;
R>    OVERLAPPED ol;
R>    UART_PACKET    packet;
          COMSTAT cs;

R>    memset( (LPVOID)&ol, 0, sizeof(ol) );
R>    ol.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
    ::SetCommMask( hComm, EV_RXCHAR | EV_BREAK | EV_ERR);
R>    while(connect)
R>    {
R>        if( ::WaitCommEvent(hComm, &dwEvent, NULL) )
R>        {
R>            if( dwEvent & EV_RXCHAR )
R>            {
R>                ::ReadFile( hComm, &packet.head, sizeof(UART_PACKET_HEAD),
R>                    &dwBytesRead, NULL);
R>                packet.pBuf = new BYTE[ packet.head.data_size ];
R>                ::ReadFile( hComm, packet.pBuf, packet.head.data_size, 
R>                    &dwBytesRead, NULL);
R>            }
R>            if(dwEvent & EV_BREAK )
R>            {
R>                connect = FALSE;
R>                break;
R>            }
                              if ((dwEvtMask & EV_ERR)!=0)
                              { DWORD dwError; 
                                //sprintf(str,"EVENT: EV_ERR"); Le(str);
                                ClearCommError(hComm,&dwError,&cs);
                              }
            else break;// А else и не будет, больше не заказано было
R>        }
R>    }
R>    ::SetEvent(eStopRecvEvent.m_hObject);
R>    return 0;
R>}
R>


R>В функции Disconnect() (там сейчас полная каша ) ни SetCommBreak(..), ни PurgeComm(..) не приводят к выходу из WaitCommEvent(..) .........


Посмотрите старый пример — программу Tty.exe, где-то она была у MS в примерах. Я дописал
случай с EV_ERR. Попробуйте.
Александр
Re: Вопрос по COM-порту
От: VVV Россия  
Дата: 20.06.02 10:53
Оценка:
Здравствуйте Rom , Вы писали:

R>Всем привет!

R>Кто может подсказать, как вывести COM-порт из комы на функции WaitCommEvent(...), чтобы корректно завершить поток, в котором порт работает на приёме? Открываю порт для синхронного чтения. Вот ниже код.
R>В функции Disconnect() (там сейчас полная каша ) ни SetCommBreak(..), ни PurgeComm(..) не приводят к выходу из WaitCommEvent(..) .........

R>С уважением, Роман.


Можно попробовать SetCommMask(hComm, 0) в Disconnect() — не уверен что сработает, т.к. читаем MSDN:

There are two interesting side effects of SetCommMask and WaitCommEvent. First, if the communications port is open for nonoverlapped operation, WaitCommEvent will be blocked until an event occurs. If another thread calls SetCommMask to set a new event mask, that thread will be blocked on the call to SetCommMask. The reason is that the original call to WaitCommEvent in the first thread is still executing. The call to SetCommMask blocks the thread until the WaitCommEvent function returns in the first thread. This side effect is universal for ports open for nonoverlapped I/O. If a thread is blocked on any communications function and another thread calls a communications function, the second thread is blocked until the communications function returns in the first thread. The second interesting note about these functions is their use on a port open for overlapped operation. If SetCommMask sets a new event mask, any pending WaitCommEvent will complete successfully, and the event mask produced by the operation is NULL.

А радикальный способ — CloseHandle(hComm) — должно сработать и WaitCommEvent должен вывалиться с ошибкой.
Re: Вопрос по COM-порту
От: Максим Алексейкин Россия  
Дата: 20.06.02 11:19
Оценка:
Здравствуйте Rom , Вы писали:

Попробуй CancelIo
ICQ #311116826
Re[2]: Вопрос по COM-порту
От: Алекс Россия http://wise-orm.com
Дата: 21.06.02 07:27
Оценка:
Здравствуйте Максим Алексейкин, Вы писали:

МА>Здравствуйте Rom , Вы писали:


МА>Попробуй CancelIo


она работает только для асинхронных операций
Re: Вопрос по COM-порту
От: Алекс Россия http://wise-orm.com
Дата: 21.06.02 07:29
Оценка:
Здравствуйте Rom , Вы писали:

R>Всем привет!

R>Кто может подсказать, как вывести COM-порт из комы на функции WaitCommEvent(...), чтобы корректно завершить поток, в котором порт работает на приёме? Открываю порт для синхронного чтения. Вот ниже код.
[skipped]
R>В функции Disconnect() (там сейчас полная каша ) ни SetCommBreak(..), ни PurgeComm(..) не приводят к выходу из WaitCommEvent(..) .........

R>С уважением, Роман.


не парься! зайди на codeproject и скачай CSerial.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.