📄 sy0902.htm
字号:
style='background:#D9D9D9'>Char <span class=GramE>wr[</span>30]; int count2;</span></p>
<p class=MsoNormal style='margin-left:21.0pt'><span class=GramE><span
lang=EN-US style='background:#D9D9D9'>WriteComm(</span></span><span lang=EN-US
style='background:#D9D9D9'>idComDev,wr,count2);</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>通过对以上的描述我们可以看出,</span><span
lang=EN-US>16</span><span style='font-family:宋体'>位以下的串口通信程序最大的特点就在于串口等外部设备的操作有自己特有的</span><span
lang=EN-US>API</span><span style='font-family:宋体'>函数。</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US>Windows
9x/NT/2000</span><span style='font-family:宋体'>中的</span><span lang=EN-US>API</span><span
style='font-family:宋体'>一般都支持</span><span lang=EN-US>32</span><span
style='font-family:宋体'>位的操作,因此又称为</span><span lang=EN-US>Win32API</span><span
style='font-family:宋体'>。为了在上述系统中实现串行数据传送,可以使用</span><span lang=EN-US>Win32</span><span
style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>。</span><span lang=EN-US>Win32</span><span
style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>基本上是一个串行端口</span><span lang=EN-US>API</span><span
style='font-family:宋体'>,不是很适合于局域网(</span><span lang=EN-US>LAN</span><span
style='font-family:宋体'>)通信。虽然在线路上发送数据之前,</span><span lang=EN-US>LAN</span><span
style='font-family:宋体'>通常将数据位串行化,这和窗口或调制解调器发送数据之前所作的工作一模一样,但局域网使用的线路的位数通常比串口少,而且还使用与串口协议很少有类似之处的访问、路由、安全性和纠错协议。局域网通信所需要的协议层使得</span><span
lang=EN-US>Win32</span><span style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>对于这些应用来说很不理想。因此,在网络通信和连接方面,</span><span lang=EN-US>TCP/IP</span><span
style='font-family:宋体'>协议要比</span><span lang=EN-US>Win32</span><span
style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>更适合一些。</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US>Windows</span><span
style='font-family:宋体'>操作系统是一个可抢占式的操作系统,所以</span><span lang=EN-US>Windows</span><span
style='font-family:宋体'>应用程序常常有被别的程序抢占时间片的可能,因此</span><span lang=EN-US>Win32</span><span
style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>也不能用于实时通信。实时通信的质量与时间密切相关。例如,数字化音频数据是实时数据,因为话音的质量依赖于播放它的速率。在录制音频时,它就以某个速度被数字化了,该速度就是人们所熟知的采样速率。声音必须以相同的采样率重放,否则听起来就会太慢或太快。实际中的视频播放,也不是实时播放,那仅仅是存放在缓冲中的那部分数据。因此,不需要许多协议层的交互式、非实时的通信可以采用</span><span
lang=EN-US>Win32</span><span style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>来实现。</span><span lang=EN-US>Win32</span><span
style='font-family:宋体'>通信</span><span lang=EN-US>API</span><span
style='font-family:宋体'>把串口操作(以及并口等)和文件操作统一起来了,使用类似的操作来实现。</span></p>
<p class=MsoNormal><span lang=EN-US> </span></p>
<p class=MsoNormal style='margin-left:.5in;text-indent:-.5in'><b><span
style='font-family:宋体;mso-ascii-font-family:"Times New Roman";mso-hansi-font-family:
"Times New Roman"'>(二)</span></b><b><span lang=EN-US style='font-size:7.0pt'>
</span><span lang=EN-US>Windows</span></b><b><span style='font-family:宋体'>串口通信相关</span><span
lang=EN-US>API</span></b><b><span style='font-family:宋体'>函数</span></b></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>“工欲善其事,必先利其器”,这一节将从使用的角度出发,对和串口通信相关的</span><span
lang=EN-US>32</span><span style='font-family:宋体'>位的</span><span lang=EN-US>Windows
API</span><span style='font-family:宋体'>函数进行介绍,力图使你们对其有个全面、准确的认识。</span></p>
<p class=MsoNormal><span lang=EN-US> </span></p>
<p class=MsoNormal style='margin-left:.25in;text-indent:-.25in'><span
lang=EN-US>2.1</span><span lang=EN-US style='font-size:7.0pt'> <span
class=GramE> </span> </span><span style='font-family:宋体'>打开和关闭串口</span></p>
<p class=MsoNormal style='margin-left:39.0pt;text-indent:-.25in'><span
lang=EN-US>1</span><span style='font-family:宋体;mso-ascii-font-family:"Times New Roman";
mso-hansi-font-family:"Times New Roman"'>.</span><span lang=EN-US
style='font-size:7.0pt'> </span><span style='font-family:宋体'>打开串口</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>在</span><span
lang=EN-US>32</span><span style='font-family:宋体'>位的</span><span lang=EN-US>Windows</span><span
style='font-family:宋体'>系统中,串口和其它通信设备是作为文件处理的。串口的打开、关闭、读取和写入所用的函数与操作文件的函数完全一致。</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>通信会话以调用</span><span
lang=EN-US>CreateFile()</span><span style='font-family:宋体'>开始。</span><span
lang=EN-US>CreateFile()</span><span style='font-family:宋体'>为<span class=GramE>读访问、写访问</span>或读写访问“打开”串口。按照</span><span
lang=EN-US>Windows</span><span style='font-family:宋体'>的通常做法,</span><span
lang=EN-US>CreateFile()</span><span style='font-family:宋体'>返回一个句柄,随后在打开的端口的操作中使用</span><span
lang=EN-US>CreateFile()</span><span style='font-family:宋体'>函数非常复杂,复杂性的原因之一是它是通用的。可以使用</span><span
lang=EN-US>CreateFile</span><span style='font-family:宋体'>打开已存在的文件,创建新文件和打开根本就不是文件的设备,例如串口、<span
class=GramE>并口和</span>调制解调器。</span><span lang=EN-US>CreateFile()</span><span
style='font-family:宋体'>函数声明如下:</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'>HANDLE <span class=GramE>CreateFile(</span></span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> LPCTSTR lpszName,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> DWORD fdwAccess,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> DWORD fdwShareMode,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> LPSECURITY_ATTRIBUTES lpsa,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> DWORD fdwCreate,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> DWORD fdwAttrsAndFlags,</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> HANDLE hTemplateFile</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US
style='background:#D9D9D9'> )</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span lang=EN-US> CreateFile</span><span
style='font-family:宋体'>函数中的参数解释如下:</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>·</span><span
lang=EN-US style='font-size:9.0pt'>lpszName</span><span style='font-size:9.0pt;
font-family:宋体'>:指定要打开的串口逻辑名,用字符串表示,如“</span><span lang=EN-US style='font-size:
9.0pt'>COM1</span><span style='font-size:9.0pt;font-family:宋体'>”和“</span><span
lang=EN-US style='font-size:9.0pt'>COM2</span><span style='font-size:9.0pt;
font-family:宋体'>”分别表示串口</span><span lang=EN-US style='font-size:9.0pt'>1</span><span
style='font-size:9.0pt;font-family:宋体'>和串口</span><span lang=EN-US
style='font-size:9.0pt'>2</span><span style='font-size:9.0pt;font-family:宋体'>。</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>·</span><span
lang=EN-US style='font-size:9.0pt'>fdwAccess</span><span style='font-family:
宋体'>:</span><span style='font-size:9.0pt;font-family:宋体'>用来指定串口访问的类型。与文件一样,串口也是可以被打开以供读取、写入或者两者兼有。</span></p>
<p class=MsoNormal style='text-indent:.25in'><span lang=EN-US style='font-size:
9.0pt'> </span><span lang=EN-US>GENERIC_READ</span><span style='font-family:
宋体'>位读取访问打开端口,</span><span lang=EN-US>GENERIC_READ</span><span
style='font-family:宋体'>位<span class=GramE>写访问</span>打开端口。这两个常数定义如下:</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span class=GramE><span
lang=EN-US style='background:#D9D9D9'>const</span></span><span lang=EN-US
style='background:#D9D9D9'> GENERIC_READ = 0x80000000h;</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span class=GramE><span
lang=EN-US style='background:#D9D9D9'>const</span></span><span lang=EN-US
style='background:#D9D9D9'> GENERIC_WRITE = 0x40000000h;</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span style='font-family:宋体'>用户可以用逻辑操作将这两个标识符连接起来,为读</span><span
lang=EN-US>/</span><span class=GramE><span style='font-family:宋体'>写访问</span></span><span
style='font-family:宋体'>权限打开端口。因为大部分串口通信都是双向的,因此常常在设置中将两个标识符连接起来使用。如:</span></p>
<p class=MsoNormal style='text-indent:21.0pt'><span class=GramE><span
lang=EN-US style='background:#D9D9D9'>fdwAccess</span></span><span lang=EN-US
style='background:#D9D9D9'> = GENERIC_READ | GENERIC_WRITE;</span></p>
<p class=MsoNormal style='margin-left:34.95pt;text-indent:-12.6pt'><span
style='font-family:宋体'>·</span><span lang=EN-US>fdwShareMode</span><span
style='font-family:宋体'>:</span><span style='font-size:9.0pt;font-family:宋体'>指定该端口的共享属性。该参数是为那些由许多应用程序共享的文件提供的。对于不能共享的串口,它必须设置为</span><span
lang=EN-US style='font-size:9.0pt'>0</span><span style='font-size:9.0pt;
font-family:宋体'>。这就是文件与通信设备之间的主要差异之一。如果在当前的应用程序调用</span><span lang=EN-US
style='font-size:9.0pt'>CreateFile()</span><span style='font-size:9.0pt;
font-family:宋体'>时,另一个应用程序已经打开了串口,该函数就会返回错误代码,原因是两个应用程序不能共享一个端口。然而,同一个应用程序的多个线程可以共享由</span><span
lang=EN-US style='font-size:9.0pt'>CreateFile()</span><span style='font-size:
9.0pt;font-family:宋体'>返回的端口句柄,并且根据安全性属性设置,该句柄可以被打开端口的应用程序的子程序所继承。</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
style='font-family:宋体'>·</span><span lang=EN-US>Ipsa</span><span
style='font-family:宋体'>:</span><span style='font-size:9.0pt;font-family:宋体'>引用安全性属性结构(</span><span
lang=EN-US style='font-size:9.0pt'>SECURITY_ARRTIBUTES</span><span
style='font-size:9.0pt;font-family:宋体'>),该结构定义了一些属性,例如通信句柄如何被打开端口的应用程序的子程序所继承。将该参数设置为</span><span
lang=EN-US style='font-size:9.0pt'>NULL</span><span style='font-size:9.0pt;
font-family:宋体'>将为该端口分配缺省的安全性属性。子应用程序所继承的缺省属性是该端口不能被继承的</span><span
style='font-family:宋体'>。</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
style='font-family:宋体'>安全属性结构</span><span lang=EN-US>SECURITY_ARRTIBUTES</span><span
style='font-family:宋体'>结构声明如下:</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
class=GramE><span lang=EN-US style='background:#D9D9D9'>typedef</span></span><span
lang=EN-US style='background:#D9D9D9'> struct_SECURITY_ARRTIBUTE {</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
lang=EN-US style='background:#D9D9D9'> DWORD nLength;</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
lang=EN-US style='background:#D9D9D9'> LPVOID lpSecurityDescriptor;</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
lang=EN-US style='background:#D9D9D9'> BOOL<span class=GramE>
bInheritHandle</span>;</span></p>
<p class=MsoNormal style='margin-left:34.15pt;text-indent:-13.25pt'><span
lang=EN-US style='background:#D9D9D9'>} SECURITY_ARRTIBUTE;</span></p>
<p class=MsoNormal style='text-indent:20.9pt'><span lang=EN-US>SECURITY_ARRTIBUTES</span><span
style='font-family:宋体'>结构成员</span><span lang=EN-US>nLength</span><span
style='font-family:宋体'>指明该结构的长度,</span><span lang=EN-US>lpSecurityDescriptor</span><span
style='font-family:宋体'>指向一个安全描述字符,</span><span lang=EN-US>bInheritHandle</span><span
style='font-family:宋体'>表明句柄是否能被继承。</span></p>
<p class=MsoNormal style='margin-left:31.5pt;text-indent:-10.5pt'><span
style='font-family:宋体'>·</span><span lang=EN-US style='font-size:9.0pt'>fdwCreate</span><span
style='font-size:9.0pt;font-family:宋体'>:指定如果</span><span lang=EN-US
style='font-size:9.0pt'>CreateFile()</span><span style='font-size:9.0pt;
font-family:宋体'>正在被已有的文件调用时应采取的动作。因为串口总是存在,</span><span lang=EN-US
style='font-size:9.0pt'>fdwCreate</span><span style='font-size:9.0pt;
font-family:宋体'>必须设置成</span><span lang=EN-US style='font-size:9.0pt'>OPEN_EXISTING</span><span
style='font-size:9.0pt;font-family:宋体'>。该标志告诉</span><span lang=EN-US
style='font-size:9.0pt'>Windows</span><span style='font-size:9.0pt;font-family:
宋体'>不用企图创建新端口,而是打开已经存在的端口。</span><span lang=EN-US style='font-size:9.0pt'>OPEN_EXISTING</span><span
style='font-size:9.0pt;font-family:宋体'>常数定义为:</span></p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -