Giter VIP home page Giter VIP logo

taskedserialport's Introduction

做过串口通讯的VCer肯定都熟悉MsComm控件和CodeProject上的CSerial。也许更多的程序员更愿意使用不需要控件的CSerial。但是不幸的是,CSerial类仅仅完成对底层串口通讯的封装,有时候并不如MsComm控件好用。

CSerialPort为bluejoe在CSerial基础上开发的类,支持开启事件监视线程。CTaskedPort为CSerialPort的派生类,它支持基于任务的事件处理。

用户发送一条命令(如:AT),可能就需要等待串口的回应(如:OK)才决定做下一步,这个AT命令其实就是一项任务(CPortTask),任务的结束一般需要用户指定关键词(如:OK或者ERROR)。CTaskedPort自动将命令和关键词列表封装成一个任务。

本包主要包括以下几个类:

CSerialPort:类似于CSerial的类,类声明如下:

	class CSerialPort  
	{
	public:
		void AssertConnected();
		CWinThread * GetListener();
		CString ReadAll();
	
		CWinThread * EnableListener(BOOL bEnable = TRUE);
		BOOL SetDCB(DCB * pDCB, int nHandshaking);
	
		enum
		{
			comNone,
				comXOnXOff,
				comRTS,
				comRTSXOnXOff
		};
	
		BOOL IsConnected();
	
		BOOL GetOverlappedResult(OVERLAPPED * pol, DWORD * pLength, BOOL bWait);
		BOOL GetTimeouts(COMMTIMEOUTS * cto);
		BOOL SetTimeouts(COMMTIMEOUTS * cto);
		BOOL Purge(DWORD nFlags);
		BOOL GetComStat(COMSTAT * pcs);
		UINT CommThread();
	
		BOOL ClearOutputBuffer();
		BOOL ClearInputBuffer();
		BOOL FlushOutputBuffer();
	
		BOOL SetDCB(DCB * pDCB);
		HANDLE GetHandle();
		BOOL Open(int nPort);
	
		BOOL GetDCB(DCB * pDCB);
		BOOL SetDCB(UINT nBaudRate, BYTE cParity = NOPARITY, BYTE nByteSize = 8, BYTE nStopBits = ONESTOPBIT);
	
		BOOL Open(CString sPort);
		void Close();
	
		CString Read(BOOL bWait = FALSE);
		DWORD Read(char *pBuffer, DWORD nLength, BOOL bWait = FALSE);
		DWORD Write(char *pBuffer, DWORD nLength, DWORD nWaitLimit = INFINITE);
		DWORD Write(CString sBuffer, DWORD nWaitLimit = INFINITE);
	
		static UINT CommThread(LPVOID pParam);
	
		//开启监视线程,以事件方式通知
		CWinThread * StartListener(DWORD nEventMask = EV_BREAK | EV_ERR | EV_RXCHAR);
		//开启监视线程,以消息方式通知
		CWinThread * StartListener(CWnd * pOwner, UINT nNotifyMessageID = IDU_COMM_EVENT, DWORD nEventMask = EV_BREAK | EV_ERR | EV_RXCHAR);
		
		CSerialPort();
		virtual ~CSerialPort();
	
	private:
	
		CWnd * m_pOwner;
		CWinThread * m_pThread;
		UINT m_nNotifyMessageID;
		OVERLAPPED m_osRead; // 用于重叠读
		OVERLAPPED m_osWrite; // 用于重叠写
	
		BOOL m_bConnected;
		volatile HANDLE m_hHandle;
		volatile HANDLE m_hShutDownEvent;
	
	protected:
	
		virtual void OnDisconnect();
		virtual void OnEvent(DWORD nEvent);
		virtual void OnEvRLSD();
		virtual void OnEvErr();
		virtual void OnEvDSR();
		virtual void OnEvBreak();
		virtual void OnEvTxEmpty();
		virtual void OnEvRXFlag();
		virtual void OnEvRxChar();
		virtual void OnEvRing();
		virtual void OnEvCTS();
	};

CPortTask:完成对串口任务的封装,类声明如下:

	class CPortTask
	{
	protected:
		
		CStringArray m_sMatches;
		CByteArray m_nMatchCodes;
		int m_nLimit;
		HANDLE m_hCompleteEvent;
		BOOL m_bCompleted;
		CWnd * m_pOwner;
		UINT m_nNotifyMessageID;
	
		CMutex m_Mutex;
		
		int m_nMatchIndex;
		int m_nDirty; //数据脏计数,每次接收到数据,该计数自动加1
		
		CTaskedPort * m_pOwnerPort;
		CString m_sFullInput; //该任务消化的字符
		
		void EndTask(); //结束当前任务
		void CompleteTask(); //完成当前任务
		
	public:
		CStringArray * GetMatches();
		
		CString m_sTaskName;
		CString GetInputBuffer();
		
		int GetDirty();
		
		void SetBufferSize(int nLimit); //设置缓冲区长度
		void AbortTask(); //取消当前任务
		void ResetTask(); //重置当前任务
		
		void SetOwner(CTaskedPort * pOwnerPort); //设置隶属CTaskedPort
		int GetMatchCode(); //获取匹配码
		
		CPortTask(CString sTaskName);
		~CPortTask();
		
		void AttachEvent(CWnd * pOwner, UINT nMessageID = IDU_TASK_COMPLETE); //设置消息通知方式
		void AttachEvent(HANDLE hEvent); //设置事件通知方式
		
		int Catch(CString sInput); //消化字符串
		
		BOOL IsCompleted(); //指定该任务是否已完成
		
		virtual void OnTaskCompleted();
		
		int AddMatches(CString sMatches); //添加多个匹配项,匹配项之间以|分隔
		int AddMatch(CString sMatch); //添加匹配项
		int AddMatch(CString sMatch, int nValue); //添加匹配项,并指定匹配码
		
	};

CTaskedPort:支持任务的串口操作类,类声明如下:

	class CTaskedPort : public CSerialPort  
	{
	private:
		
		CPortTask * m_pBGTask; //后台任务
		CPortTask * m_pFGTask; //前台任务
	
		
	public:
	
		void WaitForTask(CPortTask *pTask, int nEndCondition, CWaiting * pWaiting, DWORD nIdleTimeLimit);
		void Close();
		
		//等待时间
		enum
		{
				tmShort = 20,
				tmNormal = 1000,
				tmInitialize = 3000,
				tmLong = 6000,
				tmLonger = 20000,
		};
		
		//指定GetInput函数的行为
		enum
		{
			//指定GetInput调用的终止条件
			
			//0-3: 匹配条件
			
			ecDirty = 0x0001, //有值即返回
				ecWaiting = 0x0002, //不等待
				ecOkOrError = 0x0004, //有OK或者ERROR即返回
				ecCrlf = 0x0008, //有回车即返回
				
				//4-7: 指定发生等待超时时GetInput的动作选项
				
				ecRetryAlways = 0x0100, //一直等待
				ecRetryPrompt = 0x0200, //提示用户是否继续
		};
		
		CMutex m_Mutex;
		
		BOOL Open(CString sPort);
		int Request(CString sRequest, CString & sResponse, int nEndCondition, CWaiting * pWaiting, char * sFind = NULL, CString sTaskName = "", DWORD nIdleTimeLimit = tmNormal);
		DWORD SendCommand(CString sCommand, DWORD nIdleTimeLimit = tmNormal);
		CString Request(CString sRequest, int nEndCondition, CWaiting * pWaiting, char * sFind = NULL, CString sTaskName = "", DWORD nIdleTimeLimit = tmNormal);
		
		void UnloadTask(CPortTask * pTask);
		
		void LoadFGTask(CPortTask * pTask);
		void LoadBGTask(CPortTask * pTask);
		
		CString m_sInputBuffer;
		
		void OnEvRxChar();
		CTaskedPort();
		virtual ~CTaskedPort();
	};

CTaskedPort支持的任务包括后台任务和前台任务,它同时只允许一个任务被激活:如果存在前台任务,后台任务自动隐藏;新前台任务的载入,会自动覆盖旧的任务。

后台任务一直存在,用以监视用户指定的串口事件,并构造字符缓冲区。当用户调用Request函数时,CTaskedPort自动创建一个前台任务,并disable后台监视任务。前台任务一直等待,直到关键字的出现(或者超时)。这个等待过程表现出来的是一个同步接口,用户只需要等待Request函数结束即可。至于用户可能需要在等待过程中做一些其它的操作,如:显示进度条,这就需要用到CWaiting类。

CWaiting:CWaiting类用以指定等待过程中的动作,系统中已提供了3种CWaiting类:CDumbWaiting(啥都不干)、CProgressWaiting(显示进度条)和CNewProgressWaiting(创建一个新的进度窗口并显示进度)。CNewProgressWaiting继承于CProgressWaiting,它们之间的区别在于CProgressWaiting可以依附于任何一个窗口(如:当前的主窗口),而CNewProgressWaiting创建一个新的窗口。

创建一个CWaiting对象,将它作为参数,传入Request函数,就这么简单,你的程序就完成了同步等待和异步显示。

此外,Request允许用户指定等待时限。在等待超时时,是否直接结束等待,还是继续重试,还是弹出提示框询问用户,这些动作都可以通过Request的参数指定。

CTaskedPort还提供了丰富的接口,用户可以通过继承,来实现更多的功能。

本包已经成功应用到bluejoe的手机串口通讯软件,目前还没有发现什么问题。希望各位使用探讨,并希望各位提出修改意见。

所附源码还包括其它的工具类,包括CUtil、CRichException、CWin32Exception等,希望能与大家一块共享。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.