VC串口編程帶全部注釋和步驟_第1頁
VC串口編程帶全部注釋和步驟_第2頁
VC串口編程帶全部注釋和步驟_第3頁
VC串口編程帶全部注釋和步驟_第4頁
VC串口編程帶全部注釋和步驟_第5頁
已閱讀5頁,還剩9頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、用 VC 6.0 實現(xiàn)串行通信的三種方法和介紹在實驗室和工業(yè)應(yīng)用中,串口是常用的計算機與外部串行設(shè)備之間的數(shù)據(jù)傳輸通道,由于串行通信方便易行,所以應(yīng)用廣泛。依據(jù)不同的條件實現(xiàn)對串口的靈活編程控制是我們所需要的。 - 在光學(xué)鏡片鍍膜工藝中,用單片機進行多路溫度數(shù)據(jù)采集控制,采集結(jié)果以串行方式進入主機,每隔10秒向主機發(fā)送一次采樣數(shù)據(jù),主機向單片機發(fā)送相關(guān)的控制命令,實現(xiàn)串行數(shù)據(jù)接收、處理、記錄、顯示,實時繪制曲線。串行通信程序開發(fā)環(huán)境為 VC 6.0。 Windows下串行通信 - 與以往 DOS 下串行通信程序不同的是, 窗口 不提倡應(yīng)用程序直接控制硬件,而是通過 窗口 操作系統(tǒng)提供的設(shè)備驅(qū)動

2、程序來進行數(shù)據(jù)傳遞。串行口在 贏32 中是作為文件來進行處理的,而不是直接對端口進行操作,對于串行通信, 贏32 提供了相應(yīng)的文件 I/O 函數(shù)與通信函數(shù),通過了解這些函數(shù)的使用,可以編制出符合不同需要的通信程序。 -與通信設(shè)備相關(guān)的結(jié)構(gòu)有COMMCONFIG、 COMMPROP、COMMTIMEOUTS、COMSTAT、DCB、MODEMDEVCAPS、 MODEMSETTINGS共7個,與通信有關(guān)的Windows API函數(shù)共有26個,詳細說明可參考 MSDN幫助文件。以下將結(jié)合實例,給出實現(xiàn)串行通信的三種方法。 實現(xiàn)串行通信的三種方法 - 方法一:使用 VC 提供的串行通信控件 MSCo

3、mm -首先,在對話框中創(chuàng)建通信控件,若Control工具欄中缺少該控件,可通過菜單ProjectAdd to ProjectComponents and Control插入即可,再將該控件從工具箱中拉到對話框中。此時,你只需要關(guān)心控件提供的對 Windows 通信驅(qū)動程序的 API 函數(shù)的接口。換句話說,只需要設(shè)置和監(jiān)視MSComm控件的屬性和事件。 -在ClassWizard中為新創(chuàng)建的通信控件定義成員對象(CMSComm m_Serial),通過該對象便可以對串口屬性進行設(shè)置,MSComm 控件共有27 個屬性,這里只介紹其中幾個常用屬性: CommPort 設(shè)置并返回通信端口號,缺省為

4、 COM1。 Settings 以字符串的形式設(shè)置并返回波特 率、奇偶校驗、數(shù)據(jù)位、停止位。 PortOpen 設(shè)置并返回通信端口的狀態(tài),也可 以打開和關(guān)閉端口。 Input 從接收緩沖區(qū)返回和刪除字符。 Output 向發(fā)送緩沖區(qū)寫一個字符串。 InputLen 設(shè)置每次Input讀入的字符個數(shù),缺 省值為0,表明讀取接收緩沖區(qū)中的全 部內(nèi)容。 InBufferCount 返回接收緩沖區(qū)中已接收到的字符 數(shù),將其置0可以清除接收緩沖區(qū)。 InputMode 定義Input屬性獲取數(shù)據(jù)的方式(為 0:文本方式;為1:二進制方式)。 -RThreshold 和 SThreshold 屬性,表示在

5、 OnComm 事件發(fā)生之前,接收緩沖區(qū)或發(fā)送緩沖區(qū)中可以接收的字符數(shù)。 - 以下是通過設(shè)置控件屬性對串口進行初始化的實例: BOOLCSampleDlg: PortOpen () BOOLm_Opened; m_Serial.SetCommPort(2);/指定串口號 m_Serial.SetSettings(“4800,N,8,1); /通信參數(shù)設(shè)置 m_Serial.SetInBufferSize(1024);/指定接收緩沖區(qū)大小 m_Serial.SetInBufferCount(0);/清空接收緩沖區(qū) m_Serial.InputMode(1);/設(shè)置數(shù)據(jù)獲取方式 m_Serial.

6、SetInputLen(0);/設(shè)置讀取方式 & nbsp ;& nbsp ; m_Opened=m_Serail.SetPortOpen(1); /打開指定的串口 回來m_Opened; - 空的CSampleDlg:OnComm () & nbsp ; switch(m_Serial.GetCommEvent() 盒子2: /串行口數(shù)據(jù)接收,處理; - 方法二:在單線程中實現(xiàn)自定義的串口通信類 -控件簡單易用,但由于必須拿到對話框中使用,在一些需要在線程中實現(xiàn)通信的應(yīng)用場合,控件的使用顯得捉襟見肘。此時,若能夠按不同需要定制靈活的串口通信類將彌補控件的不足,以下將介紹如何在單線程中建立自定

7、義的通信類。 -該通信類CSimpleComm需手動加入頭文件與源文件,其基類為CObject,大致建立步驟如下: -(1) 打開串口,獲取串口資源句柄 -通信程序從CreateFile處指定串口設(shè)備及相關(guān)的操作屬性,再返回一個句柄,該句柄將被用于后續(xù)的通信操作,并貫穿整個通信過程。CreateFile() 函數(shù)中有幾個值得注意的參數(shù)設(shè)置:串口共享方式應(yīng)設(shè)為0,串口為不可共享設(shè)備;創(chuàng)建方式必須為OPEN_EXISTING,即打開已有的串口。對于dwFlagAndAttribute參數(shù),對串口有意義的值是FILE_FLAG_OVERLAPPED,該標(biāo)志表明串口采用異步通信模式,可進行重疊操作;若

8、值為NULL,則為同步通信方式,在同步方式下,應(yīng)用程序?qū)⑹冀K控制程序流,直到程序結(jié)束,若遭遇通信故障等因素,將導(dǎo)致應(yīng)用程序的永久等待,所以一般多采用異步通信。 -(2)串口設(shè)置 - BOOL & nbsp ; CSimpleComm:打開 () DCB dcb; m_hIDComDev=CreateFile ( “COM2, GENERIC_READ | GENERIC_WRITE,0, 空,打開_現(xiàn)有 ,文件_ATTRIBUTE_NORMAL | 文件_FLAG_OVE & nbsp ;& nbsp ;& nbsp ; RLAPPED ,空);& nbsp ;& nbsp ;& nbsp ;

9、& nbsp ;& nbsp ;& nbsp ; / 打開串口,異步操作 如果( m_hIDComDev =NULL )回來(假); & nbsp ;& nbsp ;& nbsp ; dcb.DCBlength = sizeof ( DCB ); GetCommState( m_hIDComDev, dcb ); /獲得端口默認設(shè)置 & nbsp ;& nbsp ; dcb.BaudRate=CBR_4800; & nbsp ;& nbsp ; dcb.ByteSize=8; & nbsp ;& nbsp ; dcb.Parity= NOPARITY ; & nbsp ;& nbsp ; dc

10、b.StopBits=(BYTE) ONESTOPBIT ; -(3)串口讀寫操作 -主要運用ReadFile()與WriteFile()API函數(shù),若為異步通信方式,兩函數(shù)中最后一個參數(shù)為指向OVERLAPPED結(jié)構(gòu)的非空指針,在讀寫函數(shù)返回值為FALSE的情況下,調(diào)用GetLastError()函數(shù),返回值為ERROR_IO_PENDING,表明I/O操作懸掛,即操作轉(zhuǎn)入后臺繼續(xù)執(zhí)行。此時,可以用WaitForSingleObject()來等待結(jié)束信號并設(shè)置最長等待時間。舉例如下: BOOLbReadStatus; bReadStatus = ReadFile ( m_hIDComDev

11、,緩沖區(qū), dwBytesRead, dwBytesRead,m_OverlappedRead ); 如果(! bReadStatus ) 如果( GetLastError () =ERROR_IO_PENDING ) & nbsp ;& nbsp ; WaitForSingleObject(m_OverlappedRead.hEvent,1000); 回來( int ) dwBytesRead ); 回來(0); 回來( int ) dwBytesRead ); -定義全局變量m_Serial作為新建通信類CSimpleComm的對象,通過調(diào)用類的成員函數(shù)即可實現(xiàn)所需串行通信功能。與方法一相

12、比,方法二賦予串行通信程序設(shè)計較大的靈活性,端口的讀寫可選擇較簡單的查詢式,或通過設(shè)置與外設(shè)數(shù)據(jù)發(fā)送時間間隔TimeCycle相同的定時器:SetTimer(1,TimeCycle,NULL),進行定時讀取或發(fā)送。 CSampleView: OnTimer ( UINT nIDEvent ) charInputData 30; & nbsp ;& nbsp ;& nbsp ;& nbsp ;& nbsp ;& nbsp ; m_Serial.ReadData(InputData,30); / 數(shù)據(jù)處理 -若對端口數(shù)據(jù)的響應(yīng)時間要求較嚴(yán)格,可采用事件驅(qū)動 I/O讀寫,Windows定義了9種串口

13、通信事件,較常用的有: EV_RXCHAR: 接收到一個字節(jié),并放入輸入 緩沖區(qū)。 EV_TXEMPTY: 輸出緩沖區(qū)中的最后一個字 符發(fā)送出去。 EV_RXFLAG: 接收到事件字符(DCB結(jié)構(gòu)中 EvtChar成員),放入輸入緩沖區(qū)。 -在用SetCommMask()指定了有用的事件后,應(yīng)用程序可調(diào)用WaitCommEvent()來等待事件的發(fā)生。SetCommMask(hComm,0)可使WaitCommEvent() 中止。 - 方法三:多線程下實現(xiàn)串行通信 - -線程的基本概念可詳見VC參考書目,Windows內(nèi)部的搶先調(diào)度程序在活動的線程之間分配CPU時間,Win 32 區(qū)分兩種不

14、同類型的線程,一種是用戶界面線程UI(User Interface Thread),它包含消息循環(huán)或消息泵,用于處理接收到的消息;另一種是工作線程(Work Thread),它沒有消息循環(huán),用于執(zhí)行后臺任務(wù)。用于監(jiān)視串口事件的線程即為工作線程。 -多線程通信類的編寫在端口的配置,連接部分與單線程通信類相同,在端口配置完畢后,最重要的是根據(jù)實際情況,建立多線程之間的同步對象,如信號燈、臨界區(qū)、事件等,相關(guān)細節(jié)可參考VC 中的同步類。 -一切就緒后即可啟動工作線程: CWinThrea CommThread = AfxBeginThread(CommWatchThread, / 線程函數(shù)名 (LP

15、VOID) m_pTTYInfo, / 傳遞的參數(shù) THREAD_優(yōu)先權(quán)_ABOVE_NORMAL, / 設(shè)置線程優(yōu)先級 (UINT) 0,/最大堆棧大小 (DWORD) CREATE_SUSPENDED, /創(chuàng)建標(biāo)志 (LPSECURITY_ATTRIBUTES) NULL);/安全性標(biāo)志 - 同時,在串口事件監(jiān)視線程中: if(WaitCommEvent(pTTYInfoidComDev, dwEvtMask,NULL) if(dwEvtMask pTTYInfodwEvtMask ) = pTTYInfodwEvtMask) WaitForSingleObject(pTTYInfohPo

16、stEvent,0xFFFFFFFF); ResetEvent(pTTYInfohPostEvent); / 置同步事件對象為非信號態(tài) : PostMessage ( CSampleView , ID_COM1_DATA ,0,0); / 發(fā)送通知消息 -用PostMessage()向指定窗口的消息隊列發(fā)送通知消息,相應(yīng)地,需要在該窗口建立消息與成員函數(shù)間的映射,用ON_MESSAGE將消息與成員函數(shù)名關(guān)聯(lián)。 BEGIN_MESSAGE_MAP ( CSampleView , CView ) / AFX_MSG_MAP ( CSampleView ) ON_MESSAGE ( ID_COM1_

17、DATA , OnProcessCom1Data ) ON_MESSAGE ( ID_COM2_DATA , OnProcessCom2Data ) / AFX_MSG_MAP END_MESSAGE_MAP () -然后在各成員函數(shù)中完成對各串口數(shù)據(jù)的接收處理,但必須保證在下一次監(jiān)測到有數(shù)據(jù)到來之前,能夠完成所有的中間處理工作,否則將造成數(shù)據(jù)的捕捉錯誤。 -多線程的實現(xiàn)可以使得各端口獨立,準(zhǔn)確地實現(xiàn)串行通信,使串口通信具有更廣泛的靈活性與嚴(yán)格性,且充分利用了CPU時間。但在具體的實時監(jiān)控系統(tǒng)中如何協(xié)調(diào)多個線程,線程之間以何種方式實現(xiàn)同步也是在多線程串行通信程序?qū)崿F(xiàn)的難點。 - 以 VC 6.

18、0 為工具,實現(xiàn)串行通信的三種方法各有利弊VC+ 簡單而強大 的多線程串口編程工具 CserialPort類一個串口類, 已作了一個基于對話框的同時檢測4個串口示例的程序,在這兒主要介紹如何將這個類應(yīng)用到VC中基于文檔的程序中。為了加深對串口數(shù)據(jù)處理的了解,我們利用這個類解決如下問題: 問題: 串口2(COM2)每隔1秒向串口1(COM1)發(fā)送的NEMA格式的報文:串頭為$,串尾為,中間為一個xxxx的整數(shù)( 比如2345,不足4位則前面以0代替代),最后是hh校驗,規(guī)定hh為xxxx四個數(shù)的半BYTE校驗和,最后加上回車與換行。整個數(shù)據(jù)包為$xxxx*hh。 串口1收到上述報文后,校驗正確后

19、,將發(fā)來的數(shù)據(jù)顯示在視窗中,并記下發(fā)來的正確幀數(shù)和錯誤幀數(shù),若正確,還向串口2發(fā)送Y,串口2收到Y(jié)后將收到的Y的計數(shù)顯示在視窗中。 測試方法: 將三線制串口線聯(lián)接上同一臺計算機的兩個串口,編好程序后就可測試。如果沒有兩個串口的微機,自己改改程序。 好了,你可以先下載源程序: scporttest.zip(大?。?9KB,VC6,WIN9X/2000,SerialPort.h SerialPort.cpp是兩個類文件) 編程步驟: 1. 建立程序: 建立一個基于單文檔的MFC應(yīng)用程序SCPortTest,所有步驟保持缺省狀態(tài)。 2. 添加類文件: 將SerialPort.h SerialPort

20、.cpp兩個類文件復(fù)制到工程文件夾中,用Project-Add to Project-Files命令將上述兩個文件加入工程。并在SCPortTestView.h中將頭文件SerialPort.h說明:#include SerialPort.h。 3. 人工增加串口消息響應(yīng)函數(shù):OnCommunication(WPARAM ch, LPARAM port) 首先在SCPortTestView.h中添加串口字符接收消息WM_COMM_RXCHAR(串口接收緩沖區(qū)內(nèi)有一個字符)的響應(yīng)函數(shù)聲明: / AFX_MSG ( CSCPortTestView ) afx_msg長的 OnCommunicati

21、on ( WPARAM ch , LPARAM端口 ); / AFX_MSG 然后在SCPortTestView.cpp文件中進行WM_COMM_RXCHAR消息映射: BEGIN_MESSAGE_MAP ( CSCPortTestView , CView ) / AFX_MSG_MAP ( CSCPortTestView ) ON_MESSAGE ( WM_COMM_RXCHAR , OnCommunication ) / AFX_MSG_MAP END_MESSAGE_MAP () 接著在SCPortTestView.cpp中加入函數(shù)的實現(xiàn): 長的 CSCPortTestView:OnCo

22、mmunication ( WPARAM ch , LPARAM端口 ) . 注意:由于這個串口類加入工程后,沒有自動的消息映射機制,因此上述步驟均需要手工添加。 4 初始化串口 在視創(chuàng)建時初始化串口,首先利用ClassWizardr按下圖生成OnInitialUpdate()函數(shù)。 接著在SerialPort.h文件中說明我們在程序中要用到的全局變量: 保存兩個串口接收數(shù)據(jù): char m_chChecksum;/用于COM1的校驗和計算 CString m_strRXhhCOM1;/用于存放COM1接收的半BYTE校驗字節(jié)hh CString m_strRXDataCOM1;/COM1接收

23、數(shù)據(jù) CString m_strRXDataCOM2;/COM2接收數(shù)據(jù) UINT m_nRXErrorCOM1;/COM1接收數(shù)據(jù)錯誤幀數(shù) UINT m_nRXErrorCOM2;/COM2接收數(shù)據(jù)錯誤幀數(shù) UINT m_nRXCounterCOM1;/COM1接收數(shù)據(jù)錯誤幀數(shù) UINT m_nRXCounterCOM2;/COM2接收數(shù)據(jù)錯誤幀數(shù)CString 再在SerialPort.h文件中說明串口類對象:CSerailPort m_ComPort2;(public)。 因為要初始化2個串口,所以這里用了數(shù)組。 下面是初始化串口1和串口2: 空的 CSCPortTestView:OnI

24、nitialUpdate () CView:OnInitialUpdate (); / TODO :添加你的這里的專業(yè)化的代碼并且/或呼叫底班 m_chChecksum=0;/校驗和置0 m_nRXErrorCOM1=0;/COM1接收數(shù)據(jù)錯誤幀數(shù)置0 m_nRXErrorCOM2=0;/COM2接收數(shù)據(jù)錯誤幀數(shù)置0 m_nRXCounterCOM1=0;/COM1接收數(shù)據(jù)錯誤幀數(shù)置0 m_nRXCounterCOM2=0;/COM2接收數(shù)據(jù)錯誤幀數(shù)置0 m_strRXhhCOM1.Empty();/清空半BYTE校驗hh存儲變量 適合于 ( int i=0;我2;i+) 如果 (m_ComP

25、orti.InitPort(this,i+1,9600,N,8,1,EV_RXFLAG | EV_RXCHAR ,512) /portnr=1(2),baud=960,parity=N,databits=8,stopsbits=1, / dwCommEvents=EV_RXCHAR | EV_RXFLAG ,nBufferSize=512 m_ComPorti.StartMonitoring();/啟動串口監(jiān)視線程 if(i=1) SetTimer(1,1000,NULL);/設(shè)置定時器,1秒后發(fā)送數(shù)據(jù) 另外 CString str; str.Format(COM%d 沒有發(fā)現(xiàn),或被其它設(shè)備占

26、用,i+1); AfxMessageBox ( str ); 5 利用ClassWizard按下圖生成CSCPortTestView 的時間消息WM_TIMER響應(yīng)函數(shù): 空的 CSCPortTestView:OnTimer ( UINT nIDEvent ) / TODO :添加你的這里的消息處理器代碼并且/或呼叫默認 int randdata=rand()%9000;/產(chǎn)生9000以內(nèi)的隨機數(shù) CString strSendData; strSendData.Format(%04d,randdata); SendString(strSendData, 2);/串口2發(fā)送數(shù)據(jù); CView:

27、OnTimer ( nIDEvent ); 上面用到的SendString()需按如下方式生成: 在ClassView中單擊鼠標(biāo)右鍵,在環(huán)境菜單中選擇Add Member Function: 空的 CSCPortTestView:SendString ( CString & str , int端口 ) char checksum=0, cr=CR , lf=LF; char c1,c2; 適合于 ( int i=0;i4)&0x0f ); 如果(c110)c1+=“0;另外的c1+=一-10; 如果(c2TextOut(10,50,strtemp);/顯示接收到的數(shù)據(jù) ReleaseDC ( pDC ); if(port=1) /COM1接收到數(shù)據(jù) m_strRXDataCOM1+=( char ) ch; 切換( ch ) 大小寫“$”: m_chChecksum=0;/開始計算CheckSum flag=0; 打破; 大小寫“*”: flag=2; c2=m_chChecksum&0x0f;c1=( m_chChecksum4)&0x0f ); 如果(c110)c1+=“0;另外的c1

溫馨提示

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

評論

0/150

提交評論