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