VC + + Serial programming of the third party class

Source: Internet
Author: User
Tags assert bool continue thread valid volatile win32 port number

Serial type

From this series of articles can be seen, and through the WIN32 API for serial access, through the MSComm of this ActiveX control serial access to the convenience of many, it can basically screen the details of multithreading, the event (issue OnComm message) way to achieve the asynchronous serial port access.

However, the use of the MSComm control is still inconvenient, for example, it sends and receives data to the variant type Object and the string transformation and so on. Therefore, many excellent programmers at home and abroad have written some serial port classes, using these classes, we will be more convenient to operate the serial port. In the author's "Simple and simple Win32 multithreaded design of a comprehensive example" (Web site: http://dev.yesky.com) in the article, has shown to the reader by the Remon SPEKREIJSE written cserialport serial port class, And this article will show you by programmer Llbird written Cncomm (China serial port? ) Serial port class.

Llbird is a good programmer, his code style concise and compact, class declaration and implementation are defined in a header file, the use of this class of friends only need to include this file in the project can:

/* Comm Base Library (win98/nt/2000) ver 1.1 Compile by:bc++ 5; C + + BUILDER 4, 5, 6, X; VC + + 5, 6; Vc.net;
GCC; Copyright (c) 2004.5-2005.8 llbird wushaojian@21cn.com */#ifndef _cn_comm_h_ #define _CN_COMM_H_ #pragma warning (disabl 
e:4530) #pragma warning (disable:4786) #pragma warning (disable:4800) #include <assert.h> #include <stdio.h> #include <windows.h>//Sent to the window message WPARAM port number #define On_com_receive + 618 #define On_com_cts Wm_user + 619//l PARAM 1 Valid #define ON_COM_DSR Wm_user + 621//lparam 1 valid #define On_com_ring Wm_user + 623 #define ON_COM_RLSD Wm_u SER + 624 #define On_com_break Wm_user + 625 #define ON_COM_TXEMPTY Wm_user + 626 #define ON_COM_ERROR Wm_user + 627//lpa RAM Save Error ID #define Default_com_mask_event Ev_rxchar | Ev_err | ev_cts | EV_DSR | Ev_break | Ev_txempty | ev_ring | EV_RLSD class Cncomm {public://------------------------------Construction-----------------------------------// The 1th parameter is whether to start the monitoring thread when the serial port is opened, and the 2nd parameter is IO blocking mode (0)/asynchronous Overlay (default) Cncomm (bool Fautobeginthread = True, DWORD Dwiomode = file_flag_overlapped): _dwiomode (Dwiomode), _fautobegi
 Nthread (fautobeginthread) {Init ();
  Virtual ~cncomm () {close ();
 UnInit ();
  }//----------------------------------Attributes----------------------------------//To determine whether the serial port is open inline bool IsOpen () {
 return _hcommhandle!= Invalid_handle_value;
 //Determine if the serial port is open operator bool () {return _hcommhandle!= invalid_handle_value;
 //Get the serial word Bing inline HANDLE gethandle () {return _hcommhandle;
 //Get the serial word bing operator HANDLE () {return _hcommhandle;
  //Get serial parameters DCB DCB *getstate () {return IsOpen () &&:: Getcommstate (_hcommhandle, &AMP;_DCB) = = TRUE?
 &_DCB:NULL; //Set serial port parameters DCB bool SetState (DCB *PDCB = null) {return IsOpen ()?:: SetCommState (_hcommhandle, PDCB = null? &_
 DCB:PDCB) = = True:false; //Set serial port parameters: Baud rate, stop bit, etc. support settings string "9600, 8, N, 1" bool SetState (char *szsetstr) {if (IsOpen ()) {if (:: Getcommstate ( _hcommhanDle, &AMP;_DCB)!= TRUE) return false;
   if (:: Buildcommdcb (Szsetstr, &AMP;_DCB)!= TRUE) return false;
  Return:: SetCommState (_hcommhandle, &AMP;_DCB) = = TRUE;
 return false;  //Set serial port parameters: Baud rate, stop bit, etc bool SetState (DWORD dwbaudrate, DWORD Dwbytesize = 8, DWORD dwparity = Noparity, dword dwstopbits =
   Onestopbit) {if (IsOpen ()) {if (:: Getcommstate (_hcommhandle, &AMP;_DCB)!= TRUE) return false; _DCB.
   BaudRate = dwbaudrate; _DCB.
   ByteSize = (unsigned char) dwbytesize; _DCB.
   Parity = (unsigned char) dwparity; _DCB.
   StopBits = (unsigned char) dwstopbits;
  Return:: SetCommState (_hcommhandle, &AMP;_DCB) = = TRUE;
 return false;  }//Get timeout structure lpcommtimeouts gettimeouts (void) {return IsOpen () &&:: Getcommtimeouts (_hcommhandle, &_co) = =
TRUE?
 &_CO:NULL; }//Set timeout bool Settimeouts (lpcommtimeouts Lpco) {return IsOpen ():: SetCommTimeouts (_hcommhandle, lpco) = = True:fals
 E //Set the I/O buffer size of the serial port bool Setbuffersize (DWORD dwinputsize, DWORD dwoutputsize) {return IsOpen ():: Setupcomm (_hcommhandle, dwinputsize, dwoutputsize) = = True:false;
  ///The window handle of the associated message inline void Setwnd (HWND hwnd) {ASSERT (:: IsWindow (hwnd));
 _hnotifywnd = hWnd;
 /Set send notification, accept character minimum inline void Setnotifynum (DWORD dwnum) {_dwnotifynum = Dwnum;
 }//Whether the thread is running inline bool Isthreadrunning () {return _hthreadhandle!= NULL;
 //Get thread handle inline HANDLE GetThread () {return _hthreadhandle;
 }//Set the event to be monitored, set valid void Setmaskevent (DWORD dwevent = default_com_mask_event) {_dwmaskevent = dwevent before opening;
  }//Get the number of characters for the read buffer int getinputsize () {Comstat Stat;
  DWORD dwerror; Return:: Clearcommerror (_hcommhandle, &dwerror, &stat) = = TRUE?
 Stat.cbinque: (DWORD)-1L; }//----------------------------------Operations----------------------------------//Open serial port default 9600, 8, N, 1 bool Open (DW
 ORD dwport) {return Open (Dwport, 9600); //Open serial port defaults baud_rate, 8, N, 1 bool Open (DWORD Dwport, DWORD dwbaudrate) {if (Dwport < 1 | |
  Dwport > 1024) return false;
  Bindcommport (Dwport); if (!
  Opencommport ()) return false; if (!
  Setupport ()) return false;
 Return SetState (dwbaudrate); //Open the serial port and use a setting string similar to "9600, 8, N, 1" to set the serial port bool Open (DWORD dwport, char *szsetstr) {if (Dwport < 1 | | Dwport > 10
  ) return false;
  Bindcommport (Dwport); if (!
  Opencommport ()) return false; if (!
  Setupport ()) return false;
 Return SetState (SZSETSTR); //Read serial dwbufferlength characters to Buffer returns the number of characters that can be read in the actual reading. DWORD Read (LPVOID Buffer, DWORD dwbufferlength, DWORD Dwwaittime = {if (!)
  IsOpen ()) return 0;
  Comstat Stat;
  DWORD dwerror; if (:: Clearcommerror (_hcommhandle, &dwerror, &stat) && dwerror > 0) {::P Urgecomm (_hcommhandle,pur Ge_rxabort |
   Purge_rxclear);
  return 0; } if (!
  Stat.cbinque)//buffer no data return 0;
  unsigned long ureadlength = 0; Dwbufferlength = dwbufferlength > Stat.cbinque?
  Stat.cbinque:d wbufferlength; if (!::readfile (_hcommhAndle, Buffer, Dwbufferlength, &ureadlength,&_readoverlapped)) {if (:: GetLastError () = = error_io_pending)
    {WaitForSingleObject (_readoverlapped.hevent, dwwaittime); End asynchronous I/O (!::getoverlappedresult (_hcommhandle, &_readoverlapped,&ureadlength, False)) {if (:: Ge
    Tlasterror ()!= error_io_incomplete) ureadlength = 0;
  } else Ureadlength = 0;
 return ureadlength; //Read serial dwBufferLength-1 characters to szbuffer return ANSI C-mode string pointer for generic character communication char *readstring (char *szbuffer, DWORD dwbufferlengt
  H, DWORD dwwaittime =20) {unsigned long ureadlength = Read (Szbuffer, dwbufferlength-1,dwwaittime);
  Szbuffer[ureadlength] = ' the ';
 return szbuffer; //write serial port can write arbitrary data "ABCD" or "\x0\x1\x2" DWORD write (LPVoid Buffer, DWORD dwbufferlength) {if (!)
  IsOpen ()) return 0;
  DWORD dwerror; if (:: Clearcommerror (_hcommhandle, &dwerror, NULL) && dwerror > 0)::P urgecomm (_hcommhandle, Purge_txabo RT | Purge_txclear);
  unsigned long uwritelength = 0; if (!::writefile (_hcommhandle, Buffer, Dwbufferlength, &uwritelength,&_writeoverlapped)) if (:: GetLastError (
   )!= error_io_pending) uwritelength = 0;
  return uwritelength;
   //write serial port write ANSI C-mode string pointer DWORD write (const char *szbuffer) {assert (szbuffer);
  Return Write ((void*) szbuffer, strlen (szbuffer)); //Read serial port Synchronization application DWORD Readsync (LPVOID Buffer, DWORD dwbufferlength) {if (!)
   IsOpen ()) return 0;
   DWORD dwerror; if (:: Clearcommerror (_hcommhandle, &dwerror, NULL) && dwerror > 0) {::P Urgecomm (_hcommhandle,purge_ Rxabort |
    Purge_rxclear);
   return 0;
   } DWORD ureadlength = 0;
   :: ReadFile (_hcommhandle, Buffer, Dwbufferlength, &ureadlength, NULL);
  return ureadlength; //write Serial Port Synchronization application DWORD Writesync (LPVOID Buffer, DWORD dwbufferlength) {if (!)
   IsOpen ()) return 0;
   DWORD dwerror;
 if (:: Clearcommerror (_hcommhandle, &dwerror, NULL) && dwerror > 0)   ::P Urgecomm (_hcommhandle, Purge_txabort |
   Purge_txclear);
   unsigned long uwritelength = 0;
   :: WriteFile (_hcommhandle, Buffer, Dwbufferlength, &uwritelength, NULL);
  return uwritelength;
  //write serial szbuffer can output format string contains buffer length DWORD Write (char *szbuffer, DWORD dwbufferlength, Char *szformat, ...) {if (!
   IsOpen ()) return 0;
   Va_list va;
   Va_start (VA, szformat);
   _vsnprintf (Szbuffer, Dwbufferlength, Szformat, VA);
   Va_end (VA);
  Return Write (szbuffer);
  //write serial szbuffer can output format string do not check buffer length carefully overflow DWORD Write (char *szbuffer, char *szformat, ...) {if (!
   IsOpen ()) return 0;
   Va_list va;
   Va_start (VA, szformat);
   vsprintf (Szbuffer, Szformat, VA);
   Va_end (VA);
  Return Write (szbuffer); ///Close serial port also closes associated thread virtual void close () {if (IsOpen ()) {PurgeComm (_hcommhandle, Purge_txabort |
    Purge_txclear);
    Endthread ();
    :: CloseHandle (_hcommhandle);
   _hcommhandle = Invalid_handle_value; }//DTR Level control bool Setdtr (boOl Onoroff) {return IsOpen ()? Escapecommfunction (_hcommhandle, Onoroff?)
  SETDTR:CLRDTR): false; //rts level control bool Setrts (bool Onoroff) {return IsOpen ()? Escapecommfunction (_hcommhandle, Onoroff?)
  Setrts:clrrts): false; }//bool Setbreak (bool Onoroff) {return IsOpen ()? Escapecommfunction (_hcommhandle, Onoroff?)
  Setbreak:clrbreak): false; }//Worker thread control build monitoring thread bool Beginthread () {if (!
    Isthreadrunning ()) {_frunflag = true;
    _hthreadhandle = NULL;
    DWORD ID;
    _hthreadhandle =:: CreateThread (NULL, 0, Commthreadproc, this, 0,&id);
   Return (_hthreadhandle!= NULL);
  return false;  //Pause Monitoring thread inline bool SuspendThread () {return isthreadrunning ():: SuspendThread (_hthreadhandle)!=0XFFFFFFFF:
  False //recovery monitoring thread inline bool ResumeThread () {return isthreadrunning ():: ResumeThread (_hthreadhandle)!=0xffffffff:f
  Alse; }//Terminate thread bool Endthread (DWORD Dwwaittime = +) {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; Serial slogan volatile HANDLE _hcommhandle; Serial handle char _szcommstr[20]; Save COM1 similar string DCB _DCB; Baud rate, stop bit, etc commtimeouts _co; Timeout structure DWORD _dwiomode; 0 Sync Default file_flag_overlapped overlapped I/O asynchronous overlapped _readoverlapped, _writeoverlapped; Overlapping I/O volatile HANDLE _hthreadhandle; Worker threads volatile HWND _hnotifywnd; Notification window volatile DWORD _dwnotifynum; Accept how many bytes (>=_dwnotifynum) to send a notification message volatile DWORD _dwmaskevent; Monitored events volatile bool _frunflag; Thread run loop flag bool _fautobeginthread;
  Open () automatic beginthread (); Overlapped _waitoverlapped; WaitcommeVent use//initialization void Init () {memset (_szcommstr, 0, 20);
   memset (&AMP;_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); }//destructor 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);
   }//Bind serial port void Bindcommport (DWORD dwport) {assert (Dwport >= 1 && dwport <= 1024);
   Char p[5];
   _dwport = Dwport;
   strcpy (_szcommstr, "\\\\.\\com");
   Ltoa (_dwport, p, 10);
  strcat (_SZCOMMSTR, p);
   //Open Serial 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 ();//Create thread failed return false;
  } return IsOpen (); }//Set serial 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 (!::P Urgecomm (_hcommhandle, Purge_txabort | Purge_rxabort | Purge_txclear |
   Purge_rxclear)) return false;
  return true; }//---------------------------------------threads callback-----------------------------------//thread receives an automatic call to the message, If the window handle is valid, send out the message, including serial number, all virtual functions can extend virtual void onreceive ()//ev_rxchar {if (:: IsWindow (_hnotifywnd)) in the base class::P OS
  Tmessage (_hnotifywnd, On_com_receive, WPARAM (_dwport), LPARAM (0));
    virtual void Ondsr () {if (:: IsWindow (_hnotifywnd)) {DWORD Status; if (Getcommmodemstatus (_hcommhandle, &status))::P ostmessage (_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))::P ostmessage (_hnotifywnd, On_com_cts, WPARAM (_dwport), LPARAM (S Tatus &ms_cts_on)?
   1:0)); virtual void Onbreak () {if (:: IsWindow (_hnotifywnd)) {::P ostmessage (_hnotifywnd, On_com_break, Wpara
   M (_dwport), LPARAM (0)); virtual void Ontxempty () {if (:: IsWindow (_hnotifywnd))::P ostmessage (_hnotifywnd, On_com_txempty, WPARAM
  (_dwport), LPARAM (0));
   virtual void OnError () {DWORD dwerror;
   :: Clearcommerror (_hcommhandle, &dwerror, NULL);
  if (:: IsWindow (_hnotifywnd))::P ostmessage (_hnotifywnd, On_com_error, WPARAM (_dwport), LPARAM (dwerror));  virtual void onring () {if (:: IsWindow (_hnotifywnd))::P ostmessage (_hnotifywnd, on_com_ring, WPARAM (_dwport),
  LPARAM (0));  virtual void Onrlsd () {if (:: IsWindow (_hnotifywnd))::P ostmessage (_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, &A Mp;dwmask, &_waitoverlapped)) {if (:: GetLastError () = error_io_pending)//asynchronous:: Getov
     Erlappedresult (_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)-&GT;THREADF
  UNC ();
}  }; #endif//_cn_comm_h_

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.