Visual C++下超简单串口类

1  概述

简单易用,使我们编写的软件代码能够在时间长久之后,仍然能够一眼就明白其中的含义和使用过程,因此,简单易用是我们编写软件的目标。反之,如果你写的代码复杂晦涩难懂,就算功能是正常的,但是交由第三方使用的时候的,第三方回感到无比的痛苦,那种感受谁用谁知道。

本着简单易懂的原则,编写了WIN32下的C++串口类,并提供的了简单使用实例,该类能够满足没有特殊要求的用户使用。

2  超简单串口类介绍

该类对接收串口数据,采用一个单独的线程对接收串口数据进行了封装,当然也保留了最原始的接收数据方法,使用者可以自己编写接收串口数据方法。

类中用到的枚举常量:

/// <summary>流控制标志</summary>

enum EComPortHandshake

{

   None = 0,

   Software = 1,

   Hardware = 2

};

 

/// <summary>奇偶检验位标志</summary>

enum EComPortParity

{

   NoParity = 0, // No parity (default)

   OddParity = 1,   // Odd parity

   EvenParity = 2,  // Even parity

   MarkParity = 3,  // Mark parity

   SpaceParity = 4  // Space parity

};

 

/// <summary>停止位标志</summary>

enum EComPortStopBits

{

   OneStopBits = 0, // 1 stopbit (default)

   One5StopBits = 1, // 1.5 stopbit

   TwoStopBits = 2  // 2 stopbits

};

 

/// <summary>事件掩码标志</summary>

enum EComPortEvtMask {

   EV_RXCHAR_ = 0x0001,  // Any Character received

   EV_RXFLAG_ = 0x0002,  // Received certain character

   EV_TXEMPTY_ = 0x0004,  // Transmitt Queue Empty

   EV_CTS_ = 0x0008,  // CTS changed state

   EV_DSR_ = 0x0010,  // DSR changed state

   EV_RLSD_ = 0x0020,  // RLSD changed state

   EV_BREAK_ = 0x0040,  // BREAK received

   EV_ERR_ = 0x0080,  // Line status error occurred

   EV_RING_ = 0x0100,  // Ring signal detected

   EV_PERR_ = 0x0200,  // Printer error occured

   EV_RX80FULL_ = 0x0400,  // Receive buffer is 80 percent full

   EV_EVENT1_ = 0x0800,  // Provider specific event 1

   EV_EVENT2_ = 0x1000  // Provider specific event 2

};

 

/// <summary>串口清理标志</summary>

enum EComPortPurgeFlags {

   PURGE_TXABORT_ = 0x0001,  // Kill the pending/current writes to the comm port.

   PURGE_RXABORT_ = 0x0002,  // Kill the pending/current reads to the comm port.

   PURGE_TXCLEAR_ = 0x0004,  // Kill the transmit queue if there.

   PURGE_RXCLEAR_ = 0x0008  // Kill the typeahead buffer if there.

};

 

enum EComPortBaudRate {

   CBR_110_ = 110,

   CBR_300_ = 300,

   CBR_600_ = 600,

   CBR_1200_ = 1200,

   CBR_2400_ = 2400,

   CBR_4800_ = 4800,

   CBR_9600_ = 9600,

   CBR_14400_ = 14400,

   CBR_19200_ = 19200,

   CBR_38400_ = 38400,

   CBR_56000_ = 56000,

   CBR_57600_ = 57600,

   CBR_115200_ = 115200,

   CBR_128000_ = 128000,

   CBR_256000_ = 256000

};

串口类的接口形式如下:

class IAsyncComPort

{

public:

   IAsyncComPort() {}

 

   /// <summary>

   /// 打开串口

   /// </summary>

   /// <param name="portNum">串口号</param>

   /// <param name="baudRate">波特率</param>

   /// <param name="dataBits">数据位, Number of bits/byte, 4-8</param>

   /// <param name="parity">奇偶校验, 0-4=None,Odd,Even,Mark,Space</param>

   /// <param name="stopBits">停止位, 0,1,2 -- 1, 1.5, 2</param>

   /// <param name="handshake">流控制, 0-无, 1-软件, 2-硬件</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long Open(unsigned short portNum, EComPortBaudRate baudRate, unsigned char dataBits, EComPortParity parity, EComPortStopBits stopBits, EComPortHandshake handshake = EComPortHandshake::None) = 0;

 

   virtual void SetComPortReceiveOneCharCallbackFunc(std::function<void (uint8_t data, uint16_t portNum)> func) = 0;

 

   virtual void SetComPortReceiveFullOneMsgCallbackFunc(std::function<void(uint8_t *datas, int32_t len, uint16_t portNum)> func) = 0;

 

   /// <summary>

   /// 设置波特率

   /// </summary>

   /// <param name="baudRate">波特率</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long SetBaudRate(unsigned long baudRate) = 0;

 

   /// <summary>

   /// 设置停止位

   /// </summary>

   /// <param name="stopBits">停止位, 0,1,2 = 1, 1.5, 2</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long SetStopBits(EComPortStopBits stopBits) = 0;

 

   /// <summary>

   /// 设置数据位

   /// </summary>

   /// <param name="dataBits">数据位, 4-8</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long SetDataBits(unsigned char dataBits) = 0;

 

   /// <summary>

   /// 设置奇偶校验

   /// </summary>

   /// <param name="parity">奇偶校验, 0-4=None,Odd,Even,Mark,Space</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long SetParity(EComPortParity parity) = 0;

 

   /// <summary>

   /// 设置流控制

   /// </summary>

   /// <param name="handshake">流控制, 0-无, 1-软件, 2-硬件</param>

   /// <returns>0-正常, 其它-错误代码</returns>

   virtual unsigned long SetHandShake(EComPortHandshake handshake) = 0;

 

   /// <summary>

   /// 向串口写入数据

   /// </summary>

   /// <param name="datas">要写入的字节数组</param>

   /// <returns>返回值, true Or false</returns>

   virtual bool Write(unsigned char *pBuffer, long bufferLen) = 0;

 

   /// <summary>

   /// 向串口写入1个字节

   ///</summary>

   /// <param name="data">要写入的字节</param>

   /// <returns>返回值, true Or false</returns>

   virtual bool Write(unsigned char data) = 0;

 

   /// <summary>

   /// 从串口读出数据

   /// </summary>

   /// <param name="datas">用于存放数据的缓冲数组</param>

   /// <param name="numberOfBytesRead">从穿口中读取到的字节数</param>

   /// <returns>返回值, TRUE Or FALSE</returns>

   virtual bool Read(unsigned char *pBuffer, long bufferLen, unsigned long *pNumberOfBytesRead) = 0;

 

   /// <summary>

   /// 从串口读出1个字节的数据

   /// </summary>

   /// <param name="data">用于存放数据的缓冲数组</param>

   /// <returns>返回值, TRUE Or FALSE</returns>

   virtual bool Read(unsigned char *pBuffer) = 0;

 

   /// <summary>

   /// 关闭串口

   /// </summary>

   virtual void Close() = 0;

 

   /// <summary>

   /// 设置串口掩码

   /// </summary>

   /// <param name="dwEvtMask">掩码值</param>

   /// <returns>返回值, TRUE Or FALSE</returns>

   virtual bool SetPortMask(EComPortEvtMask dwEvtMask) = 0;

 

   /// <summary>

   /// 获取或设置接收线程的是否启动或已经启动

   /// </summary>

   virtual void EnableReceiveThread(bool bEnable) = 0;

 

   /// <summary>

   /// 设置消息的长度(字节数), 同步头信息.(如果 msgLen小于0 且syncHeader为null, 则默认50个字节为一条消息.syncHeader=null, 则认为没有同步头)

   /// </summary>

   /// <param name="msgLen">一条完整消息的长度, 字节数(含同步头数组的字节数)</param>

   /// <param name="syncHeader">同步头字节数组</param>

   virtual bool SetRecvMsgLengthAndSyncHeader(long msgLen, unsigned char *pSyncHeader, long syncHeaderLen) = 0;

 

   virtual unsigned short GetPortNum() const = 0;

 

   virtual unsigned long GetBaudRate() const = 0;

   virtual unsigned char GetDataBits() const = 0;

   virtual unsigned char GetParity() const = 0;

   virtual unsigned char GetStopBits() const = 0;

   virtual unsigned long GetHandShake() const = 0;

 

   virtual void Release() = 0;

 

public:

   virtual ~IAsyncComPort() { OutputDebugString(_T("~IAsyncComPort Destructor.\n")); }

};

 

#if defined(__cplusplus)

extern "C"

{

#endif

 

   IAsyncComPort *CreateAsyncComPortObject();

   void ReleaseAsyncComPortObject(IAsyncComPort **p);

 

#if defined(__cplusplus)

}

#endif

其中CreateAsyncComPortObject用于创建串口类对象的指针,而ReleaseAsyncComPortObject则用于释放串口类的指针。

也可以stl中的智能指针对指针对象进行管理。

3  串口类的特点

该串口类的一个非常大的特点:简单易用。采用异步读写的方式,接收串口数据采用单独一个线程进行封装,可以让该类自动完成同步头的对比,当接收到1条完整的消息后,调用回调函数通知用户;也可以设置回调函数,自己完成同步头和校验和的对比工作。

其使用步骤如下:

IAsyncComPort *port = CreateAsyncComPortObject();

port->SetRecvMsgLengthAndSyncHeader(4, nullptr, 0);

port->SetComPortReceiveFullOneMsgCallbackFunc( … );

port->Open(…);

然后就可以在循环中发送数据,在设置的回调函数中处理接收到的串口数据。

在软件退出时,调用如下过程:

port->EnableReceiveThread(false);

ReleaseAsyncComPortObject(&port); // 如果采用了智能指针管理该指针,则可以不用调用该函数。

4  使用实例

下面时使用实例中的主要代码段(详细过多,就不粘贴了):

080540_p6cd_229842.png

生成指针对象,并由智能指针管理。

080610_5Upc_229842.png

初始化,设置接收消息的回调函数,打开串口,开始工作。

080619_I4dq_229842.png

退出软件时,关闭接收串口数据的线程,完成串口资源的清理工作。

转载于:https://my.oschina.net/u/229842/blog/1618148

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值