VC++串口通訊編程詳解

來源:互聯網
上載者:User

標籤:

  在Win32下,可以使用兩種編程方式實現串口通訊,其一是使用ActiveX控制項,這種方法程式簡單,但欠靈活。其二是調用Windows的API函數,這種方法可以清楚地掌握串口通訊的機制,並且自由靈活。下面是介紹的是關於API串口通訊內容。

  串口的操作可以有兩種操作方式:同步操作方式和重疊操作方式(又稱為非同步作業方式)。同步操作時,API函數會阻塞直到操作完成以後才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監聽線程);而重疊操作方式,API函數會立即返回,操作在後台進行,避免線程的阻塞。

   但是無論那種操作方式,一般都會通過以下四個步驟來完成:

  (1) 開啟串口;

  (2) 配置串口;

  (3) 讀寫串口;

  (4) 關閉串口;

   1、開啟串口

  Win32系統把檔案的概念進行了擴充。無論是檔案、通訊裝置、具名管道、郵件槽、磁碟、還是控制台,都是使用API函數CreateFile來開啟或建立的。該函數的原型為:

 1 HANDLE CreateFile(  2  3         LPCTSTR lpFileName, //需要開啟的串口邏輯名,如"COM3"        4   5         DWORD dwDesiredAccess,//指定串口的訪問類型,讀、寫或者是兩者共存,讀:GENERIC_READ、寫:GENERIC_WRITE 6  7         DWORD dwShareMode, //指定共用屬性,但是串口不能共用,該參數必須為0 8  9         LPSECURITY_ATTRIBUTES lpSecurityAttributes, //引用安全性屬性結構,預設值為NULL10 11         DWORD dwCreationDistribution, //建立標誌,對串口操作時該參數必須為OPEN_EXISTING12 13         DWORD dwFlagsAndAttributes, //屬性描述,指定該串口是同步還是非同步,該值為FILE_FLAG_OVERLAPPED,表示使用非同步I/O;該值為0,表示同步I/O操作;14 15         HANDLE hTemplateFile//對串口來說,該參數為NULL16 17   );    

  2、配置串口

       在開啟通訊裝置的控制代碼後,需要對串口進行一些初始化的配置。這就需要通過一個DCB結構來進行。DCB結構包含了如傳輸速率、資料位元數、同位和停止位元等資訊。在查詢或配置串口的屬性時,都要用DCB結構來作為緩衝區。

       一般在用CreateFile開啟串口後,調用GetCommState函數來擷取串口的初始配置。在要修改串口的配置時,應該先修改DCB結構,然後再調用SetCommState函數來設定串口。
  DCB結構包含了串口的各項參數設定,下面僅介紹幾個該結構常用的變數:

1 typedef struct _DCB{2             DWORD BaudRate,//傳輸速率:9600、115200等等3             DWORD fParity,//指定同位,為1時,允許同位4             BYTE ByteSize,//通訊位元組位,4-8位5             BYTE Parity,//指定同位的方法,EVENPARITY 偶校正、 NOPARITY 無校正、MARKPARITY 標記校正、ODDPARITY 奇數同位6             BYTE StopBits,//指定停止位的位元:ONESTOPBIT、ON 5STOPBITS、TWOSTOPBITS7 };
DCB結構

  GetCommState函數可以擷取COM口的裝置控制塊,從而擷取相關參數,原型如下

1 BOOL GetCommState( 2     HANDLE hFile, //標識通訊連接埠的控制代碼 3     LPDCB lpDCB //指向一個裝置控制塊(DCB結構)的指標4  ); 

  SetCommState函數設定COM口的裝置控制塊,原型為:

1 BOOL SetCommState( 2     HANDLE hFile, //標識通訊連接埠的控制代碼3     LPDCB lpDCB//指向一個裝置控制塊4  );  

  我們除了在DCB中的設定外,程式一般還需要設定I/O緩衝區的大小和逾時。

  Windows中用I/O緩衝區來暫存串口輸入和輸出的資料。如果通訊的速率較高,則應該設定較大的緩衝區。調用SetupComm函數可以設定串列口的輸入和輸出緩衝區的大小。 原型如下:

1 BOOL SetupComm( 2     HANDLE hFile, // 通訊裝置的控制代碼 3     DWORD dwInQueue, // 輸入緩衝區的大小(位元組數)4     DWORD dwOutQueue // 輸出緩衝區的大小(位元組數)5  );  

  在用ReadFile和WriteFile讀寫串列口時,需要考慮逾時問題。

  逾時的作用是在指定的時間內沒有讀入或發送指定數量的字元,ReadFile或WriteFile的操作仍然會結束。要查詢當前的逾時設定應調用GetCommTimeouts函數,該函數會填充一個COMMTIMEOUTS結構。調SetCommTimeouts可以用某一個COMMTIMEOUTS結構的內容來設定逾時。

  讀寫串口的逾時有兩種:間隔逾時和總逾時。間隔逾時是指在接收時兩個字元之間的最大時延。總逾時是指讀寫操作總共花費的最大時間。寫操作只支援總逾時,而讀操作兩種逾時均支援。

  用COMMTIMEOUTS結構可以規定讀寫操作的逾時,原型如下:

1 typedef struct _COMMTIMEOUTS { 2     DWORD ReadIntervalTimeout; //讀間隔逾時 3     DWORD ReadTotalTimeoutMultiplier; //讀時間係數 4     DWORD ReadTotalTimeoutConstant; //讀時間常量 5     DWORD WriteTotalTimeoutMultiplier; // 寫時間係數 6     DWORD WriteTotalTimeoutConstant; //寫時間常量 7 } COMMTIMEOUTS,*LPCOMMTIMEOUTS;  

  COMMTIMEOUTS結構的成員都以毫秒為單位。總逾時的計算公式是:

總逾時=時間係數×要求讀/寫的字元數+時間常量例如,要讀入10個字元,那麼讀操作的總逾時的計算公式為:

讀總逾時=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant

可以看出:間隔逾時和總逾時的設定是不相關的,這可以方便通訊程式靈活地設定各種逾時。

  如果所有寫逾時參數均為0,那麼就不使用寫逾時。如果ReadIntervalTimeout為0,那麼就不使用讀間隔逾時。如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都為0,則不使用讀總逾時。如果讀間隔逾時被設定成MAXDWORD並且讀時間係數和讀時間常量都為0,那麼在讀一次輸入緩衝區的內容後讀操作就立即返回,而不管是否讀入了要求的字元。
  在用重疊方式讀寫串口時,雖然ReadFile和WriteFile在完成操作以前就可能返回,但逾時仍然是起作用的。在這種情況下,逾時規定的是操作的完成時間,而不是ReadFile和WriteFile的返回時間。

  配置串口的範例程式碼:

 1 SetupComm(hCom,1024,1024); //輸入緩衝區和輸出緩衝區的大小都是1024 2 COMMTIMEOUTS TimeOuts; //設定讀逾時 3 TimeOuts.ReadIntervalTimeout=1000; 4 TimeOuts.ReadTotalTimeoutMultiplier=500; 5 TimeOuts.ReadTotalTimeoutConstant=5000; //設定寫逾時 6 TimeOuts.WriteTotalTimeoutMultiplier=500;  7 TimeOuts.WriteTotalTimeoutConstant=2000;  8 SetCommTimeouts(hCom,&TimeOuts); //設定逾時 DCB dcb;  9 GetCommState(hCom,&dcb); 10 dcb.BaudRate=9600; //傳輸速率為9600 11 dcb.ByteSize=8; //每個位元組有8位 12 dcb.Parity=NOPARITY; //無同位位元 13 dcb.StopBits=TWOSTOPBITS; //兩個停止位14 SetCommState(hCom,&dcb);15 PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR); //清空緩衝區

  在進行讀寫串口之前,還要用PurgeComm()函數清空緩衝區,該函數原型: 

1 BOOL PurgeComm( 2     HANDLE hFile, //串口控制代碼 3     DWORD dwFlags // 需要完成的操作,PURGE_TXABORT 中斷所有寫操作並立即返回,即使寫操作還沒有完成; PURGE_RXABORT 中斷所有讀操作並立即返回,即使讀操作還沒有完成;PURGE_TXCLEAR 清除輸出緩衝區 ;PURGE_RXCLEAR 清除輸入緩衝區 4 );  

   3、讀寫串口

       我們使用ReadFile和WriteFile讀寫串口,下面是兩個函數的聲明:

1 BOOL ReadFile( 2     HANDLE hFile, //串口的控制代碼  3     LPVOID lpBuffer// 讀入的資料存放區的地址,即讀入的資料將儲存在以該指標的值為首地址的一片記憶體區, 4     DWORD nNumberOfBytesToRead, // 要讀入的資料的位元組數 5     LPDWORD lpNumberOfBytesRead,// 指向一個DWORD數值,該數值返回讀操作實際讀入的位元組數 6     LPOVERLAPPED lpOverlapped  // 重疊操作時,該參數指向一個OVERLAPPED結構,同步操作時,該參數為NULL。 7 );

  寫函數的聲明原型:

1 BOOL WriteFile( 2     HANDLE hFile, //串口的控制代碼3     LPCVOID lpBuffer,   // 寫入的資料存放區的地址4     DWORD nNumberOfBytesToWrite, //要寫入的資料的位元組數5     LPDWORD lpNumberOfBytesWritten, // 指向指向一個DWORD數值,該數值返回實際寫入的位元組數 6     LPOVERLAPPED lpOverlapped // 重疊操作時,該參數指向一個OVERLAPPED結構,同步操作時,該參數為NULL。 7 );  

  ReadFile和WriteFile函數是同步還是非同步由CreateFile函數決定,如果在調用CreateFile建立控制代碼時指定了FILE_FLAG_OVERLAPPED標誌,那麼調用ReadFile和WriteFile對該控制代碼進行的操作就應該是重疊的;如果未指定重疊標誌,則讀寫操作應該是同步的。ReadFile和WriteFile函數的同步或者非同步應該和CreateFile函數相一致。

  在使用ReadFile 函數進行讀操作前,應先使用ClearCommError函數清除錯誤。ClearCommError函數的原型如下:

1 BOOL ClearCommError( 2     HANDLE hFile, // 串口控制代碼 3     LPDWORD lpErrors, // 指向接收錯誤碼的變數 4     LPCOMSTAT lpStat // 指向通訊狀態緩衝區 5 );  

該函數獲得通訊錯誤並報告串口的目前狀態,同時,該函數清除串口的錯誤標誌以便繼續輸入、輸出操作。參數lpStat指向一個COMSTAT結構,該結構返回串口狀態資訊。

例舉一下同步方式讀寫串口的代碼:

 1 //同步讀串口  2 char str[100];  3 DWORD wCount;//讀取的位元組數  4 BOOL bReadStat; bReadStat=ReadFile(hCom,str,100,&wCount,NULL);  5 if(!bReadStat)  6 {  7     AfxMessageBox("讀串口失敗!");  8     return FALSE;  9 } 10 return TRUE; 11 12 //同步寫串口 13 char lpOutBuffer[100]; 14 DWORD dwBytesWrite=100; 15 COMSTAT ComStat; 16 DWORD dwErrorFlags; 17 BOOL bWriteStat; ClearCommError(hCom,&dwErrorFlags,&ComStat);18 bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL); 19 if(!bWriteStat) 20 { 21     AfxMessageBox("寫串口失敗!"); 22 } 23 PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);  

  4、關閉串口

       利用API函數關閉串口非常簡單,只需使用CreateFile函數返回的控制代碼作為參數調用CloseHandle即可:

1 BOOL CloseHandle(2     HANDLE hObject; //handle to object to close3 );

 

VC++串口通訊編程詳解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

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.