Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4264343
  • 博文数量: 776
  • 博客积分: 13014
  • 博客等级: 上将
  • 技术积分: 10391
  • 用 户 组: 普通用户
  • 注册时间: 2010-02-22 17:00
文章分类

全部博文(776)

文章存档

2015年(55)

2014年(43)

2013年(147)

2012年(20)

2011年(82)

2010年(429)

分类: WINDOWS

2010-09-21 13:44:36

#include "stdafx.h"
#include 
"SerialPort.h"

#include 
"assert.h"

CSerialPort::CSerialPort()
{
    memset(
&m_OverlappedRead, 0sizeof(m_OverlappedRead));
    memset(
&m_OverlappedWrite, 0sizeof
(m_OverlappedWrite));
    m_bOpened 
= false
;
    m_ReadComThread 
=
 NULL;
    m_hIDCom 
=
 NULL;
    m_dwReadLen 
= 0
;
}

CSerialPort::
~
CSerialPort()
{

}

BOOL CSerialPort::OpenPort(UINT nPort, UINT nBaud)
{
    ASSERT(nPort 
> 0 && nPort < 5
);  
    
if
(m_bOpened)
        
return true
;
    
    TCHAR szPort[
15
];
    TCHAR szComParams[
50
];
    DCB dcb;

    wsprintf(szPort, _T(
"COM%d"
), nPort);
    m_hIDCom 
=
 ::CreateFile(szPort, 
        GENERIC_READ 
|
 GENERIC_WRITE, 
        
0

        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL 
|
 FILE_FLAG_OVERLAPPED,
        NULL);
    
if(m_hIDCom ==
 NULL)
        
return false
;

    memset(
&m_OverlappedRead, 0sizeof
(OVERLAPPED));
    memset(
&m_OverlappedWrite, 0sizeof
(OVERLAPPED));

    COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout 
= 0xFFFFFFFF
;
    CommTimeOuts.ReadTotalTimeoutConstant 
= 0
;
    CommTimeOuts.ReadTotalTimeoutMultiplier 
= 0
;
    CommTimeOuts.WriteTotalTimeoutMultiplier 
= 0
;
    CommTimeOuts.WriteTotalTimeoutConstant 
= 5000
;
    ::SetCommTimeouts(m_hIDCom, 
&
CommTimeOuts);

    wsprintf(szComParams, _T(
"COM%d:%d,N,8,1"
), nPort, nBaud);
    m_OverlappedRead.Offset 
= 0
;
    m_OverlappedRead.OffsetHigh 
= 0
;
    m_OverlappedRead.hEvent 
= ::CreateEvent(NULL, truefalse
, NULL);
    m_OverlappedWrite.Offset 
= 0
;
    m_OverlappedWrite.OffsetHigh 
= 0
;
    m_OverlappedWrite.hEvent 
= ::CreateEvent(NULL, truefalse
, NULL);

    dcb.DCBlength 
= sizeof
(DCB);
    ::GetCommState(m_hIDCom, 
&
dcb);
    dcb.BaudRate 
=
 nBaud;
    dcb.ByteSize 
= 8
;
    dcb.Parity 
= 0
;

    
if(!SetCommState(m_hIDCom, &dcb) || !SetupComm(m_hIDCom, 40964096||

        m_OverlappedRead.hEvent 
== NULL || m_OverlappedWrite.hEvent == NULL)
    {
        DWORD dwError 
=
 ::GetLastError();
        
if(m_OverlappedRead.hEvent !=
 NULL)
            ::CloseHandle(m_OverlappedRead.hEvent);
        
if(m_OverlappedWrite.hEvent !=
 NULL)
            ::CloseHandle(m_OverlappedWrite.hEvent);
        ::CloseHandle(m_hIDCom);
        
return false
;
    }
    ::SetCommMask(m_hIDCom, EV_RXCHAR);
    ::PurgeComm(m_hIDCom, PURGE_TXABORT 
| PURGE_RXABORT | PURGE_TXCLEAR |
 PURGE_RXCLEAR);
    ::EscapeCommFunction(m_hIDCom, SETDTR);

    m_bOpened 
=true
;
    m_bExitThread 
=false
;

    StartMonitoring();
    
return
 m_bOpened;
}

BOOL CSerialPort::Close()
{
    
if(!m_bOpened || m_hIDCom ==
 NULL)
        
return true
;
    m_bExitThread 
= true
;
    ::SetCommMask(m_hIDCom, 
0
);
    StopMonitoring();
    
    
if(m_OverlappedRead.hEvent !=
 NULL)
        ::CloseHandle(m_OverlappedRead.hEvent);

    
if(m_OverlappedWrite.hEvent !=
 NULL)
        ::CloseHandle(m_OverlappedWrite.hEvent);

    ::CloseHandle(m_hIDCom);

    m_bOpened 
= false
;
    m_hIDCom 
=
 NULL;

    
return true
;
}


//向串口写数据

void CSerialPort::WriteToPort(BYTE *Byte, int Len)
{
    
if(!m_bOpened || m_hIDCom ==
 NULL)
        
return
;

    BOOL bWriteStat;
    DWORD dwBytesWritten;
    ClearReadBuf();
    bWriteStat 
= ::WriteFile(m_hIDCom, Byte, Len, &dwBytesWritten, &
m_OverlappedWrite);

    
if(!bWriteStat && (::GetLastError() ==
 ERROR_IO_PENDING))
    {
        
//
WaitForSingleObject函数用来检测hHandle事件的信号状态,当函数的执行时间超过dwMilliseconds就
        
//
返回,但如果参数dwMilliseconds为INFINITE时函数将直到相应时间事件变成有信号状态才返回,
        
//否则就一直等待下去,直到WaitForSingleObject有返回直才执行后面的代码。

        DWORD dw = ::WaitForSingleObject(m_OverlappedWrite.hEvent, INFINITE );
        
if(dw ==
 WAIT_TIMEOUT)
        {
            dwBytesWritten 
= 0
;
            DCB dcb;
            ::GetCommState(m_hIDCom, 
&
dcb);
            ::PurgeComm(m_hIDCom, PURGE_TXCLEAR);
            
return
;
        }
        
else

        {
            ::GetOverlappedResult(m_hIDCom, 
&m_OverlappedWrite, &dwBytesWritten, false);//等待服务器完成IO操作
            m_OverlappedWrite.Offset += dwBytesWritten;
        }
    }
    
return
 ;
}


//从串口读取数据

int CSerialPort::ReadFromPort(BYTE *lpszBlock, int nRLen)
{
    
if(!m_bOpened || m_hIDCom ==
 NULL)
        
return 0
;

    BOOL bReadStat;
    DWORD dwBytesRead, dwErrorFlags;
    COMSTAT ComStat;
    ::ClearCommError(m_hIDCom, 
&dwErrorFlags, &
ComStat);
    
if(!
ComStat.cbInQue)
        
return 0
;

    dwBytesRead 
=
 (DWORD) ComStat.cbInQue;
    
if(nRLen < (int
)dwBytesRead)
        dwBytesRead 
=
 (DWORD) nRLen;

    bReadStat 
= ::ReadFile(m_hIDCom, lpszBlock, dwBytesRead, &dwBytesRead, &
m_OverlappedRead);
    
if(!
bReadStat)
    {
        
if(::GetLastError() ==
 ERROR_IO_PENDING)
        {
            ::WaitForSingleObject(m_OverlappedRead.hEvent, INFINITE);
            
return (int
)dwBytesRead;
        }
        
return 0
;
    }
    
return (int
)dwBytesRead;
}



UINT CSerialPort::CommThread(LPVOID pParam)
{
    CSerialPort
* pSerialPort = (CSerialPort*
)pParam;
    BYTE Buffer[
4096
];
    DWORD dwEvent, dwError;
    COMSTAT ComStat;
    
int ReadLen = 0
;
    memset(pSerialPort
->m_ReadBuf, '\0'sizeof(pSerialPort->
m_ReadBuf));
    ::SetCommMask(pSerialPort
->
m_hIDCom, EV_RXCHAR);
    
while(!pSerialPort->
m_bExitThread)
    {
        memset(Buffer, 
'\0'4096
);
        ::WaitCommEvent(pSerialPort
->m_hIDCom, &
dwEvent, NULL);
        ::ClearCommError(pSerialPort
->m_hIDCom, &dwError, &
ComStat);
        
if((dwEvent & EV_RXCHAR) &&
 ComStat.cbInQue)
        {
            pSerialPort
->m_dwReadLen = pSerialPort->ReadFromPort(Buffer,4096
);
            pSerialPort
->m_dwReadLen = ReadLen >4096 ? 4096
 : ReadLen;
            
if(pSerialPort->m_dwReadLen > 0
)
            {
                memcpy(pSerialPort
->m_ReadBuf, Buffer,pSerialPort->
m_dwReadLen);
            }
        }
        ::PurgeComm(pSerialPort
->
m_hIDCom, PURGE_RXCLEAR);
    }
    
return 0
;
}

BOOL CSerialPort::StartMonitoring()
{
    
if(m_ReadComThread ==
 NULL)
    {
        
if(!(m_ReadComThread = ::AfxBeginThread(CommThread, this
)))
            
return false
;
    }
    
return true
;
}

BOOL CSerialPort::StopMonitoring()
{
    
if(m_ReadComThread !=
 NULL)
    {
        ::TerminateThread(m_ReadComThread
->m_hThread, 0); //终结线程

        m_ReadComThread = NULL;
    }
    
return true
;
}

void
 CSerialPort::ClearReadBuf()
{
    memset(m_ReadBuf, 
'\0'sizeof
(m_ReadBuf));
    m_dwReadLen 
= 0
;
}
阅读(2145) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~