📄 -
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0061)http://roaringwind.best.163.com/scomm/scluoyunbingshizhan.htm -->
<HTML><HEAD><TITLE>实战串行通讯</TITLE>
<META content="MSHTML 5.00.2920.0" name=GENERATOR>
<META
content=roaringwind,roaringwind.best.163.com,啸峰工作室,龚建伟,串口调试助手,VC/C编程,移动机器人,matlab仿真
name=keywords>
<META content=串口、端口、网络通信技术,VC、C编程技术,轮式移动机器人控制相关技术,Matlab仿真及数据处理
name=DESCRIPTION>
<META content="text/html; charset=gb2312" http-equiv=Content-Type>
<STYLE type=text/css>A:link {
COLOR: #006666; TEXT-DECORATION: none
}
A:visited {
COLOR: #006666; TEXT-DECORATION: none
}
A:active {
COLOR: #33cc00; TEXT-DECORATION: none
}
A:hover {
COLOR: #33cc00; TEXT-DECORATION: underline
}
BODY {
COLOR: #006666; FONT-FAMILY: 宋体; FONT-SIZE: 9pt
}
TABLE {
FONT-FAMILY: 宋体; FONT-SIZE: 9pt
}
.H1 {
FONT-SIZE: 9pt; LINE-HEIGHT: 9pt; align: center
}
TD {
FONT-FAMILY: "宋体", "Arial", "Times New Roman"; FONT-SIZE: 9pt
}
P {
FONT-FAMILY: "宋体", "Arial", "Times New Roman"; FONT-SIZE: 9pt
}
</STYLE>
<SCRIPT language=JavaScript><!--function MM_swapImgRestore() { //v3.0 var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;}function MM_preloadImages() { //v3.0 var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array(); var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++) if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}}function MM_findObj(n, d) { //v3.0 var p,i,x; if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) { d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n]; for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); return x;}function MM_swapImage() { //v3.0 var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3) if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}}//--></SCRIPT>
<META content="Microsoft FrontPage 4.0" name=GENERATOR></HEAD>
<BODY background=实战串行通讯.files/background.gif bgColor=#ffffff leftMargin=0
topMargin=6 marginwidth="0" marginheight="0">
<TABLE align=center bgColor=#33ccff border=0 cellPadding=0 cellSpacing=0
height=70 width=758>
<TBODY>
<TR bgColor=#99cccc vAlign=center>
<TD align=middle height=60 width=151>
<P align=center><A href="http://roaringwind.best.163.com/index.htm"><IMG
border=0 height=60 src="实战串行通讯.files/roaringlogo.jpg"
width=120></A></P></TD>
<TD bgColor=#00ccff height=60 width=475>
<P align=center><IMG border=0 height=60 src="实战串行通讯.files/coldfirexfs.gif"
width=400> </P>
<TD align=middle bgColor=#cbe4e4 height=60 width=132>
<DIV align=center>
<TABLE border=1 borderColorDark=#ffffff borderColorLight=#000000
cellPadding=2 cellSpacing=2 height=60 width=68>
<TBODY>
<TR bgColor=#dfeeee>
<TD bgColor=#33ccff height=53>
<DIV align=center>
<SCRIPT language=javascript> <!--- today = new Date(); var hours = today.getHours(); var minutes = today.getMinutes(); var seconds = today.getSeconds(); function initArray(){ this.length=initArray.arguments.length for(var i=0;i<this.length;i++) this[i+1]=initArray.arguments[i] } var d=new initArray("<font color=red>星期天","星期一","星期二","星期三","星期四","星期五","<font color=GREEN>星期六"); document.write(today.getYear(),"年","<br>",today.getMonth()+1,"月",today.getDate(),"日</FONT>","<br>",d[today.getDay()+1]," "); //--> </SCRIPT>
</DIV></TD></TR></TBODY></TABLE></DIV></TD></TR></TBODY></TABLE>
<TABLE align=center background=实战串行通讯.files/top.gif bgColor=#99cccc border=0
cellPadding=0 cellSpacing=0 height=22 width=758>
<TBODY>
<TR>
<TD height=23 width=25>
<DIV align=center></DIV></TD>
<TD height=23 width=74>
<DIV align=center>
<P align=center><A
href="http://roaringwind.best.163.com/index.htm">首页</A></P></DIV></TD>
<TD height=23 width=18> </TD>
<TD height=23 width=73>
<P align=center><A href="http://roaringwind.best.163.com/article.htm"
target=_blank>发表论文</A></P></TD>
<TD height=23 width=17> </TD>
<TD height=23 width=73>
<DIV align=center><A href="http://roaringwind.best.163.com/myprogram.htm"
target=_blank>自制软件</A></DIV></TD>
<TD height=23 width=17> </TD>
<TD height=23 width=74>
<DIV align=center><A href="http://roaringwind.best.163.com/serialcomm.htm"
target=_blank>串口通讯</A></DIV></TD>
<TD height=23 width=17> </TD>
<TD height=23 width=72>
<DIV align=center><A href="http://roaringwind.best.163.com/vcandindex.htm"
target=_blank>VC/C编程</A></DIV></TD>
<TD height=23 width=17> </TD>
<TD height=23 width=72>
<DIV align=center>网络通讯</DIV></TD>
<TD height=23 width=18> </TD>
<TD height=23 width=74>
<DIV align=center>机器人控制</DIV></TD>
<TD height=23 width=18> </TD>
<TD colSpan=2 height=23>
<DIV align=center><A
href="http://roaringwind.best.163.com/matlabindex.htm"
target=_blank>MATLAB</A></DIV></TD>
<TD height=23 width=29> </TD></TR></TBODY></TABLE>
<TABLE align=center bgColor=#ffffff border=0 cellPadding=0 cellSpacing=0
height=443 width=758>
<TBODY>
<TR>
<TD align=middle background=实战串行通讯.files/bck_broad.gif bgColor=#cbe4e4
rowSpan=2 vAlign=top width=30> </TD>
<TD align=left height=443 rowSpan=2 vAlign=top width=4> </TD>
<TD align=middle rowSpan=2 vAlign=top width=450>
<TABLE border=0 cellPadding=1 cellSpacing=1 height=220 width=550>
<TBODY>
<TR>
<TD width=543>
<P align=center><IMG border=0 height=3
src="实战串行通讯.files/headline1.gif" width=480> </P></TD></TR>
<TR>
<TD width=543>
<P align=center><STRONG><FONT color=#0000ff face=隶书 size=6><IMG
border=0 height=120 src="实战串行通讯.files/splash_lg_clr.gif"
width=100>实战串行通讯</FONT></STRONG><BR>罗云彬,2001.1 </P></TD></TR>
<TR>
<TD width=543>
<P align=center><IMG border=0 height=3
src="实战串行通讯.files/headline1.gif" width=480></P></TD></TR>
<TR>
<TD vAlign=top width=543>
<P>
<HR SIZE=1>
<P>本文不是全面的讲述如何编写串行通讯程序,而是讨论一些实际遇到的问题。</P>
<P><FONT color=#ff0000>1 选择通讯方式 -- 同步还是非同步</FONT></P>
<P>正如在《Serial communications in Microsoft
Win32》等文章中提到的,同步(NonOverLapped)方式是比较简单的一种方式,编写起来代码的长度要明显少于异步(OverLapped)方式,我开始用同步方式编写了整个子程序,在
Windows98 下工作正常,但后来在
Windows2000下测试,发现接收正常,但一发送数据,程序就会停在那里,原因应该在于同步方式下如果有一个通讯 Api
在操作中,另一个会阻塞直到上一个操作完成,所以当读数据的线程停留在 WaitCommEvent 的时候,WriteFile
就停在那里。我又测试了我手上所有有关串行通讯的例子程序,发现所有使用同步方式的程序在 Windows 2000
下全部工作不正常,对这个问题我一直找不到解决的办法,后来在 Iczelion 站点上发现一篇文章提到 NT 下对串行通讯的处理和 9x
有些不同,根本不要指望在 NT 或 Windows 2000
下用同步方式同时收发数据,我只好又用异步方式把整个通讯子程序重新写了一遍。</P>
<P>所以对于这个问题的建议是:如果程序只打算工作在 Win9x 下,为了简单起见,可以用同步方式写程序,如果程序打算在 NT
下也可以工作的话,就必须用异步方式写。</P>
<P><FONT color=#ff0000>2 Win32 通讯 API Bug 之一 ---
CommConfigDialog</FONT></P>
<P>CommConfigDialog 是弹出系统内置串口设置对话框的 API,我们在设备管理器中设置串口参数的对话框就是这个,使用这个
API 时不用先打开端口,它并不针对一个已打开的端口,而是仅仅是把 DCB 的内容填写到对话框中,当按了 OK 后把输入的结果存回到
DCB 数据结构中,至于什么时候把结果设置到串口上,那就是你自己要做的事情了。</P>
<P>CommCinfigDialog 的定义如下:</P>
<P>BOOL CommConfigDialog(</P>
<P>LPTSTR lpszName, // pointer to device name string<BR>HWND hWnd,
// handle to window<BR>LPCOMMCONFIG lpCC // pointer to comm.
configuration structure<BR>);</P>
<P>但在使用中发现,对话框有时能出来,有时出不来,最后总结的经验是问题出在 COMMCONFIG 结构的 dwSize
字段上,COMMCONFIG 的定义如下:</P>
<P>typedef struct _COMM_CONFIG {<BR>DWORD dwSize;<BR>WORD
wVersion;<BR>WORD wReserved;<BR>DCB dcb;<BR>DWORD
dwProviderSubType;<BR>DWORD dwProviderOffset;<BR>DWORD
dwProviderSize;<BR>WCHAR wcProviderData[1];<BR>} COMMCONFIG,
*LPCOMMCONFIG;</P>
<P>在参数中,wVersion 要填 100h,dwProviderSubType 要填 1,但 dwSize 就不能填 sizeof
COMMCONFIG 了,我发现好象一定要把 dwSize 设置为比 sizeof COMMCONFIG
对话框才能出来,所以我用的代码中定义了一个足够大的缓冲区作为结构的地址:</P>
<P>_CommConfigDialog proc<BR>local @stCC[256]:BYTE</P>
<P>pushad<BR>invoke RtlZeroMemory,addr @stCC,sizeof @stCC<BR>mov
(COMMCONFIG ptr @stCC).dwSize,256<BR>mov (COMMCONFIG ptr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -