基於VC++的串口編程

串行通信接口標準有多個版本,但是基本上都是在RS-232標準的基礎上發展而來。RS-232C標準時美國EIA和BELL等公司一起開發並於1969年公佈的通信協議。1997年TIA發不了最新的一個版本,命名爲TIA/EIA-232-F。ITU和CCITT發佈了一個類似的標準-V.28。RS-232C標準最初是爲遠程通信連接數據終端設備DTE和數據通信設備DCE而制定的。因此RS-232C標準中所提到的發送和接收都是站在DTE立場上,而不是站在DCE的立場上來定義的。
RS-232採用負邏輯,即+3V~+15V表示邏輯0,而-3V~-15V表示邏輯1。而在RTS/CTS/DSR/DTR/DCD等控制線上,+3V~+15V表示信號有效,-3V~-15V表示信號無效。
RS-232C並未定義連接器的物理特性,因此出現了DB-25、DB-15和DB-9各種類型的連接器,其引腳的定義也各不相同,DB9定義如圖1所示。通信速率低於20kbps時,且碼元畸變小於4%時,要求驅動器的負載電容小於2500pF,支持最長距離爲15m。

image

圖1 RS232 DB9引腳定義

PC機的每個串口都保留了一序列的端口資源,大多數都有一個指定的中斷請求IRQ或中斷請求級別,端口被命名爲COM1、COM2等。在Widnows中可以在控制面板中瀏覽端口資源。端口可以使用硬件支持的任何地址和IRQ號,每個端口保留8個連續地址,從基址開始的寄存器。串行接口包括4個主要寄存器,即控制寄存器、狀態寄存器、數據輸入寄存器及數據輸出寄存器。

串行通信協議分爲同步協議和異步協議
(1)面向字符的同步協議,這種協議的典型代表是IBM公司開發的BSC協議。它的特點是一次傳送由若干字符組成的數據塊,而不是隻傳送一個字符,並規定了10個字符作爲這個數據塊的開頭和結束標誌以及整個傳輸過程的控制信息,也叫做通信控制字。此種協議涉及到“數據透明”和“字符填充技術”。
(2)面向比特的同步協議HDLC,不是靠特定字符來標識幀的開始和結束,故稱“面向比特”的協議。包含有標識場、地址場、控制場、信息場和幀校驗信息。
(3)起止式異步協議,一個字符一個字符地傳輸,並且傳送一個字符總是以起始比特開始,以停止位結束,字符之間沒有固定的時間間隔要求。起始比特是用來通知收方,以此來重新覈對收發雙方同步。若接收設備和發送設備兩者的時鐘頻率略有偏差,也不會因偏差的累積而導致錯位。但是由於需要起始位和停止比特位這樣一些附加位,使得傳輸效率只有約80%。因此這種協議一般用在數據速率較慢的場合,而高速傳送時,一般要採用同步協議。

Widnows系統下進行串口編程有多種方法:1)API方式:CreateFile,GetCommState,SetCommState,ReadFile,WriteFile。2)ActiveX方式:MSComm控件。3)直接嵌入彙編方式:Windows98以前使用。4)VXD或者WDM實現。

MSComm控件通過串行傳輸和接收數據,並且在VC,CB以及Delphi等語言中都可以使用。MSComm提供了兩種處理通信問題的方法:一是事件驅動方法,一是查詢法。

1.事件驅動方式
當發生特定事件,比如接收到一個字符或者一個RTS/CD事件時,就會發生OnComm事件,而且還可以檢查和處理通信錯誤。在編程過程中,可以在OnComm事件處理函數中加入自己的處理代碼。這種方法的優點是程序響應及時,可靠性高。每個MSComm控件對應着一個串行端口,如果應用程序要訪問多個換行端口,必須使用多個MSComm控件。

2.查詢方式
查詢方式本質上還是屬於事件驅動,通過檢查CommEvent屬性的值來檢查事件和錯誤,只要CommEvent屬性的值有了變化,就表明一個通信事件或一個錯誤發生。如果應用程序較小,且自成一體,這種方法是比較方便的。

MSComm控件的屬性:
(1)CommPort屬性
void SetCommPort(short nNewValue);
short GetCommPort();
此屬性用於設置和返回連接的串行端口號,必須在打開端口之前設置CommPort屬性。設置時,nNewValue可以設置成1~16的任何數(默認爲1)。但是如果用PortOpen方法打開一個並不存在的端口時,MSComm控件會產生錯誤68(設備無效)。
(2)Settings屬性
void SetSettings(LPCTSTR lpszNewValue);
String GetSettings();
該屬性包含數據傳輸速率、奇偶校驗、數據比特、停止比特位參數,打開端口前必須設置。當端口打開時,如果value非法,則控件產生錯誤380(非法屬性值)。其中lpszNewValue用字符串表示,由四個設置值組成,有如下的組成格式:
“BBBB,P,D,S”
BBBB爲數據傳輸速率,P爲就校驗,D爲數據比特數,S爲停止比特數。

(3)RThreshold屬性
void SetRThreshold(short nNewValue);
short GetRThreshold();
控件設置CommEvent屬性爲comEvReceive併產生OnComm之前要接收的字符數。當接收字符後,如果RThreshold屬性爲0,則不會產生OnComm事件。否則當接收緩衝區內字節個數達到或超過該值就會產生OnComm事件。
(4)SThreshold屬性
void SetSThreshold(short nNewValue);
short GetSThreshold();
控件設置CommEvent屬性爲comEvSend併產生OnComm事件之前,設置並返回傳輸緩衝區中允許的最小字符數。nNewValue代表在OnComm事件產生之前在傳輸緩衝區中的最小字符數。如果設置SThreshold屬性爲0(默認值),數據傳輸事件不會產生OnComm事件。若設置SThreshold屬性爲1,當傳輸緩衝區完全空時,MSCOmm空間產生OnComm事件。如果在傳輸緩衝區的字符數小於Value,CommEvent屬性設置爲comEvSend,併產生OnComm事件。CommEvSend事件僅當字符數與SThreshold交叉時被激活一次。
(5)InputMode屬性
void SetInputMode(long nNewValue);
long GetInputMode();
該屬性用於設置或者返回傳輸數據的類型,即以文本或二進制方式取回數據
(6)InputLen屬性
void SetInputLen(short nNewVlaue);
short GetInputLen();
該屬性用於設置並返回Input屬性從接受緩衝區讀取的字符數。如果設置爲0,則Input將讀取接受緩衝區的所有數據。在使用Input前,用戶可以選擇檢查InBufferCount屬性來確定緩衝區中是否已有需要數目的字符,該屬性在從輸出格式爲定常數據的機器讀取數據時非常有用。
(7)InBufferSize屬性
void SetInBufferSize(short nNewValue);
short GetInBufferSize();
設置和返回輸入緩衝區的大小,默認值爲1024字節
(8)InBufferCount屬性
void setInBufferCount(short nNewValue);
short GetInBufferCount();
返回輸入緩衝區內的等待讀取的字節個數,可以通過該屬性值爲0來清除接收緩衝區
(9)Input屬性
VARIANT GetInput();
表示從接收緩衝區移走一串字符,將緩衝區接收到的數據讀入變量,屬性值爲Variant型變量,即當InputMode屬性值爲0(文本模式)時,變量中含String型數據。當InputMode屬性值爲1(二進制模式)時,變量中含有Byte型數組數據。該屬性在端口未打開時不可用,在運行時是隻讀的。
(10)PortOpen屬性
void SetPortOpen(BOOL bNewValue);
BOOL GetPortOpen();
打開或關閉端口,通常需要顯式打開或關閉串口。
(11)OutBuffersize屬性
void SetOutBufferSize(short nNewValue);
設置或者返回發送緩衝區的大小,默認爲512字節。發送緩衝區設置越大,應用程序可用內存就越小,然而如果設置太小,緩衝區將會溢出,除非使用握手協議。
(12)OutBufferCounter屬性
void SetOutBufferCounter(short nNewValue);
short GetOutBufferSize();
返回發送緩衝區內等待發送的字節數,可以用來清空發送緩衝區。
(13)OutPut屬性
void SetOutput(const VARIANT &newValue);
向發送緩衝區寫數據流,屬性爲Variant變量。在端口未打開時不可用,在運行時是隻寫的。Output屬性可以發送文本數據或二進制數據,通常發送ANSI字符串可以以文本方式發送,如果數據包含了內嵌控制字符,Null字符等,必須將其作爲二進制傳輸。
(14)DTREnable屬性
void SetDTREnable(BOOL bNewValue);
BOOL GetDTREnable();
設置DTR線是否有效
(15)RTSEnable屬性
void SetRTSEnable(BOOL bNewValue);
BOOL GetRTSEnable();
設置RST線是否有效。
(16)DSRHolding屬性
判斷DSR線是否有效
(17)CDHolding屬性
判斷CD線的狀態是否有效
(18)CTSHolding屬性
用於判斷CTS先的狀態

API串口通信編程
在WIN32 API中,串口使用文件方式進行訪問,其操作的API基本上與文件操作的API一致。
打開串口:
Win32中用於打開串口的API函數爲CreateFile,其原型爲:
HANDLE CreateFile (
LPCTSTR lpFileName, //將要打開的串口邏輯名,如COM1 或COM2
DWORD dwAccess, //指定串口訪問的類型,可以是讀取、寫入或兩者並列
DWORD dwShareMode, //指定共享屬性,由於串口不能共享,該參數必須置爲0
LPSECURITY_ATTRIBUTES lpsa, //引用安全性屬性結構,缺省值爲NULL
DWORD dwCreate, //創建標誌,對串口操作該參數必須置爲OPEN EXISTING
DWORD dwAttrsAndFlags, //屬性描述,用於指定該串口是否可進行異步操作,
//FILE_FLAG_OVERLAPPED:可使用異步的I/O
HANDLE hTemplateFile //指向模板文件的句柄,對串口而言該參數必須置爲NULL
);
windows文件操作分爲同步I/O和重疊I/O(Overlapped I/O)兩種方式,在同步I/O方式中,API會阻塞直到操作完成以後才能返回(在多線程方式中,雖然不會阻塞主線程,但是仍然會阻塞監聽線程);而在重疊I/O方式中,API會立即返回,操作在後臺進行,避免線程的阻塞。重疊I/O非常靈活,它也可以實現阻塞(比如可以設置一定要讀取到一個數據才能進行到下一步操作)。如果進行I/O操作的API在沒有完成操作的情況下返回,我們可以通過調用GetOverLappedResult()函數阻塞到I/O完成後返回。
配置串口:
配置串口是通過改變設備控制塊DCB(Device Control Block)的成員變量來實現的,接收緩衝區和發送緩衝區的大小可通過SetupComm函數來設置。
DCB結構體定義爲:
typedef struct _DCB { // dcb
DWORD DCBlength; // sizeof(DCB)
DWORD BaudRate; // current baud rate
DWORD fBinary: 1; // binary mode, no EOF check
DWORD fParity: 1; // enable parity checking
DWORD fOutxCtsFlow:1; // CTS output flow control
DWORD fOutxDsrFlow:1; // DSR output flow control
DWORD fDtrControl:2; // DTR flow control type
DWORD fDsrSensitivity:1; // DSR sensitivity
DWORD fTXContinueOnXoff:1; // XOFF continues Tx
DWORD fOutX: 1; // XON/XOFF out flow control
DWORD fInX: 1; // XON/XOFF in flow control
DWORD fErrorChar: 1; // enable error replacement
DWORD fNull: 1; // enable null stripping
DWORD fRtsControl:2; // RTS flow control
DWORD fAbortOnError:1; // abort reads/writes on error
DWORD fDummy2:17; // reserved
WORD wReserved; // not currently used
WORD XonLim; // transmit XON threshold
WORD XoffLim; // transmit XOFF threshold
BYTE ByteSize; // number of bits/byte, 4-8
BYTE Parity; // 0-4=no,odd,even,mark,space
BYTE StopBits; // 0,1,2 = 1, 1.5, 2
char XonChar; // Tx and Rx XON character
char XoffChar; // Tx and Rx XOFF character
char ErrorChar; // error replacement character
char EofChar; // end of input character
char EvtChar; // received event character
WORD wReserved1; // reserved; do not use
} DCB;

而SetupComm函數的原型則爲:
BOOL SetupComm(
HANDLE hFile, // handle to communications device
DWORD dwInQueue, // size of input buffer
DWORD dwOutQueue // size of output buffer
);

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章