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

📄 comm.h

📁 模拟数字硬盘录像机部分功能
💻 H
📖 第 1 页 / 共 2 页
字号:
        PurgeComm(_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

        EndThread();
        ::CloseHandle(_hCommHandle);

        _hCommHandle = INVALID_HANDLE_VALUE;
      }
    }
    //DTR 电平控制
    bool SetDTR(bool OnOrOff)
    {
      return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETDTR :CLRDTR): false;
    }
    //RTS 电平控制
    bool SetRTS(bool OnOrOff)
    {
      return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETRTS :CLRRTS): false;
    }
    //
    bool SetBreak(bool OnOrOff)
    {
      return IsOpen() ? EscapeCommFunction(_hCommHandle, OnOrOff ? SETBREAK: CLRBREAK): false;
    }
    //辅助线程控制 建监视线程
    bool BeginThread()
    {
      if (!IsThreadRunning())
      {
        _fRunFlag = true;
        _hThreadHandle = NULL;

        DWORD id;

        _hThreadHandle = ::CreateThread(NULL, 0, CommThreadProc, this, 0,&id);

        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[20]; //保存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

    //初始化
    void Init()
    {
      memset(_szCommStr, 0, 20);
      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 != INVALID_HANDLE_VALUE);

      _WriteOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
      assert(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);

      _hNotifyWnd = NULL;
      _dwNotifyNum = 0;
      _dwMaskEvent = DEFAULT_COM_MASK_EVENT;
      _hThreadHandle = NULL;

      memset(&_WaitOverlapped, 0, sizeof(_WaitOverlapped));
      _WaitOverlapped.hEvent = ::CreateEvent(NULL, true, false, NULL);
      assert(_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE);
    }
    //析构
    void UnInit()
    {
      if (_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
        CloseHandle(_ReadOverlapped.hEvent);

      if (_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
        CloseHandle(_WriteOverlapped.hEvent);

      if (_WaitOverlapped.hEvent != INVALID_HANDLE_VALUE)
        CloseHandle(_WaitOverlapped.hEvent);
    }
    //绑定串口
    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)
            // asynchronous
            ::GetOverlappedResult(_hCommHandle, &_WaitOverlapped,&dwLength, TRUE);
          else
            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 &);

    //base function for thread
    static DWORD WINAPI CommThreadProc(LPVOID lpPara)
    {
      return ((cnComm*)lpPara)->ThreadFunc();
    }
  };
#endif //_COMM_H_

⌨️ 快捷键说明

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