⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialprot.cpp

📁 实用串口编程库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Comm.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "../HSDPA.h"
#include "../HSDPADlg.h"
#include "SerialPort.h"
#include "../resource.h"
#include "../Ds.h"
#include "Winioctl.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


void AfxErrorMsg(DWORD dwError)
{
    CString str;
    str.Format(_T("%d"), dwError);
    AfxMessageBox(str);
}

#ifdef _DEBUG
struct {
    char snd[512];
    char rcv[512];
} gStAtMsg;
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSerialPort::CSerialPort()
{
    //数据成员初始化
    m_hComm = NULL;
    m_ReadThread = NULL;
    m_WriteThread = NULL;
    m_DetectThread = NULL;
    m_ReadThread = NULL;
    m_bOverlapped = FALSE;
    m_bIsConnect = FALSE;
    m_dwEvtMask = 0;
    m_SerialState = SERIAL_STATE_INI;
 
    memset(&m_ReadOvlp,0,sizeof(OVERLAPPED));
    memset(&m_WriteOvlp,0,sizeof(OVERLAPPED));
    memset(&m_WaitOvlp,0,sizeof(OVERLAPPED));
    memset(&m_IoCtrlOvlp,0,sizeof(OVERLAPPED));

#ifdef FEATURE_SERIAL_ASYNWRITE
    for(int i = 0; i < SERAIL_EVENTARRAYNUM; i++)
    {
        m_hEventArray[i] = NULL;
    }
    //创建自动重置事件
    m_hWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    m_hIoCtrlEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
    m_hCloseWriteEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);

    m_hEventArray[SERAIL_WRITEEVENT]  = m_hWriteEvent;
    m_hEventArray[SERAIL_IOCTRLEVENT] = m_hIoCtrlEvent;
    m_hEventArray[SERAIL_CLOSEEVENT]  = m_hCloseWriteEvent;    
#endif

#ifndef FEATURE_SERIAL_QUEUE
    InitializeCriticalSection(&m_csRxQueue);
#ifdef FEATURE_SERIAL_ASYNWRITE
    InitializeCriticalSection(&m_csTxBuff);
#endif
#endif
}

CSerialPort::~CSerialPort()
{
    StopPort();

#ifdef FEATURE_SERIAL_ASYNWRITE
    for(int i = 0; i < SERAIL_EVENTARRAYNUM; i++)
    {
        if(m_hEventArray[i] != NULL)
            ::CloseHandle(m_hEventArray[i]);            
    }
#endif

#ifndef FEATURE_SERIAL_QUEUE
    DeleteCriticalSection(&m_csRxQueue);
#ifdef FEATURE_SERIAL_ASYNWRITE
    DeleteCriticalSection(&m_csTxBuff);
#endif
#endif
}

BOOL CSerialPort::Open(LPCTSTR lpszCommName, BOOL bOverlapped)
{    
    // Check if the port isn't already opened
    ASSERT(!IsOpen());

    m_bOverlapped = bOverlapped;

    m_hComm = ::CreateFile(lpszCommName,
                           GENERIC_WRITE | GENERIC_READ,
                           0,
                           NULL,
                           OPEN_EXISTING,
                           bOverlapped ? FILE_FLAG_OVERLAPPED : 0,
                           NULL);

    if(m_hComm == INVALID_HANDLE_VALUE)
    {
        m_hComm = NULL;
        m_bOverlapped = FALSE;
        return FALSE;
    }
    return TRUE;
}

void CSerialPort::Close()
{    
    if(IsOpen())
    {
		m_bIsConnect = FALSE;
		SetCommMask(m_hComm,0);
		EscapeCommFunction(m_hComm,CLRDTR);
        Purge(PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
        ::CloseHandle(m_hComm);
        m_hComm = NULL;
        m_bOverlapped = FALSE;
    }
	Sleep(100);
}

inline BOOL CSerialPort::IsOpen() const
{
    return (m_hComm != NULL);
}

inline HANDLE CSerialPort::GetCommHandle() const
{
    return m_hComm;
}

DWORD CSerialPort::GetLastError() const
{
    return ::GetLastError();
}

//直接从串口读数据
DWORD CSerialPort::Read(LPVOID lpBuffer, DWORD dwToRead, DWORD dwTimeout)
{
    ASSERT(IsOpen());

    DWORD dwRead = 0;

    //同步读
    if(!m_bOverlapped) 
    {
        // Read the data
        if(!::ReadFile(m_hComm, lpBuffer, dwToRead, &dwRead, 0))
            dwRead = 0;
    }
    else //异步读
    {    
        // Wait for the event to happen
        memset(&m_ReadOvlp,0,sizeof(OVERLAPPED));
        m_ReadOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        
        // Write the data
        if(!::ReadFile(m_hComm, lpBuffer, dwToRead, &dwRead, &m_ReadOvlp))
        {
            m_dwLastError = ::GetLastError();
            // Overlapped operation in progress is not an actual error
            if(m_dwLastError == ERROR_HANDLE_EOF)
                NULL;
            else if(m_dwLastError != ERROR_IO_PENDING)
                dwRead = 0;
            else
            {
                // Wait for the overlapped operation to complete
                switch(::WaitForSingleObject(m_ReadOvlp.hEvent, dwTimeout))
                {
                case WAIT_OBJECT_0:
                    // The overlapped operation has completed
                    if(!::GetOverlappedResult(m_hComm, &m_ReadOvlp, &dwRead, FALSE))
                    {
                        if(::GetLastError() != ERROR_HANDLE_EOF)
                            dwRead = 0;
                    }
                    break;
                case WAIT_TIMEOUT:
                    // Cancel the I/O operation
                    ::CancelIo(m_hComm);
                default:
                    dwRead = 0;
                }
            }
        }
        ::CloseHandle(m_ReadOvlp.hEvent);
    }

    return dwRead;
}

//直接向串口写数据
DWORD CSerialPort::Write(LPCVOID lpBuffer, DWORD dwToWrite, DWORD dwTimeout)
{
    ASSERT(IsOpen());

    DWORD dwWrite = 0;

    //同步写
    if(!m_bOverlapped) 
    {
        // Write the data
        if(!::WriteFile(m_hComm, lpBuffer, dwToWrite, &dwWrite, 0))
            dwWrite = 0;
    }
    else //异步写
    {    
        // Wait for the event to happen
        memset(&m_WriteOvlp,0,sizeof(OVERLAPPED));
        m_WriteOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        
        // Write the data
        if(!::WriteFile(m_hComm, lpBuffer, dwToWrite, &dwWrite, &m_WriteOvlp))
        {    
            // Overlapped operation in progress is not an actual error
            if(::GetLastError() != ERROR_IO_PENDING)
                dwWrite = 0;
            else
            {
                // Wait for the overlapped operation to complete
                switch(::WaitForSingleObject(m_WriteOvlp.hEvent, dwTimeout))
                {
                case WAIT_OBJECT_0:
                    // The overlapped operation has completed
                    if(!::GetOverlappedResult(m_hComm, &m_WriteOvlp, &dwWrite, FALSE))
                        dwWrite = 0;
                    break;
                case WAIT_TIMEOUT:
                    // Cancel the I/O operation
                    ::CancelIo(m_hComm);
                default:
                    dwWrite = 0;
                }
            }
        }
        ::CloseHandle(m_WriteOvlp.hEvent);
    }

    return dwWrite;
}

BOOL CSerialPort::WaitEvent(DWORD dwTimeout)
{
    ASSERT(IsOpen());

    m_dwEvtMask = 0;
    BOOL bRet = FALSE;
    DWORD dwTrans;

    // Wait for the COM event
    if(!m_bOverlapped) //同步
    {
        if(!::WaitCommEvent(m_hComm, LPDWORD(&m_dwEvtMask), 0))
            bRet = FALSE;
    }
    else //异步
    {
        // Wait for the event to happen
        memset(&m_WaitOvlp,0,sizeof(OVERLAPPED));
        m_WaitOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        
        // Wait for the COM event
        if(!::WaitCommEvent(m_hComm, LPDWORD(&m_dwEvtMask), &m_WaitOvlp))
        {    
            // Overlapped operation in progress is not an actual error
            if(::GetLastError() != ERROR_IO_PENDING)
                bRet = FALSE;
            else
            {
                // Wait for the overlapped operation to complete
                switch (::WaitForSingleObject(m_WaitOvlp.hEvent,dwTimeout))
                {
                case WAIT_OBJECT_0:
                    if(!::GetOverlappedResult(m_hComm, &m_WaitOvlp, &dwTrans, FALSE))
                        bRet = FALSE;
                    else
                        bRet = TRUE;
                    break;
        
                case WAIT_TIMEOUT:
                    // Cancel the I/O operation
                    ::CancelIo(m_hComm);                
                default:
                    bRet = FALSE;
                }
            }
        }
        ::CloseHandle(m_WaitOvlp.hEvent);
    }

    return bRet;
}

BOOL CSerialPort::Purge(DWORD dwFlags)
{
    ASSERT(IsOpen());
    return ::PurgeComm(m_hComm, dwFlags);
}

BOOL CSerialPort::IoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD dwTimeout)
{
    ASSERT(IsOpen());

    BOOL bRet = FALSE;

    //同步控制
    if(!m_bOverlapped) 
    {
        if(!::DeviceIoControl(m_hComm,
                              dwIoControlCode,
                              lpInBuffer,
                              nInBufferSize,
                              lpOutBuffer,
                              nOutBufferSize,
                              lpBytesReturned,
                              0))
        bRet = FALSE;
    }
    else //异步控制
    {
        // Wait for the event to happen
        memset(&m_IoCtrlOvlp,0,sizeof(OVERLAPPED));
        m_IoCtrlOvlp.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        
        if(!::DeviceIoControl(m_hComm,
                              dwIoControlCode,
                              lpInBuffer,
                              nInBufferSize,
                              lpOutBuffer,
                              nOutBufferSize,
                              lpBytesReturned,
                              &m_IoCtrlOvlp))    
        {
            // Overlapped operation in progress is not an actual error
            if(::GetLastError() != ERROR_IO_PENDING)
                bRet = FALSE;
            else
            {
                // Wait for the overlapped operation to complete
                switch(::WaitForSingleObject(m_IoCtrlOvlp.hEvent, dwTimeout))
                {
                case WAIT_OBJECT_0:
                    // The overlapped operation has completed
                    if(!::GetOverlappedResult(m_hComm, &m_IoCtrlOvlp, lpBytesReturned, FALSE))  
                        bRet = FALSE;
                    else
                        bRet = TRUE;
                    break; 
                case WAIT_TIMEOUT:
                    // Cancel the I/O operation
                    ::CancelIo(m_hComm);
                default:
                    bRet = FALSE;
                }
            }
        }
        ::CloseHandle(m_IoCtrlOvlp.hEvent);
    }
    
    // Return successfully
    return bRet;
}

#ifdef FEATURE_SERIAL_ASYNWRITE
UINT CSerialPort::CommWriteThreadProc(LPVOID pParam)
{
    DWORD dwWrite;
    DWORD dwEvent;
    CSerialPort *pComm = (CSerialPort*)pParam;

//  AfxMessageBox("Serial Write Thread Start!");
    for(;;)
    {
        dwEvent = ::WaitForMultipleObjects(SERAIL_EVENTARRAYNUM, pComm->m_hEventArray, FALSE, INFINITE);
        dwEvent -= WAIT_OBJECT_0;

        switch(dwEvent) {
        case SERAIL_WRITEEVENT:
            pComm->Purge(PURGE_TXCLEAR);
            dwWrite = 0;
#ifdef FEATURE_SERIAL_QUEUE    
            CSerialBuffer *buf;
            while(buf = pComm->m_WriteBufQueue.GetFromHead())
            {
                dwWrite = 0;                
                dwWrite = pComm->Write(buf->m_szBuffer, buf->m_dwBytes);
                delete buf;
            }
#else
            EnterCriticalSection(&pComm->m_csTxBuff);
            dwWrite = pComm->Write(pComm->m_TxBuff, pComm->m_wTxCount);
            LeaveCriticalSection(&pComm->m_csTxBuff);
#endif
            break;

        case SERAIL_IOCTRLEVENT:
//            pComm->IoControl();
            break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -