2、配置串口
在打開通訊設備句柄后,常常需要對串口進行一些初始化配置工作。這需要通過一個DCB結構來進行。DCB結構包含了諸如波特率、數據位數、奇偶校驗和停止位數等信息。在查詢或配置串口的屬性時,都要用DCB結構來作為緩沖區。
一般用CreateFile打開串口后,可以調用GetCommState函數來獲取串口的初始配置。要修改串口的配置,應該先修改DCB結構,然后再調用SetCommState函數設置串口。
DCB結構包含了串口的各項參數設置,下面僅介紹幾個該結構常用的變量:
typedef struct _DCB{ ………
DWORD BaudRate;//波特率,指定通信設備的傳輸速率。這個成員可以是實際波特率值或者下面的常量值之一: CBR_110,CBR_300,CBR_600,CBR_1200,CBR_2400,CBR_4800,CBR_9600,CBR_19200, CBR_38400, CBR_56000, CBR_57600, CBR_115200, CBR_128000, CBR_256000, CBR_14400
DWORD fParity; // 指定奇偶校驗使能。若此成員為1,允許奇偶校驗檢查 …
BYTE ByteSize; // 通信字節位數,4—8
BYTE Parity; //指定奇偶校驗方法。此成員可以有下列值: EVENPARITY 偶校驗 NOPARITY 無校驗 MARKPARITY 標記校驗 ODDPARITY 奇校驗
BYTE StopBits; //指定停止位的位數。此成員可以有下列值: ONESTOPBIT 1位停止位 TWOSTOPBITS 2位停止位
ON 5STOPBITS 1.5位停止位
GetCommState函數可以獲得COM口的設備控制塊,從而獲得相關參數:
BOOL GetCommState(
HANDLE hFile, //標識通訊端口的句柄
LPDCB lpDCB //指向一個設備控制塊(DCB結構)的指針 );
SetCommState函數設置COM口的設備控制塊:
BOOL SetCommState( HANDLE hFile, LPDCB lpDCB );
除了在BCD中的設置外,程序一般還需要設置I/O緩沖區的大小和超時。Windows用I/O緩沖區來暫存串口輸入和輸出的數據。如果通信的速率較高,則應該設置較大的緩沖區。調用SetupComm函數可以設置串行口的輸入和輸出緩沖區的大小。
BOOL SetupComm( HANDLE hFile, // 通信設備的句柄
DWORD dwInQueue, // 輸入緩沖區的大?。ㄗ止潝担?/p>
DWORD dwOutQueue // 輸出緩沖區的大?。ㄗ止潝担?);
在用ReadFile和WriteFile讀寫串行口時,需要考慮超時問題。超時的作用是在指定的時間內沒有讀入或發送指定數量的字符,ReadFile或WriteFile的操作仍然會結束。
要查詢當前的超時設置應調用GetCommTimeouts函數,該函數會填充一個COMMTIMEOUTS結構。調用SetCommTimeouts可以用某一個COMMTIMEOUTS結構的內容來設置超時。
讀寫串口的超時有兩種:間隔超時和總超時。間隔超時是指在接收時兩個字符之間的最大時延??偝瑫r是指讀寫操作總共花費的最大時間。寫操作只支持總超時,而讀操作兩種超時均支持。用COMMTIMEOUTS結構可以規定讀寫操作的超時。
COMMTIMEOUTS結構的定義為:
typedef struct _COMMTIMEOUTS {
DWORD ReadIntervalTimeout; //讀間隔超時
DWORD ReadTotalTimeoutMultiplier; //讀時間系數
DWORD ReadTotalTimeoutConstant; //讀時間常量
DWORD WriteTotalTimeoutMultiplier; // 寫時間系數
DWORD WriteTotalTimeoutConstant; //寫時間常量
} COMMTIMEOUTS,*LPCOMMTIMEOUTS;
COMMTIMEOUTS結構的成員都以毫秒為單位。
總超時的計算公式是:總超時=時間系數×要求讀/寫的字符數+時間常量
例如,要讀入10個字符,那么讀操作的總超時的計算公式為:
讀總超時=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant
可以看出:間隔超時和總超時的設置是不相關的,這可以方便通信程序靈活地設置各種超時。
如果所有寫超時參數均為0,那么就不使用寫超時。如果ReadIntervalTimeout為0,那么就不使用讀間隔超時。如果ReadTotalTimeoutMultiplier 和 ReadTotalTimeoutConstant 都為0,則不使用讀總超時。如果讀間隔超時被設置成MAXDWORD并且讀時間系數和讀時間常量都為0,那么在讀一次輸入緩沖區的內容后讀操作就立即返回,而不管是否讀入了要求的字符。
在用重疊方式讀寫串口時,雖然ReadFile和WriteFile在完成操作以前就可能返回,但超時仍然是起作用的。在這種情況下,超時規定的是操作的完成時間,而不是ReadFile和WriteFile的返回時間。
配置串口的示例代碼:
SetupComm(hCom,1024,1024); //輸入緩沖區和輸出緩沖區的大小都是1024
COMMTIMEOUTS TimeOuts; //設定讀超時
TimeOuts.ReadIntervalTimeout=1000;
TimeOuts.ReadTotalTimeoutMultiplier=500;
TimeOuts.ReadTotalTimeoutConstant=5000; //設定寫超時
TimeOuts.WriteTotalTimeoutMultiplier=500;
TimeOuts.WriteTotalTimeoutConstant=2000;
SetCommTimeouts(hCom,&TimeOuts); //設置超時
DCB dcb;
GetCommState(hCom,&dcb);
dcb.BaudRate=9600; //波特率為9600
dcb.ByteSize=8; //每個字節有8位
dcb.Parity=NOPARITY; //無奇偶校驗位
dcb.StopBits=TWOSTOPBITS; //兩個停止位
SetCommState(hCom,&dcb);
PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
在讀寫串口之前,還要用PurgeComm()函數清空緩沖區,該函數原型:
BOOL PurgeComm( HANDLE hFile, //串口句柄
DWORD dwFlags // 需要完成的操作 );
參數dwFlags指定要完成的操作,可以是下列值的組合:
PURGE_TXABORT 中斷所有寫操作并立即返回,即使寫操作還沒有完成。
PURGE_RXABORT 中斷所有讀操作并立即返回,即使讀操作還沒有完成。
PURGE_TXCLEAR 清除輸出緩沖區
PURGE_RXCLEAR 清除輸入緩沖區
評論