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

📄 cncomm1.3.h

📁 一个功能强大的串口通信类库
💻 H
📖 第 1 页 / 共 2 页
字号:
    {
        cnComm* ptr;

        InnerLock(cnComm* p) : ptr(p)
        {
            ptr->Lock();
        }
        ~InnerLock()
        {
            ptr->Unlock();
        }
    };

    ///锁定资源
    void Lock()
    {
        ::EnterCriticalSection(&_Mutex);
    }
    void Unlock()
    {
        ::LeaveCriticalSection(&_Mutex);
    }
    ///DTR 电平控制
    bool SetDTR(bool OnOrOff)
    {
        return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR : CLRDTR) != 0 : false;
    }
    ///RTS 电平控制
    bool SetRTS(bool OnOrOff)
    {
        return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS : CLRRTS) != 0 : false;
    }
    //////
    bool SetBreak(bool OnOrOff)
    {
        return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK : CLRBREAK) != 0 : false;
    }
    ///辅助线程控制 建监视线程
    bool BeginThread() 
    {
        if(!IsThreadRunning()) 
        {
            _fRunFlag = true;
            _hThreadHandle = NULL;
            
            #ifdef _MT
            unsigned int id;
            _hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, CommThreadProc, this, 0, &id);
            #else
            DWORD id;
            _hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0, &id); 
            #endif
            
            return (_hThreadHandle != NULL); 
        }
        return false;
    }
    ///暂停监视线程
    inline bool SuspendThread()
    {
        return IsThreadRunning() ? ::SuspendThread(_hThreadHandle) != 0xFFFFFFFF : false;
    }
    ///恢复监视线程
    inline bool ResumeThread()
    {
        return IsThreadRunning() ? ::ResumeThread(_hThreadHandle) != 0xFFFFFFFF : false;
    }
    ///终止线程
    bool EndThread(DWORD dwWaitTime = 100)
    {
        if(IsThreadRunning()) 
        {
            _fRunFlag = false;
            ::SetCommMask(_hCommHandle, 0);
            ::SetEvent(_WaitOverlapped.hEvent);
            if(::WaitForSingleObject(_hThreadHandle, dwWaitTime) != WAIT_OBJECT_0)
                if(!::TerminateThread(_hThreadHandle, 0))
                    return false;
                
                ::CloseHandle(_hThreadHandle);
                ::ResetEvent(_WaitOverlapped.hEvent);
                
                _hThreadHandle = NULL;
                
                return true;
        }
        return false;
    }
    
protected:

    volatile DWORD _dwPort;   ///串口号
    volatile HANDLE _hCommHandle;  ///串口句柄
    char _szCommStr[64];  ///保存COM1类似的字符串
    
    DCB _DCB;  ///波特率,停止位,等   
    COMMTIMEOUTS _CO;  ///超时结构   
    
    DWORD _dwIOMode;  ////// 0 同步  默认 FILE_FLAG_OVERLAPPED 重叠I/O 异步
    OVERLAPPED _ReadOverlapped, _WriteOverlapped; ////// 重叠I/O
    
    volatile HANDLE _hThreadHandle; ///辅助线程
    volatile HWND _hNotifyWnd;  ////// 通知窗口
    volatile DWORD _dwNotifyNum; ///接受多少字节(>=_dwNotifyNum)发送通知消息
    volatile DWORD _dwMaskEvent; ///监视的事件
    volatile bool _fRunFlag;  ///线程运行循环标志
    bool _fAutoBeginThread;  ///Open() 自动 BeginThread();
    OVERLAPPED _WaitOverlapped;  ///WaitCommEvent use
    
    ///初始化
    virtual void Init() 
    {
        memset(_szCommStr, 0, 64);
        memset(&_DCB, 0, sizeof(_DCB));
        _DCB.DCBlength = sizeof(_DCB);
        _hCommHandle = INVALID_HANDLE_VALUE;
        
        memset(&_ReadOverlapped, 0, sizeof(_ReadOverlapped));
        memset(&_WriteOverlapped, 0, sizeof(_WriteOverlapped));
        
        _ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        assert(_ReadOverlapped.hEvent != NULL); 
        
        _WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        assert(_WriteOverlapped.hEvent != NULL);
        
        _hNotifyWnd = NULL;
        _dwNotifyNum = 0;
        _dwMaskEvent = DEFAULT_COM_MASK_EVENT;
        _hThreadHandle = NULL;
        _dwPort = 0;
        
        memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
        _WaitOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
        assert(_WaitOverlapped.hEvent != NULL); 

        ::InitializeCriticalSection(&_Mutex);
    } 
    ///析构
    virtual void Destroy()
    {
        if(_ReadOverlapped.hEvent != NULL)
            CloseHandle(_ReadOverlapped.hEvent);
        
        if(_WriteOverlapped.hEvent != NULL)
            CloseHandle(_WriteOverlapped.hEvent);
        
        if(_WaitOverlapped.hEvent != NULL)
            CloseHandle(_WaitOverlapped.hEvent);

        ::DeleteCriticalSection(&_Mutex);
    }
    ///绑定串口
    void BindCommPort(DWORD dwPort)
    {
        assert(dwPort >= 1 && dwPort <= 1024);
        
        char p[5];
        
        _dwPort = dwPort;
        strcpy(_szCommStr, "\\\\.\\COM"); 
        ltoa(_dwPort, p, 10);
        strcat(_szCommStr, p);
    }
    ///打开串口
    virtual bool OpenCommPort()
    {
        if(IsOpen())
            Close();
        
        _hCommHandle = ::CreateFile(
            _szCommStr,
            GENERIC_READ | GENERIC_WRITE,
            0,
            NULL,
            OPEN_EXISTING,
            FILE_ATTRIBUTE_NORMAL | _dwIOMode, 
            NULL
            );
        
        if(_fAutoBeginThread)
        {
            if(IsOpen() && BeginThread())
                return true;
            else
            {
                Close();  ///创建线程失败
                return false;
            }
        }
        return IsOpen();
    }
    ///设置串口
    virtual bool SetupPort()
    {
        if(!IsOpen())
            return false;
        
        
        if(!::SetupComm(_hCommHandle, 4096, 4096))
            return false; 
        
        
        if(!::GetCommTimeouts(_hCommHandle, &_CO))
            return false;
        _CO.ReadIntervalTimeout = 0;
        _CO.ReadTotalTimeoutMultiplier = 1;
        _CO.ReadTotalTimeoutConstant = 1000;
        _CO.WriteTotalTimeoutMultiplier = 1;
        _CO.WriteTotalTimeoutConstant = 1000;
        if(!::SetCommTimeouts(_hCommHandle, &_CO))
            return false; 
        
        
        if(!::PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
            return false; 
        
        return true;
    } 
    
    //////---------------------------------------threads callback-----------------------------------------------------
    ///线程收到消息自动调用, 如窗口句柄有效, 送出消息, 包含串口编号, 均为虚函数可以在基层类中扩展       
    virtual void OnReceive()///EV_RXCHAR
    {
        if(::IsWindow(_hNotifyWnd))
            ::PostMessage(_hNotifyWnd, ON_COM_RECEIVE, WPARAM(_dwPort), LPARAM(0));
    }
    
    virtual void OnDSR()
    {
        if(::IsWindow(_hNotifyWnd))
        {
            DWORD Status;
            if(GetCommModemStatus(_hCommHandle, &Status))
                ::PostMessage(_hNotifyWnd, ON_COM_DSR, WPARAM(_dwPort), LPARAM( (Status & MS_DSR_ON) ? 1 : 0));
        }
    }
    
    virtual void OnCTS()
    {
        if(::IsWindow(_hNotifyWnd))
        {
            DWORD Status;
            if(GetCommModemStatus(_hCommHandle, &Status))
                ::PostMessage(_hNotifyWnd, ON_COM_CTS, WPARAM(_dwPort), LPARAM( (Status & MS_CTS_ON) ? 1 : 0));
        }
    }
    
    virtual void OnBreak()
    {
        if(::IsWindow(_hNotifyWnd))
        {
            ::PostMessage(_hNotifyWnd, ON_COM_BREAK , WPARAM(_dwPort), LPARAM(0));
        }
    }
    
    virtual void OnTXEmpty()
    {
        if(::IsWindow(_hNotifyWnd))
            ::PostMessage(_hNotifyWnd, ON_COM_TXEMPTY, WPARAM(_dwPort), LPARAM(0));
    }
    
    virtual void OnError()
    {
        DWORD dwError;
        ::ClearCommError(_hCommHandle, &dwError, NULL);
        if(::IsWindow(_hNotifyWnd))
            ::PostMessage(_hNotifyWnd, ON_COM_ERROR, WPARAM(_dwPort), LPARAM(dwError));
    }
    
    virtual void OnRing()
    {
        if(::IsWindow(_hNotifyWnd))
            ::PostMessage(_hNotifyWnd, ON_COM_RING, WPARAM(_dwPort), LPARAM(0));
    }
    
    virtual void OnRLSD()
    {
        if(::IsWindow(_hNotifyWnd))
            ::PostMessage(_hNotifyWnd, ON_COM_RLSD, WPARAM(_dwPort), LPARAM(0));
    }
    
    virtual DWORD ThreadFunc()
    {
        if(!::SetCommMask(_hCommHandle, _dwMaskEvent))
        {
            char szBuffer[256];
            _snprintf(szBuffer, 255, "%s(%d) : COM%d Call WINAPI SetCommMask(%x, %x) Fail, thread work invalid! GetLastError() = %d;",
                __FILE__, __LINE__, _dwPort, _hCommHandle, _dwMaskEvent, GetLastError());
            MessageBox(NULL, szBuffer, "Class cnComm", MB_OK);
            return 1;
        }
        
        COMSTAT Stat;
        DWORD dwError;
        
        for(DWORD dwLength, dwMask = 0; _fRunFlag && IsOpen(); dwMask = 0)
        {
            if(!::WaitCommEvent(_hCommHandle, &dwMask, &_WaitOverlapped))
            {
                if(::GetLastError() != ERROR_IO_PENDING)
				{
                    ::ClearCommError(_hCommHandle, &dwError, &Stat);
                    continue;
				}
            }
            
            if(dwMask == 0)
                continue;
            
            switch(dwMask)
            {
            case EV_RXCHAR :
                ::ClearCommError(_hCommHandle, &dwError, &Stat);
                if(Stat.cbInQue >= _dwNotifyNum)
                    OnReceive();
                break;
                
            case EV_TXEMPTY :
                OnTXEmpty();
                break;
                
            case EV_CTS :
                OnCTS();
                break;
                
            case EV_DSR :
                OnDSR();
                break;
                
            case EV_RING :
                OnRing();
                break;
                
            case EV_RLSD :
                OnRLSD();
                break;
                
            case EV_BREAK:
                OnBreak();
                break;
                
            case EV_ERR :
                OnError();
                break;
                
            }///case
        }///for
        return 0;
    }
    
private:  ///the function protected 
    
    cnComm(const cnComm&);
    cnComm &operator = (const cnComm&);
    CRITICAL_SECTION _Mutex;
    
    ///base function for thread
    #ifdef _MT
    static UINT APIENTRY CommThreadProc(LPVOID lpPara)
    #else
    static DWORD WINAPI CommThreadProc(LPVOID lpPara)
    #endif
    {
        return ( (cnComm *)lpPara )->ThreadFunc();
    }
};

#endif ///_CN_COMM_H_

⌨️ 快捷键说明

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