📄 teach_sp_55.htm
字号:
<!-- LANGUAGE='JavaScript'>write_body();<-->
<!-- LANGUAGE='JavaScript'>write_bar();<-->
<table width=98% cellspacing="0" cellpadding="0" align=center><!--整体框架-->
<tr><td>
<table border=0 width="100%" cellspacing="0" cellpadding="2"><!--标记放置区域-->
<tr>
<td width="30%" align="center" bgcolor="#8E8E8E" valign=middle><img src=../../img/brand_200_60.gif width=200 height=60 alt="LOGO1"></td>
<td width="70%" align="center" bgcolor="#8E8E8E" valign=middle><!-- LANGUAGE='JavaScript'>write_ban();<--></td>
</tr>
<tr>
<td colspan="2" bgcolor="#939393" align=center><font color=white>您当前位置</font> <a href=../../index.htm><font color=white>首页</font></a> <a href=../index.htm><font color=white>开发教程</font></a> <a href=index.htm><font color=white><font class=engul>Visual C++/MFC</font>专题讲座</font></a> <font color=white>5.5 串口的操作</font> <font color=white><!-- LANGUAGE='JavaScript'>write_command();<--></font></td>
</tr>
</table><!--标记放置区域 END-->
<table border=0 width=100% cellspacing="0" cellpadding="0">
<tr bgcolor="#F4F4F4">
<td><!-- article title begin here-->
<br>
<p align=center><big>5.5 串口的操作</big>
<p>串口是一种时常用来与外界通信的一种设备,虽然现在网络已经很普及,但由于PC机时常需要通过MODEM与远距离主机或是与单片机设备进行通信所以串口的用途还是很广泛。
<p>串口在Win32的开发中可以以文件的形式来进行打开和关闭,并且串口的读写也可以利用ReadFile和WriteFile来进行操作。以前在Windows 3.X下的OpenComm等部分串口操作函数已经被废弃。
<p>串口的开打可以使用下面的方法:
<pre>
HANDLE hDev = CreateFile( "COM1", //指明串口名称,COM1代表第一个串口,COM2代表第二个串口
GENERIC_READ | GENERIC_WRITE, //用于读和写
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //指明为异步操作方式
NULL );
</pre>
串口被打开后,马上要进行的操作就是设置串口的状态和属性,通过指定一个DCB的结构来对串口进行设置,所使用的函数有下面这些
<pre>
BOOL SetCommState(
HANDLE hFile, // handle to communications device
LPDCB lpDCB // device-control block
);
其中DCB结构为
typedef struct _DCB {
DWORD DCBlength; // sizeof(DCB) 结构长度
DWORD BaudRate; // current baud rate 波特率 可取下面的值,表示每秒的速率(bit per second)
/*
CBR_110
CBR_19200
CBR_300
CBR_38400
CBR_600
CBR_56000
CBR_1200
CBR_57600
CBR_2400
CBR_115200
CBR_4800
CBR_128000
CBR_9600
CBR_256000
CBR_14400
*/
DWORD fBinary: 1; // binary mode, no EOF check 二进制方式
DWORD fParity: 1; // enable parity checking 允许奇偶校验
DWORD fOutxCtsFlow:1; // CTS output flow control CTS(clear-to-send)流控
DWORD fOutxDsrFlow:1; // DSR output flow control DSR(data-set-ready)流控
DWORD fDtrControl:2; // DTR flow control type DTR(data-terminal-ready)流制
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 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;
//通过一个字符串来建立DCB结构
//例如字符串:baud=1200 parity=N data=8 stop=1 表明使用1200BPS速率,偶校验,8位数据位,1位停止位
BOOL BuildCommDCB(
LPCTSTR lpDef, // device-control string
LPDCB lpDCB // device-control block
);
//设置端口的缓冲区大小
BOOL SetupComm(
HANDLE hFile, // handle to communications device
DWORD dwInQueue, // size of input buffer 输入缓冲区大小
DWORD dwOutQueue // size of output buffer 输出缓冲区大小
);
</pre>
<p>串口的读写依然可以利用ReadFile和WriteFile函数,这里介绍另一个函数来查询端口状态,
<pre>
BOOL ClearCommError(
HANDLE hFile, // handle to communications device
LPDWORD lpErrors, // error codes
LPCOMSTAT lpStat // communications status
);
//COMSTAT结构如下
typedef struct _COMSTAT {
DWORD fCtsHold : 1;
DWORD fDsrHold : 1;
DWORD fRlsdHold : 1;
DWORD fXoffHold : 1;
DWORD fXoffSent : 1;
DWORD fEof : 1;
DWORD fTxim : 1;
DWORD fReserved : 25;
DWORD cbInQue; // 接收队列内数据量
DWORD cbOutQue; // 发送队列内数据量
} COMSTAT, *LPCOMSTAT;
//从串口内读取数据
{
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );//检查当前是否有数据在接收队列内
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit; //确定当前可能读入的最大数量
bReadStatus = ReadFile( m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus )
{
if( GetLastError() == ERROR_IO_PENDING )
{
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );//等待读操作完成
return( (int) dwBytesRead );
}
return( 0 );
}
}
</pre>
<p>在本节提供一个经过封装的类CSerial来完成串口的操作,这份代码来自于网上,我写了一个简单的DEMO用于向MODEM发送AT命令并读回数据。相关代码如下:
<pre>
CSerial ser;//假设COM1端口上是一个MODEM,通过发送AT命令来和MODEM进行通信
//关于AT命令请查询其他资料
if(ser.Open(1,9600))
{
char szCmd[100],szRet[100];
strcpy(szCmd,"ATI0\r\n");//返回调制解调器默认的速率
int iSend = ser.SendData(szCmd,strlen(szCmd));
while(ser.ReadDataWaiting() == 0)
{//等待数据
Sleep(100);
}
int iRead =ser.ReadData(szRet,99);
if(iRead != 0)
{
szRet[iRead]='\0';
printf("send %s read %s\n",szCmd,szRet);
}
}
else
{
printf("error open COM port\n");
}
</pre>
<p><a href=sam_sp_55.zip>下载本节示范代码</a>
<p align=center><a href=index.htm#charpter5>返回</a></p>
<p align=center><small>版权所有 闻怡洋 <a href=http://www.vchelp.net/><font class=engul>http://www.vchelp.net/<font></font></font></a></small></p>
</small>
</td></tr><!-- article content end-->
</table>
</td>
</tr><!-- article title end-->
</table>
</td></tr></table><!--整体框架 END-->
<!-- LANGUAGE='JavaScript'>write_tail();<-->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -