多線程多接收模式串口類LsComm_第1頁
多線程多接收模式串口類LsComm_第2頁
多線程多接收模式串口類LsComm_第3頁
多線程多接收模式串口類LsComm_第4頁
多線程多接收模式串口類LsComm_第5頁
已閱讀5頁,還剩8頁未讀, 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、多線程,多接收模式串口類LsComm作者:Liu_sir下載示例源代碼描述:一個串口通訊類 應用平臺:Windows 版本: v1.0 主要功能:設計了一個簡潔易用的多線程串行通訊接口,可以切換查詢和自動接收模式,進行對串口數據收發的類 接觸VC,很不習慣mscomm等Active控件老讓人去注冊的方式,所以參照Delphi中的SpComm設計了一個類CComPort,對PJ Naughter 的CSerialPort()進行了2次封裝,主要目的是簡化串口的使用.使其用簡單的代碼就可以完成串口通訊的過程.做了一個Demo程序演示了CComPort的使用,附圖如下: 下面我從如何使用和類的設計兩

2、個方面說明一下: 一 如何使用: 考慮到使用過程盡可能簡潔,實用,為了滿足不同的使用要求設計4種接收模式, 前兩種為手動接收方式,后兩種為自動類回調方式,下面是使用代碼 1.ManualReceiveByQuery 手動查詢接收#include ComPort.h LsComm:CComPort m_ComPort; /LsComm is namespace in c+m_ComPort.Open(2,LsComm:CComPort:AutoReceiveByquery);/ReCeive Com Data: 接收語句DWORD InBufferCount;byte pbuffer2048;I

3、nBufferCount = m_ComPort.GetInBufferCount();if(InBufferCount0) m_ComPort.GetInput(pbuffer,InBufferCount);/Write Com Data: 寫串口數據char a10=abcdefg;this-m_ComPort.Output(a,sizeof(a);2.ManualReceiveByConst(異步模式) 手動定常數接收模式 #include ComPort.h LsComm:CComPort m_ComPort;/LsComm is namespace in c+m_ComPort.Op

4、en(2,LsComm:CComPort:AutoReceiveByConst);/ReCeive Com Data: /接收數據DWORD InBufferCount=0;byte pbuffer2048;InBufferCount=this-m_ComPort.GetInput(pbuffer,10,1000);/上面我要在1000毫秒內接收10字節的數據,IbufferCount返回實際得到的數據if(InBufferCount=0)return;CString c;char a4; for(int i=0;iGetDlgItem(IDC_LIST1);for(int i=0;iAddS

5、tring(c);3.AutoReceiveBySignal 自動信號接收模式 #include ComPort.h LsComm:CComPort m_ComPort;/LsComm is namespace in c+m_ComPort.Open(2,LsComm:CComPort:AutoReceiveBySignal ); m_ComPort.SetReceiveFunc(FOnReceiveData)OnReceiveData,this); m_ComPort.SetBreakHandleFunc(OnComBreak); /ReCeive Com Data:接收數據函數in OnR

6、eceiveData(LPVOID pSender,void* pBuf,DWORD InBufferCount) /above/write data the same as the first mode; 4.AutoReceiveByBreak 中斷接收模式#include ComPort.h LsComm:CComPort m_ComPort;/LsComm is namespace in c+m_ComPort.Open(2,LsComm:CComPort:AutoReceiveByBreak ); m_ComPort.SetReceiveFunc(FOnReceiveData)OnR

7、eceiveData,this); /ReCeive Com Data:接收數據函數in OnReceiveData(LPVOID pSender,void* pBuf,DWORD InBufferCount) /above/write data the same as the first mode; 另外說明2點: (1)如果你需要處理中斷事件,你可以在每種模式中設置中斷接收事件:如下 /定義中斷事件接收函數 void OnComBreak(LPVOID pSender,DWORD dwMask,COMSTAT stat) /deal with the break of com herem_

8、ComPort.SetBreakHandleFunc(OnComBreak); /設置中斷事件(2)如何處理如,改變波特率,以及其它參數呢?m_ComPort.GetSerialPort()可以獲得一個CSerialPort類的指針,如何就可以操作各種com屬性了. DCB dcb;this-m_ComPort.GetSerialPort()-GetState(dcb);二.類的設計與編程1. 類結構為了說明一個大概的類構成,我用Rose畫了一下類圖:如下CComPort內部聚合了一個CSerialPort的串口類,并與一個CReadComThread線程關聯,讓其去讀取串口數據. LsCom

9、m:CComPort m_ComPort;/LsComm is namespace in c+m_ComPort.Open(2,LsComm:CComPort:AutoReceiveBySignal ); m_ComPort.SetReceiveFunc(OnReceiveData,this); m_ComPort.SetBreakHandleFunc(OnComBreak);這些語句是怎么實現串口數據的發送和讀取的呢? 2. 打開過程CComPort:Open() void CComPort:Open(int nPort,ReceiveMode mode, DWORD dwBaud, Par

10、ity parity, BYTE DataBits, StopBits stopbits,FlowControl fc) /1.新建串口this-m_pPort = new CSerialPort();/2.判斷收發模式if(mode=ReceiveMode:ManualReceiveByQuery) this-m_IsOverlapped = false;else this-m_IsOverlapped = true;this-m_RecvMode = mode; /3.轉換參數,打開串口int index;index=parity-CComPort:EvenParity;CSerialPo

11、rt:Parity spParity=(CSerialPort:Parity)(CSerialPort:EvenParity+index);略去 this-m_pPort-Open(nPort,dwBaud,spParity,DataBits,spStopbits,spFC,m_IsOverlapped); this-m_pPort-Setup(4096,4096); this-m_pPort-Purge(PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);/it is important!COMMTIMEOUTS ti

12、meouts;this-m_pPort-GetTimeouts(timeouts);timeouts.ReadIntervalTimeout=100;this-m_pPort-SetTimeouts(timeouts);this-m_CurPortNum = nPort; /創建關閉事件this-m_hCloseEvent = CreateEvent(NULL,true,false,NULL);ASSERT(this-m_hCloseEvent); /4.創建線程類this-m_pReadThread = new CReadComThread();this-m_pReadThread-Band

13、SerialPort(this); this-m_pReadThread-Create();this-m_pReadThread-Resume(); if(this-IsOverlapped() this-m_hWriteEvent = :CreateEvent(NULL,false,false,NULL);主要做的工作是:新建串口 this-m_pPort = new CSerialPort(); 打開串口 this-m_pPort-Open 創建讀取線程 this-m_pReadThread = new CReadComThread(); 設立線程類與CComPort的關聯關系this-m

14、_pReadThread-BandSerialPort(this); void CReadComThread:BandSerialPort(CComPort* pPort)ASSERT(pPort);this-m_pPort = pPort;/創建異步讀取事件 if(this-m_pPort-IsOverlapped() this-m_ReadOverlapped.hEvent =:CreateEvent(NULL,false,false,NULL); ASSERT(this-m_ReadOverlapped.hEvent); this-m_BreakOverlapped.hEvent = :

15、CreateEvent(NULL,false,false,NULL); ASSERT(this-m_BreakOverlapped.hEvent); 模式主要在線程執行的過程中發揮作用3.串口的發送數據過程 DWORD CComPort:Output(void* pBuf,DWORD Count) DWORD dwWriteBytes=0;if(this-IsOverlapped()/異步模式this-m_pPort-Write(pBuf,Count,this-m_WriteOverlapped);if(WaitForSingleObject(this-m_WriteOverlapped.hE

16、vent,INFINITE)=WAIT_OBJECT_0) this-m_pPort-GetOverlappedResult(this-m_WriteOverlapped,dwWriteBytes,false);elsedwWriteBytes= this-m_pPort-Write(pBuf,Count); return dwWriteBytes;再看this-m_pPort-Write(pBuf,Count);實際上是:調用DWORD CSerialPort:Write(const void* lpBuf, DWORD dwCount) ASSERT(IsOpen(); ASSERT(!m

17、_bOverlapped); DWORD dwBytesWritten = 0; if (!WriteFile(m_hComm, lpBuf, dwCount, &dwBytesWritten, NULL) TRACE(_T(Failed in call to WriteFilen); AfxThrowSerialException(); return dwBytesWritten;或者是BOOL CSerialPort:Write(const void* lpBuf, DWORD dwCount, OVERLAPPED& overlapped, DWORD* pBytesWritten) 異

18、步寫串口的過程 4.串口的讀取過程分兩種:查詢讀取和線程自動讀取 (1) 查詢讀取 DWORD CComPort:GetInput(void* pBuf,DWORD Count,DWORD dwMilliseconds) /不能在自動模式下getinputif(this-GetReceiveMode()=CComPort:AutoReceiveByBreak|this-GetReceiveMode()=CComPort:AutoReceiveBySignal):AfxMessageBox(Cant use GetInput methord in this mode!);return 0;if(

19、this-IsOverlapped() ASSERT(this-m_pReadThread); DWORD dwBytes = this-m_pReadThread-ReadInput(pBuf,Count,dwMilliseconds); this-m_pPort-TerminateOutstandingReads(); return dwBytes;else return this-m_pPort-Read(pBuf,Count); 主要是調用m_pPort-Read(pBuf,Count);然后調用API函數ReadFile(2) 線程等待處理主要過程:在線程CreadComThread

20、的Execute中void CReadComThread:Execute()if(this-m_pPort-GetReceiveMode()=CComPort:ManualReceiveByQuery) this-ExecuteByManualQueryRecvMode(); else if(this-m_pPort-GetReceiveMode()=CComPort:ManualReceiveByConst) this-ExecuteByManualConstRecvMode(); else if(this-m_pPort-GetReceiveMode()=CComPort:AutoRece

21、iveBySignal) this-ExecuteByAutoSignalRecvMode(); else/中斷模式 this-ExecuteByAutoBreakRecvMode(); 主要是選擇模式然后執行: 下面看看this-ExecuteByAutoSignalRecvMode(); void CReadComThread:ExecuteByAutoSignalRecvMode()DWORD dwMask=0;HANDLE WaitHandles3; /監聽事件數組DWORD dwSignaledHandle;WaitHandles0 = this-m_pPort-GetCloseHa

22、ndle();WaitHandles1 = this-m_ReadOverlapped.hEvent;WaitHandles2 = this-m_BreakOverlapped.hEvent;this-m_pPort-GetSerialPort()-SetMask(EV_ERR | EV_RLSD | EV_RING ); if(!SetBreakEvent(dwMask)goto EndThread;/設置讀事件if(!SetReadEvent(this-m_ReadOverlapped)goto EndThread;/設置comEventfor(;)dwSignaledHandle=:Wa

23、itForMultipleObjects(3,WaitHandles,false,INFINITE);switch(dwSignaledHandle)case WAIT_OBJECT_0:goto EndThread; break;case WAIT_OBJECT_0+1:if(!this-HandleReadEvent(this-m_ReadOverlapped)goto EndThread;if(!this-SetReadEvent(this-m_ReadOverlapped)goto EndThread;break;case WAIT_OBJECT_0+2:if(!this-Handle

24、BreakEvent(dwMask)goto EndThread; if(!this-SetBreakEvent(dwMask)goto EndThread;break;default: /goto EndThread;break; EndThread:this-m_pPort-GetSerialPort()-Purge(PURGE_RXABORT | PURGE_RXCLEAR); :CloseHandle(this-m_ReadOverlapped.hEvent);:CloseHandle(this-m_BreakOverlapped.hEvent); return ; 主要是一個等待事件發送然后調用,響應的過程,如果讀取事件發生則調用this-HandleReadEvent(this-m_ReadOverlapped); bool CR

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論