1 串口是一种时常用来与外界通信的一种设备,虽然现在网络已经很普及,但由于PC机时常需要通过MODEM与远距离主机或是与单片机设备进行通信所以串口的用途还是很广泛。
2 串口在Win32的开发中可以以文件的形式来进行打开和关闭,并且串口的读写也可以利用ReadFile和WriteFile来进行操作。以前在Windows 3.X下的OpenComm等部分串口操作函数已经被废弃。
3 串口的开打可以使用下面的方法:
4 HANDLE hDev = CreateFile( "COM1", 指明串口名称,COM1代表第一个串口,COM2代表第二个串口
5 GENERIC_READ | GENERIC_WRITE, 用于读和写
6 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, 指明为异步操作方式
7
8 NULL );
9 串口被打开后,马上要进行的操作就是设置串口的状态和属性,通过指定一个DCB的结构来对串口进行设置,所使用的函数有下面这些
10 BOOL SetCommState(
11 HANDLE hFile, handle to communications device
12 LPDCB lpDCB device-control block
13 );
14
15 其中DCB结构为
16 typedef struct _DCB {
17 DWORD DCBlength; sizeof(DCB) 结构长度
18 DWORD BaudRate; current baud rate 波特率 可取下面的值,表示每秒的速率(bit per second)
19 /*
20 CBR_110 CBR_19200 CBR_300 CBR_38400 CBR_600 CBR_56000 CBR_1200 CBR_57600
21 CBR_2400 CBR_115200 CBR_4800 CBR_128000 CBR_9600 CBR_256000 CBR_14400 */
22 DWORD fBinary: 1; binary mode, no EOF check 二进制方式
23 DWORD fParity: 1; enable parity checking 允许奇偶校验
24 DWORD fOutxCtsFlow:1; CTS output flow control CTS(clear-to-send)流控
25 DWORD fOutxDsrFlow:1; DSR output flow control DSR(data-set-ready)流控
26 DWORD fDtrControl:2; DTR flow control type DTR(data-terminal-ready)流制
27 DWORD fDsrSensitivity:1; DSR sensitivity 是否检测握手信号
28 DWORD fTXContinueOnXoff:1; XOFF continues Tx
29 DWORD fOutX: 1; XON/XOFF out flow control
30 DWORD fInX: 1; XON/XOFF in flow control
31 DWORD fErrorChar: 1; enable error replacement
32 DWORD fNull: 1; enable null stripping
33 DWORD fRtsControl:2; RTS flow control
34 DWORD fAbortOnError:1; abort on error
35 DWORD fDummy2:17; reserved
36 WORD wReserved; not currently used
37 WORD XonLim; transmit XON threshold
38 WORD XoffLim; transmit XOFF threshold
39 BYTE ByteSize; number of bits/byte, 4-8 数据位
40 BYTE Parity; 0-4=no,odd,even,mark,space 校验方式
41 BYTE StopBits; 0,1,2 = 1, 1.5, 2 停止位
42 char XonChar; Tx and Rx XON character
43 char XoffChar; Tx and Rx XOFF character
44 char ErrorChar; error replacement character
45 char EofChar; end of input character
46 char EvtChar; received event character
47 WORD wReserved1; reserved; do not use
48 } DCB;
49 通过一个字符串来建立DCB结构
50 例如字符串:baud=1200 parity=N data=8 stop=1 表明使用1200BPS速率,偶校验,8位数据位,1位停止位
51 BOOL BuildCommDCB(
52 LPCTSTR lpDef, device-control string
53 LPDCB lpDCB device-control block
54 );
55 设置端口的缓冲区大小
56 BOOL SetupComm(
57 HANDLE hFile, handle to communications device
58 DWORD dwInQueue, size of input buffer 输入缓冲区大小
59 DWORD dwOutQueue size of output buffer 输出缓冲区大小
60 );
61
62 串口的读写依然可以利用ReadFile和WriteFile函数,这里介绍另一个函数来查询端口状态,
63 BOOL ClearCommError(
64 HANDLE hFile, handle to communications device
65 LPDWORD lpErrors, error codes
66 LPCOMSTAT lpStat communications status
67 );
68
69 COMSTAT结构如下
70 typedef struct _COMSTAT {
71 DWORD fCtsHold : 1;
72 DWORD fDsrHold : 1;
73 DWORD fRlsdHold : 1;
74 DWORD fXoffHold : 1;
75 DWORD fXoffSent : 1;
76 DWORD fEof : 1;
77 DWORD fTxim : 1;
78 DWORD fReserved : 25;
79 DWORD cbInQue; //接收队列内数据量
80 DWORD cbOutQue; 发送队列内数据量
81 } COMSTAT, *LPCOMSTAT;
82 //从串口内读取数据
83 {
84 BOOL bReadStatus;
85 DWORD dwBytesRead, dwErrorFlags;
86 COMSTAT ComStat;
87 ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
88 if( !ComStat.cbInQue ) return( 0 ); //检查当前是否有数据在接收队列内
89 dwBytesRead = (DWORD) ComStat.cbInQue;
90 if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit; //确定当前可能读入的最大数量
91 bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
92 if( !bReadStatus )
93 {
94 if( GetLastError() == ERROR_IO_PENDING )
95 {
96 WaitForSingleObject( m_OverlappedRead.hEvent, 2000 ); //等待读操作完成
97 return( (int) dwBytesRead );
98 }
99 return( 0 );
100 }
101 }
102
103 //在本节提供一个经过封装的类CSerial来完成串口的操作,这份代码来自于网上,我写了一个简单的DEMO用于向MODEM发送AT命令并读回数据。相关代码如下:
104 //CSerial ser;假设COM1端口上是一个MODEM,通过发送AT命令来和MODEM进行通信
105 //关于AT命令请查询其他资料
106 if(ser.Open(1,9600))
107 {
108 char szCmd[100],szRet[100];
109 strcpy(szCmd,"ATI0\r\n");返回调制解调器默认的速率
110 int iSend = ser.SendData(szCmd,strlen(szCmd));
111 while(ser.ReadDataWaiting() == 0)
112 {//等待数据
113 Sleep(100);
114 }
115 int iRead =ser.ReadData(szRet,99);
116 if(iRead != 0)
117 {
118 szRet[iRead]='\0';
119 printf("send %s read %s\n",szCmd,szRet);
120 }
121 }
122 else
123 {
124 printf("error open COM port\n");
125 }
picked from:http://yadang418.blog.163.com/blog/static/2684365620096103126456/