win32 API串口通讯详解
Win32API 异步串口通讯
![Win32API 异步串口通讯](https://img.taocdn.com/s3/m/207f43fff8c75fbfc77db271.png)
使用Win32API实现Windows下异步串口通讯目录:1.异步非阻塞串口通讯的优点2.异步非阻塞串口通讯的基本原理3.异步非阻塞串口通讯的基础知识4.异步非阻塞串口通讯的实现步骤一,异步非阻塞串口通讯的优点读写串行口时,既可以同步执行,也可以重叠(异步)执行。
在同步执行时,函数直到操作完成后才返回。
这意味着在同步执行时线程会被阻塞,从而导致效率下降。
在重叠执行时,即使操作还未完成,调用的函数也会立即返回。
费时的I/O操作在后台进行,这样线程就可以干别的事情。
例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。
"重叠"一词的含义就在于此。
二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。
三,异步非阻塞串口通讯的基础知识下面来介绍并举例说明一下编写异步非阻塞串口通讯的程序中将会使用到的几个关键函数CreateFile()功能:打开串口设备函数原型HANDLE CreateFile(LPCTSTR lpFileName, // 串口名称字符串;如:"COM1" 或"COM2"DWORD dwDesiredAccess, // 设置读写属性(访问模式);一般为GENERIC_READ|GENERIC_WRITE, DWORD dwShareMode, // 共享模式;"必须"为0, 即不能共享LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性;一般为NULLDWORD dwCreationDistribution, // 创建方式,串口设置必须设置此值;在这里"必须"为OPEN_EXISTING DWORD dwFlagsAndAttributes, // 文件属性和标志;在这里我们设置成FILE_FLAG_OVERLAPPED ,实现异步I/OHANDLE hTemplateFile // 临时文件的句柄,通常为NULL);说明:如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。
WIN32 API串口通信
![WIN32 API串口通信](https://img.taocdn.com/s3/m/eb87e53343323968011c9271.png)
WIN32 API串口通信掌握串行通信API函数的用法是掌握串行通信编程技术的关键。
在Win32中,系统将串行口与文件统一了起来,对它们的打开、读写、关闭等操作都使用相同的API函数,但是它们之间又有差别,这些差别主要体现在API函数中部分参数的设置上。
有关通信的API主要包括打开串口、关闭串口、配置串口、设置缓冲区、设置超时、事件驱动、读串口、写串口等。
串口的打开和关闭1:串口的打开。
由于在Windows环境中,串口作为一种文件来使用,打开串口用打开文件同样的API函数CreateFile()。
函数原型为:HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 其中几个参数的含义分别为:lpFileName指定文件名或设备名,串口通讯时,它必须是“COMx”,其中的“x”为串口编号,如第一个串口则为“COM1”;dwDesiredAccess为串口读写属性;dwShareMode指定该端口的共享属性,串行口不能作为共享设备,故参数值必须为0;lpSecurityAttributes为安全属性,对于串口应该为0 ;dwCreationDisposition指文件的创建模式,对于串口必须为OPEN—EXISTING;dwFlagsAndAttributes描述了创建文件的其它属性,对于串行口,有效的设置只能是FILE-FLAG-OVERLAPPED 或者0,分别表示异步或同步读写;参数hTemplateFile必须为NULL。
返回值:若成功,返回创建的句柄;否则返回INVALID—HANDLE—VALUE。
win32串口通信c语言
![win32串口通信c语言](https://img.taocdn.com/s3/m/4a9255ee370cba1aa8114431b90d6c85ed3a884e.png)
w i n 32串口通信c 语言标标题题::W W i i n n 3322下下使使用用C C 语语言言进进行行串串口口通通信信导导言言::串串口口通通信信在在嵌嵌入入式式系系统统和和物物联联网网应应用用中中扮扮演演着着重重要要角角色色。
本本文文将将介介绍绍如如何何使使用用C C 语语言言在在W W i i n n 3322平平台台下下进进行行串串口口通通信信的的基基本本操操作作和和流流程程,,涵涵盖盖串串口口的的初初始始化化、、数数据据读读写写以以及及错错误误处处理理等等方方面面的的内内容容。
#### 11.. 环环境境准准备备在在进进行行串串口口通通信信前前,,需需要要使使用用相相应应的的开开发发环环境境和和工工具具。
以以下下是是环环境境搭搭建建的的基基本本步步骤骤::-- 安安装装合合适适的的C C 编编译译器器,,如如M M i i n n G G W W 或或者者D D e e v v --C C ++++。
-- 确确保保系系统统中中包包含含``w w i i n n d d o o w w s s ..h h ``头头文文件件,,该该头头文文件件包包含含了了W W i i n n 3322 A A P P I I 的的定定义义。
#### 22.. 串串口口初初始始化化在在进进行行串串口口通通信信前前,,需需要要对对串串口口进进行行初初始始化化设设置置,,包包括括波波特特率率、、数数据据位位、、停停止止位位和和校校验验位位等等参参数数的的配配置置。
下下面面是是一一个个简简单单的的串串口口初初始始化化函函数数示示例例::``````c c##i i n n c c l l u u d d e e <<w w i i n n d d o o w w s s ..h h >>H H A A N N D D L L E E S S e e r r i i a a l l I I n n i i t t ((i i n n t t p p o o r r t t ,, i i n n t t b b a a u u d d r r a a t t e e )){{H H A A N N D D L L E E h h S S e e r r i i a a l l ;;D D C C B B d d c c b b S S e e r r i i a a l l P P a a r r a a m m s s == {{00}};;//// 打打开开串串口口c c h h a a r r p p o o r r t t N N a a m m e e [[1100]];;s s p p r r i i n n t t f f ((p p o o r r t t N N a a m m e e ,, ""C C O O M M %%d d "",, p p o o r r t t ));;h h S S e e r r i i a a l l == C C r r e e a a t t e e F F i i l l e e ((p p o o r r t t N N a a m m e e ,, G G E E N N E E R R I I C C __R R E E A A D D || G G E E N N E E R R I I C C __W W R R I I T T E E ,, 00,, N N U U L L L L ,, O O P P E E N N __E E X X I I S S T T I I N N G G ,,F F I I L L E E __A A T T T T R R I I B B U U T T E E __N N O O R R M M A A L L ,, N N U U L L L L ));;i i f f ((h h S S e e r r i i a a l l ==== I I N N V V A A L L I I D D __H H A A N N D D L L E E __V V A A L L U U E E )) {{p p r r i i n n t t f f ((""无无法法打打开开串串口口!!\\n n ""));;r r e e t t u u r r n n I I N N V V A A L L I I D D __H H A A N N D D L L E E __V V A A L L U U E E ;;}}//// 配配置置串串口口参参数数d d c c b b S Se e r r i i a a l l P P a a r r a a m m s s ..D D C C B B l l e e n n g g t t h h ==s s i i z z e e o o f f ((d d c c b b S S e e r r i i a a l l P P a a r r a a m m s s ));;i i f f ((!!G G e e t t C C o o m m m m S S t t a a t t e e ((h h S S e e r r i i a a l l ,, &&d d c c b b S S e e r r i i a a l l P P a a r r a a m m s s )))) {{p p r r i i n n t t f f ((""无无法法获获取取串串口口参参数数!!\\n n ""));;C C l l o o s s e e H H a a n n d d l l e e ((h h S S e e r r i i a a l l ));;r r e e t t u u r r n n I I N N V V A A L L I I D D __H H A A N N D D L L E E __V V A A L L U U E E ;;}}d d c c b b S Se e r r i i a a l l P P a a r r a a m m s s ..B B a a u u d d R R a a t t e e == b b a a u u d d r r a a t t e e ;;d d c c b b S Se e r r i i a a l l P P a a r r a a m m s s ..B B y y t t e e S S i i z z e e == 88;;d d c c b b S Se e r r i i a a l l P P a a r r a a m m s s ..S S t t o o p p B B i i t t s s == O O N N E E S S T T O O P P B B I I T T ;;d d c c b b S Se e r r i i a a l l P P a a r r a a m m s s ..P P a a r r i i t t y y == N N O O P P A A R R I I T T Y Y ;;i i f f ((!!S S e e t t C C o o m m m m S S t t a a t t e e ((h h S S e e r r i i a a l l ,, &&d d c c b b S S e e r r i i a a l l P P a a r r a a m m s s )))) {{ p p r r i i n n t t f f ((""无无法法设设置置串串口口参参数数!!\\n n ""));;C C l l o o s s e e H H a a n n d d l l e e ((h h S S e e r r i i a a l l ));;r r e e t t u u r r n n I I N N V V A A L L I I D D __H H A A N N D D L L E E __V V A A L L U U E E ;;}}r r e e t t u u r r n n h h S S e e r r i i a a l l ;;}}``````#### 33.. 数数据据读读写写完完成成串串口口的的初初始始化化后后,,可可以以进进行行串串口口数数据据的的读读写写操操作作。
win32API串口通信
![win32API串口通信](https://img.taocdn.com/s3/m/5483d477168884868762d6ac.png)
WIN32API--串口通信[源码]serial.cpp vc++6.0#include<stdio.h>#include<stdlib.h>#include<windows.h>HANDLE hComm;OVERLAPPED m_ov;COMSTAT comstat;DWORD m_dwCommEvents;/*注意:在异步通信时不用等到I/O操作完成后函数才返回异步可以更快的响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程*/bool openport(char *portname)//打开一个串口{//创建串口句柄hComm = CreateFile(portname, //设备名GENERIC_READ | GENERIC_WRITE, //指定可对串口进行读写0,//串口不能共享0,OPEN_EXISTING, //定义文件创建方式FILE_FLAG_OVERLAPPED, //设定为异步通信方式0);//模板文件句柄 0:串口无模板if (hComm == INVALID_HANDLE_VALUE)return FALSE; //串口打开不成功INVALID_HANDLE_value(0XFFFFFFFF)。
elsereturn true; //串口打开成功}/*设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。
这需要通过一个DCB结构来进行。
DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。
在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。
第一次打开串口时,串口设置为系统默认值,函数GetCommState和SetCommState可用于检索和设定端口设置的DCB(设备控制块)结构。
该结构中BaudRate、ByteSize、StopBits和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。
用Win32 API 实现串行通信
![用Win32 API 实现串行通信](https://img.taocdn.com/s3/m/2cf5ec89cc22bcd126ff0c20.png)
用Win32 API 实现串行通信南京航空航天大学牛新庄--------------------------------------------------------------------------------串口是常用的计算机与外部串行设备之间的数据传输通道,由于串行通信方便易行,所以应用广泛。
我们可以利用Windows API 提供的通信函数编写出高可移植性的串行通信程序。
在Win16中,可以利用OpenComm、CloseComm和WriteComm等函数打开、关闭和读写串口。
但在Win32中,串口和其他通信设备均被作为文件处理,串口的打开、关闭和读写等操作所用的API函数与操作文件的函数相同。
可通过CreateFile函数打开串口,通过CloseFile函数关闭串口,通过CommProp、DCB结构、GetCommProperties、SetCommProperties、GetCommState及SetCommState等函数设置串口状态,通过函数ReadFile和WritFile读写串口。
VC++ 6.0是Windows应用程序开发的主流语言之一,它具有良好的图形设计界面并支持面向对象的程序设计方法。
本文结合一个实例介绍在VC++ 6.0下如何利用Win32 API 实现串行通信程序。
实现原理本文的实例来自一个水泥发货系统,在系统中,需要将通过总量传感器采集到的仓重值传入到计算机中,以便系统做出相应的处理。
这需要使用串行通信来完成采集数据的传递工作。
对于串行通信设备,Win32 API支持同步和异步两种I/O操作。
同步操作方式的程序设计相对比较简单,但I/O操作函数在I/O操作结束前不能返回,这将挂起调用线程,直到I/O操作结束。
异步操作方式相对要复杂一些,但它可让耗时的I/O操作在后台进行,不会挂起调用线程,这在大数据量通信的情况下对改善调用线程的响应速度是相当有效的。
异步操作方式特别适合同时对多个串行设备进行I/O操作和同时对一个串行设备进行读/写操作。
WindowsAPI在串口通信中的应用
![WindowsAPI在串口通信中的应用](https://img.taocdn.com/s3/m/2bdb08f9a98271fe900ef966.png)
1 引言在很多情况下,远程监控和工业自动化领域系统经常采用串并口通信编程,其中串行接口被广泛地应用于工程实践的长距离通信中。
运用Windows通信API可以在Windows 环境下进行串口编程,不用对硬件直接进行操作,并通过VC、VB和Delphi等语言进行调用,大大方便了对数据的处理。
本文对和串口通信相关的32位Windows API函数进行了介绍,并给出了相应的程序实例。
2 Windows API简介Win32 API作为Microsoft 32位平台(包括:Windows 9x,Windows NT3.1/4.0/5.0,WindowsCE)的应用程序编程接口,它是构筑所有32位Windows平台的基石,所有在Windows平台上运行的应用程序都可以调用这些函数。
API是windows的核心,从事Windows应用程序开发,离不开对Win32 API函数的调用。
只有充分理解和利用API 函数,才能深入到Windows的部,充分挖掘系统提供的强大功能和灵活性。
3 Windows API相关串口通信函数介绍在32位的Windows系统中,串口通信是作为文件处理的,串口操作一般为的打开、关闭、读取、写入等操作,相应的Windows API 函数如下:3.1 打开和关闭串口1 打开串口在Windows系统中串口通信会话以调用CreateFile ( )函数开始。
CreateFile ( )函数可以读写访问串口,并返回一个句柄,并在以后的端口操作中使用。
现其他初始化工作。
2 关闭串口关闭串口通过调用CloseHandle ( )函数关闭由CreatHandle ( )函数返回的句柄来完成。
3.2 串口配置和串口属性在用CreatFile ( )函数打开串口后,系统将根据上次打开串口时设置的值来初始化串口,可以集成上次打开操作后的数值,包括设备控制块(DCB)和超时控制结构(COMMTIMEOUTS)。
串口编程之一:WIN32API中串口DCB结构的介绍-随想随写-电子工程专...
![串口编程之一:WIN32API中串口DCB结构的介绍-随想随写-电子工程专...](https://img.taocdn.com/s3/m/4dbc9c07abea998fcc22bcd126fff705cc175cd4.png)
串口编程之一:WIN32API中串口DCB结构的介绍-随想随写-电子工程专...串口编程之一: WIN32 API 中串口DCB 结构的介绍在应用WIN32 API 对串口进行编程时, 必定会使用到DCB 结构. 下面的DCB 结构的一些介绍.首先是DCB 结构.typedef struct _DCB {DWORD DCBlength;DWORD BaudRate;DWORD fBinary: 1;DWORD fParity: 1;DWORD fOutxCtsFlow:1;DWORD fOutxDsrFlow:1;DWORD fDtrControl:2;DWORD fDsrSensitivity:1;DWORD fTXContinueOnXoff:1;DWORD fOutX: 1;DWORD fInX: 1;DWORD fErrorChar: 1;DWORD fNull: 1;DWORD fRtsControl:2;DWORD fAbortOnError:1;DWORD fDummy2:17;WORD wReserved;WORD XonLim;WORD XoffLim;BYTE ByteSize;BYTE Parity;BYTE StopBits;char XonChar;char XoffChar;char ErrorChar;char EofChar;char EvtChar;WORD wReserved1;} DCB;在这个结构中, 共有28个变量, 我把这些成员归类为几种.1. 串口的基本设置1) DWORD BaudRate; 波特率设置。
2) BYTE ByteSize; 数据位设置。
3) DWORD fParity: 1; TRUE时,支持奇偶检验。
4) BYTE Parity; 奇偶检验位的设置5) BYTE StopBits; 停止位的设置2. 流控制(Flow Control) 的设置流控制分为硬件流控制和软件流控制。
WIN32
![WIN32](https://img.taocdn.com/s3/m/d709623e52ea551810a68742.png)
typedef struct _DCB{ ……… //波特率,指定通信设备的传输速率。这个成员可以是实际波特 率值或者下面的常量值之一: DWORD BaudRate; 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; // 指定奇偶校验使能。若此成员为1,允许奇偶校 验检查 … BYTE ByteSize; // 通信字节位数,4—8 BYTE Parity; //指定奇偶校验方法。此成员可以有下列值: EVENPARITY 偶校验 NOPARITY 无校验 MARKPARITY 标记校验 ODDPARITY 奇校验 BYTE StopBits; //指定停止位的位数。此成员可以有下列值: ONESTOPBIT 1位停止位 TWOSTOPBITS 2位停止位 ONE5STOPBITS 1.5位停止位 ……… } DCB; winbase.h文件中定义了以上用到的常量。如下: #define NOPARITY 0 #define ODDPARITY 1 #define EVENPARITY 2 #define ONESTOPBIT 0 #define ONE5STOPBITS 1 #define TWOSTOPBITS 2 #define CBR_110 110 #define CBR_300 300 #define CBR_600 600 #define CBR_1200 1200 #define CBR_2400 2400 #define CBR_4800 4800 #define CBR_9600 9600 #define CBR_14400 14400 #define CBR_19200 19200 #define CBR_38400 38400 #define CBR_56000 56000 #define CBR_57600 57600 #define CBR_115200 115200
win32下的几种串口通信编程
![win32下的几种串口通信编程](https://img.taocdn.com/s3/m/72302c0716fc700abb68fc15.png)
类别:技术文章来源:未知作者:冯传玉关键字:串口加入日期:2003-10-29今天阅读:1总共阅读:8918win32下的几种串口通信编程安徽合肥冯传玉---- 要完成串口通信, 在32位模式下, 一般说来有以下四种方法:---- 1. 以文件方式打开串口:---- 这里使用的是Win32 API 函数, 所以无论在BCB或VC下都可以实现. 具体的函数的意义可以参考Win32 API的帮助.这里有一个易于使用的BCB下的类, 可以方便的使用串口.---- 下面给出简要说明:---- (1) 应用CreateFile() 来初始化串口FhFileComm=CreateFile( FCommName.c_str(),GENERIC_READ | GENERIC_WRITE,0, // exclusive access&lpSecurity,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, // overlapped I/ONULL );if( FhFileComm == INVALID_HANDLE_VALUE)return false;(2) 应用WriteFile() 和ReadFile() 从串口读写数据bool MyComm::WriteBuffer(unsigned char*buffer,unsigned long length){return WriteFile(FhFileComm,buffer,length,&length,&FgOverLapped);}bool MyComm::ReadBuffer(unsigned char*buffer,unsigned long length){return ReadFile(FhFileComm,buffer,length,&length,&FgOverLapped);}相应的源文件为UsageComm.cpp UsageComm.h---- 2. 使用现成的控件:---- 易于使用的是微软的MS Communication 控件, 它是做为一个.ocx 提供的.---- 在BCB 中可以用Import ActiveX Control 将它加入到BCB 中, 缺省是加载在ActiveX 页中. 就可以作为一个普通的BCB 控件来使用了.(也有不少第三方提供的其它硬件操作控件)---- 3. 直接嵌入汇编法:---- (该方法不能在NT下使用, 由于98的非完全保护,下面的代码可以使用)利用BCB的直接嵌入汇编功能, 可以在BCB中直接对串口操作.---- 如下所示,在BCB中使用汇编代码如下byte __fastcall ReadByte(WORD Address)// eax :address{asm{mov DX,AXin AL,DX}}void __fastcall WriteByte(unsigned char byte, WORD Address)// EAX: BYTE EDX: ADDRESS{asm{out DX,AL}---- 这里必须用__fastcall 调用约定以使在调用该函数时用寄存器传递参数.---- (用在BCB中的汇编指令代码in 和out必须用小写,(其余可以为大写)寄存器名称大小写都可以) ---- 其它的如写多个字节,读多个字节, 同样可以实现.---- 4. 最困难的要数用VxD来实现:---- 这不是一下子能说得清的, 如果要做, 当然要找本书了.。
【免费下载】WIN32 API串口通信编程实例教程
![【免费下载】WIN32 API串口通信编程实例教程](https://img.taocdn.com/s3/m/60f351dae009581b6bd9ebe0.png)
WIN32 API串口通讯实例教程第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。
常用函数及作用下:函数名作用CreateFile 打开串口GetCommState 检测串口设置SetCommState 设置串口BuilderCommDCB 用字符串中的值来填充设备控制块GetCommTimeouts 检测通信超时设置SetCommTimeouts 设置通信超时参数SetCommMask 设定被监控事件WaitCommEvent 等待被监控事件发生WaitForMultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeComm 清空串口缓冲区,退出所有相关操作ClearCommError 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API 编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高。
API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile。
下面依次讲述各个步骤的过程。
第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数。
Windows 32 API在串口通信中的应用
![Windows 32 API在串口通信中的应用](https://img.taocdn.com/s3/m/ffdaa1df360cba1aa811dab3.png)
( 坊 学 院 , 山东 潍
潍坊
2 16 ) 6 0 1
摘
要 :本 文分析 了Wi o s n w 环境 下 串行通信 的编程技 术 ,并介绍 了在用v + d c +语 言编 写
P C机与单片机 串行通信程序 实现 ,提 出了在实际应用中提 高串行通信性能的方法。 关键词:V + ;Wi 2 P 函数;串行通信;单 片机 c+ n AI 3
维普资讯
第6 卷第4 期
20 0 6年 7月
潍坊学院学报
J u a f W e fn ie s o m l i a Un v ri o a
VO . No4 1 . 6
J1 0 6 u. 0 2
Widw 2 P 在 串E通信 中的应用 no S I 3A l
Mioo c s ̄公 一 的 V + 6 r J C + . 一 种 高级 编 程 语 数据景 的实时通信,大大提高 了通信 的效率,故 0是 言 ,其 基 础类 库 ( C 封 装 了Wi3AP 中 的标 奉程 序 采 用 此种 方 式 进 行 串 行通 信 ,至 于 通 信 的 MF ) n2 l 准通 信 函数 ,可 方 便 地 支 持 串 口通信 。 下面 就 结 可 靠性 可 以通过 软件 设 汁来 保证 。 合 实例 介 绍 在 Wi o 环 境 下 , 用VC + . : 3 串行通信程序 n ws d + 60编 与 . 串行通信 程序 的技 术及 方法 。
序处 理 。
数 、 消息 的集 合 ,它 可 以看 作 是 Wi o s系统 为 n w d 在其 下运 行 的各 种 丌 发 系 统 提供 的 丌放 式 通用 功
在Widws中 , 串行 通 信 有 两 种 T 作 方 式 : no
基于Win32 API的通用串口通信组件的开发
![基于Win32 API的通用串口通信组件的开发](https://img.taocdn.com/s3/m/2d82cc25915f804d2b16c14b.png)
协 同 工作 方 式 , 实现 了可 用 于 各种 W i n d o ws平 台 下 串 口通 信 编程 的 通 用 组件 , 并 提 供 了手 动 模 式及 消 息模 式 两 种 接 口方 式 。 分 析 了 目前 串 口通 信 组 件 的 不足 和 工 业领 域 串 口通 信 组 件 的 需 求 ; 在 归 纳 了 Wi n 3 2 串口相 关 A P I 的 基 础 上提 出 了组 件设计框架 , 对 组 件 实现 过 程 中的 缓 冲 区设 计 、 线程 同 步 、 信 号 系统 、 回 调 函 数接 口、 读 写 线 程 流程 等进 行 了详 细 介 绍 。 文 末 给 出 了 串 口通 信 组 件 的 两 个 应 用 实例 , 其 运 行 效 果 证 明 了 串 口通信 组 件 的设 计 合 理 、 有效 。
c at i o n a r e an al y z e d f i r s t l y . T o c on s t r u c t t h e f r a mewor k o f c om p on en t , an i n du ct i on o f Wi n 3 2 pl a t f or m API i s p r e s en t ed.
关键 词 : 串 口通 信 组 件 , Wi n 3 2 A P I , 多线 程 , O V E R L A P P E D方 式
Abs t r a c t
A de s i gn o f ge ne r i c se r i al c omm un i ca t i on c o m po ne n t whi ch ca n be u s ed on wi n do ws s er i al c omm u ni ca t i o n pr o gr am— mi ng i s i n t r o du ce d. B y W i n 3 2 API a nd OVERLAP PED m a ni pul a t i ng mod e. t h e co mp on en t i s i m pl e m en t ed u s i n g m u l t i —t hr e ad— i n g an d m u l t i —bu f er t e ch n i qu e, a nd t h e co m po n en t of f er s t wo me t h o ds t o u s e whi ch ar e ma nu al m o de an d m e s s a ge mod e. Th e i ns i gn c an ce s o f c ur r en t s e r i a l c omm u ni ca t i o n c ompo ne n t a r e l i s t e d an d t h e r equ i r emen t s o f i n du s t r i a l s e r i al cO mmu n 卜
应用Win32 API函数开发串口通讯程序
![应用Win32 API函数开发串口通讯程序](https://img.taocdn.com/s3/m/e7ecdc4d69eae009581becee.png)
中 , 照预 定 好 的通 信 握 手 方 式 , 确 检 测 串 口状 按 正
态 , 取发 送 串 口数据 。 读
2 串 1通 讯 AP : 2 I函 数 及 编 程 机 制
2 1 串行 端 口 的 打 开 和 关 闭 .
I 0; If n t n / AP u ci o
在 Wi3 n 2中所有 的设 备都 被 看 成是 文 件 , 串行 端 口也是作 为文 件来进 行处 理 的。 串行端 口的打开
lp e ) a p d 和异 步方式 ( elp e ) Ov r p d 。下 面是 以 O e— a vr lp e a p d方式 打开 串 口的程序 片断 。
HADLE Co h mm :
无线通 讯适 配器 传送 到计算 机里 。从 而需要 控 制该
适 配器 的 收发状 态 以完成数 据 的发送 和接 收 。收发 状态 的切换 要 通过 串行 电 缆 中 R TS控 制线 的 电平 高低来 控 制 。因 此选 用 Wi3 I函 数 开 发 通 讯 n 2AP
Ab ta t Ex ou e t me h d sr c : p nd d he t o us d o de e t —
v l p s ra o eo e il c mm u ia i n wih W i 3 I f n - n c to t n 2 AP u c
置 串 口接收 发送 数据 的缓 冲 区 大小 , 口的设 置 就 串 基本 完成 , 之后就 可 以启 动 读写线 程 了。
一
关键 词 : 口通 讯 ; 步 I0; P 函数 串 异 / A I
中图分 类号 : 3 1 1 TP 1 . l
文献 标识 码 : A
01 Win32 API串口通信编程
![01 Win32 API串口通信编程](https://img.taocdn.com/s3/m/5b0745e1998fcc22bcd10d35.png)
1、串口通信编程步骤a)打开串口b)配置串口c)读写串口d)关闭串口2、代码实例及解析a)打开串口Windows系统中对于文件的操作进行了扩充,无论是文件、通信设备、命名管道、磁盘和控制台,都是使用CreateFile函数打开或者创建。
打开串口的方式有两种——同步I/O方式打开、重叠I/O方式打开。
同步I/O方式,发出I/O操作请求的API函数将一直被阻塞,直到I/O操作完成后,才能继续向下执行,在采用多线程进行编程时,要注意避免线程被阻塞。
重叠I/O 方式,发出I/O操作请求,的API可以立即返回,系统在后台运行I/O操作,这样可以避免API函数被阻塞。
同步I/O方式打开HANDLE hCom;hCom = CreateFile(“COM1”, //串口名称GENERIC_READ | GENERIC_WRITE, //允许读写0, //独占方式NULL,OPEN_EXISTING, //打开而不是创建0, //同步方式NULL);if( hCom == (HANDLE)-1){MessageBox(“打开COM失败!”);return FALSE;}MessageBox(“打开COM成功!”);return TRUE;重叠I/O方式打开HANDLE hCom;hCom = CreateFile(“COM1”, //串口名称GENERIC_READ | GENERIC_WRITE, //允许读写0, //独占方式NULL,OPEN_EXISTING, //打开而不是创建FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //重叠I/O方式打开NULL);if( hCom == INVALID_HANDLE_VALUE){MessageBox(“打开COM失败!”);return FALSE;}MessageBox(“打开COM成功!”);return TRUE;b)配置串口串口打开后,还要进行相应的配置,这里主要讨论:DCB配置、I/O缓冲区设置、超时设置。
应用Win32 API函数开发串口通讯程序
![应用Win32 API函数开发串口通讯程序](https://img.taocdn.com/s3/m/569f5f19eef9aef8941ea76e58fafab069dc4496.png)
应用Win32 API函数开发串口通讯程序
李青
【期刊名称】《机械与电子》
【年(卷),期】2007(000)010
【摘要】阐述了使用Win32 API函数开发串口通讯程序的方法.详细介绍了使用的主要函数和编程机制.
【总页数】3页(P56-58)
【作者】李青
【作者单位】贵州省移动通信有限责任公司贵阳分公司运行维护部,贵州,贵阳,550002
【正文语种】中文
【中图分类】TP311.11
【相关文献】
1.基于Windows API函数的串口通讯程序设计 [J], 龙灏;丁旭玲
2.在VC++下用Win32 API函数编写多线程串口通信程序 [J], 金剑
3.在VC++下用Win32 API函数编写多线程串口通信程序 [J], 金剑
4.一种利用Win32 API函数实现串口实时通迅的方法 [J], 罗云虎
5.Win32API函数在VFP程序设计中的应用 [J], 王雪松
因版权原因,仅展示原文概要,查看原文内容请购买。
WindowsAPI编程控制串口
![WindowsAPI编程控制串口](https://img.taocdn.com/s3/m/7fad2a9e69dc5022aaea0080.png)
Windows API编程控制串口WIN32通信API基本上是一个串行端口API,不是很适合于局域网(LAN)通信。
在网络通信和连接方面,TCP/IP协议要比WIN32通信API更适合一些。
WIN32通信API也不能用于实时通信。
不需要许多协议层的交互式,非实时的通信可以采用WIN32通信API来实现,WIN32通信API把串口操作(以及并口等)和文件操作统一起来了。
Windows串口通信相关API函数打开和关闭串口一.打开串口在32位的Windows系统中,串口和其他通信设备是作为文件处理的。
串口的打开,关闭,读取和写入所用的函数与操作文件的函数完全一致。
通信会话以调用CreateFile()开始。
CreateFile()为读访问,写访问或读写访问“打开”串口。
按照Windows的通常做法,CreateFile()返回一个句柄,随后在打开的端口的操作中使用。
CreateFile()函数非常的复杂,复杂性的原因之一是它是通用的。
可以使用CreateFile 打开已存在的文件,创建新文件或打开根本就不是文件的设备,例如串口,并口和调制解调器。
CreateFile()函数声明如下:HANDLE CreateFile(LPCTSTR lpFileName, // pointer to name of the fileDWORD dwDesiredAccess, // access (read-write) modeDWORD dwShareMode, // share modeLPSECURITY_ATTRIBUTES lpSecurityAttributes, // pointer to security attributesDWORD dwCreationDisposition, // how to createDWORD dwFlagsAndAttributes, // file attributesHANDLE hTemplateFile // handle to file with attributes to copy);CreateFile的参数解释:lpFileName:指定要打开的串口逻辑名,用字符串表示,如“COM1”和“COM2”分别表示串口1/2dwDesiredAccess用来指定串口访问的类型。
WindowsAPI在串口通信中的应用
![WindowsAPI在串口通信中的应用](https://img.taocdn.com/s3/m/d97b9d3d700abb68a882fb3e.png)
WindowsAPI在串口通信中的应用在专门多情形下,远程监控和工业自动化领域系统经常采纳串并口通信编程,苴中串行接口被广泛地应用于工程实践的长距离通信中。
运用Windows通信API能够在Windows环境下进行串口编程,不用对硬件直截了当进行操作,并通过VC、VB和Delphi等语言进行调用,大大方便了对数据的处理。
本文对和串口通信相关的32位Windows API函数进行了介绍,并给岀了相应的程序实例。
2Windows API 简介Win32 API 作为 Microsoft 32 位平台(包括:Windows 9x, Windows NT3.1 / 4.0/5.0, WindowsCE)的应用程序编程接口,它是构筑所有32位Windows平台的基石,所有在 Windows平台上运行的应用程序都能够调用这些函数。
API是windows的核心,从事Windows 应用程序开发,离不开对Win32 API函数的调用。
只有充分明白得和利用API函数,才能深入到Windows 的内部,充分挖掘系统提供的强大功能和灵活性。
3Windows API相关串口通信函数介绍在32位的Windows系统中,串口通信是作为文件处理的,串口操作一样为的打开、关闭、读取、写入等操作,相应的Windows API函数如下:3.1打开和关闭串口1打开串口在Windows系统中串口通信会话以调用CreateFile ()函数开始。
CreateFile ()函数能够读写访咨询串口,并返回一个句柄,并在以后的端口操作中使用。
丄・CreateFile ()函数声明如下:2・HANDLE CreateFile(3・LPCTSTR IpszNAME, //抬定耍打开的串口逻输名4・DWORD fdwAccess, //抬定串口访咨询的类空5・DWORD fdwShareMode, //扌H左端I丨的共';•闭牛•6・LPSECURITY_ATTRIBUTES Ipsa, // 弓|用安全属性结构SECUR:ETY_ATTRHBUTES7・DWORD fdwCreate, //抬定CreateFile {)正在被已有的文件调用时应采取的描施8・DWORD fdwAttrsAndFlags, //描述端口的各种屈件9・HANDLE hTemolate描向模板文件的句柄10・)11.其中安全屈性结构SECURITY_ATTRIBUTES结构声明如下:12 . typedef struct_SECURITY_ATTRIBUTES{丄3・DWORD nLength; //抬明该结构的长度14 . LPVOID IpSecurityDescriptor; // 扌H向一个安全描述字符1.5・BOOL blnheritHandle; //讲明句柄是否能被继承丄6・}SECURITY_ATTRIBUTES;17・调用CreateFile ()函数打开COM1串口操作如下所示:丄8・HANDLE hCOM;丄9・DWORD DWeRROR;对串口 1 进行操作20. hCom=Creatfile (''COM1,,Z//2丄・GENERIC READ I GENERIC WRITE, //承诺读和写22. 0, //独占方式23・ NULL,24・ OPEN_EXTSTTNG,25. I , //重叠方式26 ・ NULL27.);28 ・ if (hCOM==TNVAL :I :D_HANDLE_VALUE)29. {30 ・ dwError=GetLastError ( ); //处理错误31・}一旦串口处于打开状态.就能够分配一个发送缓冲区和接收缓冲区•同时通过调用SetupComm()函数 实现其他初始化工作。
01 Win32 API串口通信相关函数详解
![01 Win32 API串口通信相关函数详解](https://img.taocdn.com/s3/m/b3f4c9f4f705cc1755270935.png)
相关函数详解(仅牵扯到串口通信方面的)CreateFile函数——打开或创建串口HANDLE CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCrationDistribution,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile);函数调用成功,返回串口的句柄;否则返回INVALID_HADLE_VALUE。
SetupComm函数——设置串口缓冲区大小BOOL SetupComm(HANDLE hFile,DWROD dwInQueue, //输入缓冲区大小DWROD dwOutQueue //输出缓冲区大小);设置成功后返回非0值;如果失败返回0值。
串口打开后,如果不设置缓冲区大小,系统则采用默认的大小。
设置时应当避免缓冲区溢出。
GetCommState函数、SetCommState函数Get……获得当前串口配置信息、SetCommState设置指定串口配置信息。
BOOL GetCommState(HANDLE hFile, LPDCB lpDCB);BOOL SetCommState(HANDLE hFile, LPDCB lpDCB);GetCommTimeouts函数、SetCommTimeouts函数BOOL GetCommTimeouts(HANDL hFile, LPCOMMTIMEOUTS lpCommTimeouts);得到超时信息BOOL SetCommTimeouts(HANDL hFile, LPCOMMTIMEOUTS lpCommTimeouts);设置超时信息填充串口配置信息的方法也可用其他的方法替代,不同的函数有不同的参数规定,比如:BuildDCB填充DCB结构、BuildCommDCBAndTimeouts填充DCB和COMMTIMEOUTS,具体用法参见MSDN。
API串口通信实例[详细]
![API串口通信实例[详细]](https://img.taocdn.com/s3/m/c412a2af6bd97f192279e9d5.png)
第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下:函数名作用CreateFile 打开串口GetCo米米State 检测串口设置SetCo米米State 设置串口BuilderCo米米DCB 用字符串中的值来填充设备控制块GetCo米米Ti米eouts 检测通信超时设置SetCo米米Ti米eouts 设置通信超时参数SetCo米米米ask 设定被监控事件WaitCo米米Event 等待被监控事件发生WaitFor米ultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeCo米米清空串口缓冲区,退出所有相关操作ClearCo米米Error 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高.API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile.下面依次讲述各个步骤的过程.第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数.CreateFile 函数原型如下:HANDLE CreateFile(LPCTSTR lpFileNa米e,DWORD dwDesiredAccess,DWORD dwShare米ode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTe米plateFile );lpFileNa米e:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字.当用CreateFile打开串口时,这个参数可用“CO米1”指定串口1,用“CO米2”指定串口2,依此类推.dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值.用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;dwShare米ode:指定此文件可以怎样被共享.因为串行口不支持任何共享模式,所以dwShare米ode必须设为0;lpSecurityAttributes定义安全属性,一般不用,可设为NULL.Win 9x下该参数被忽略; dwCreationDistribution定义文件创建方式, 对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;hTe米plateFile指向一个模板文件的句柄,串口无模板可言,设为NULL.在Windows 9x下该参数必须为NULL.串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF).上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的.异步,就是说,在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程.对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择.实例1:/****************** exa米ple1.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/实例2:/****************** exa米ple2.cpp ******************************************/ /* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/第三节设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作.这需要通过一个DCB结构来进行.DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息.在查询或配置串口的属性时,都要用DCB结构来作为缓冲区.第一次打开串口时,串口设置为系统默认值,函数GetCo米米State和SetCo米米State可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity 字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息.程序中用DCB进行串口设置时,应先调用API函数GetCo米米State,来获得串口的设置信息: GetCo米米State()用途:取得串口当前状态原型:BOOL GetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.此结构中含有和设备相关的参数.此处是与串口相关的参数.由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入.然后在需要设置的地方对dcb进行设置.串口有很多的属性,上面也已经介绍了一些最重要的参数.这里介绍数据结构DCB:typedef struct _DCB { // dcbDWORD DCBlength; //DCB结构体大小DWORD BaudRate; //波特率DWORD fBinary: 1; //是否是二进制,一般设置为TRUEDWORD fParity: 1;//是否进行奇偶校验DWORD fOutxCtsFlow:1; //CTS线上的硬件握手DWORD fOutxDsrFlow:1; //DSR线上的硬件握手DWORD fDtrControl:2; //DTR控制DWORD fDsrSensitivity:1;DWORD fTXContinueOnXoff:1;DWORD fOutX: 1; //是否使用XON/XOFF协议DWORD fInX: 1; //是否使用XON/XOFF协议DWORD fErrorChar: 1; //发送错误协议DWORD fNull: 1;DWORD fRtsControl:2;DWORD fAbortOnError:1;DWORD fDu米米y2:17;WORD wReserved;WORD XonLi米; //设置在XON字符发送之前inbuf中允许的最少字节数WORD XoffLi米; //在发送XOFF字符之前outbuf中允许的最多字节数BYTE ByteSize; //数据宽度,一般为8,有时候为7BYTE Parity; //奇偶校验BYTE StopBits; //停止位数char XonChar; //设置表示XON字符的字符,一般是采用0x11这个数值char XoffChar; //设置表示XOFF字符的字符,一般是采用0x13这个数值char ErrorChar;char EofChar;char EvtChar;WORD wReserved1;} DCB;我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数: DWORD BaudRate:串口波特率DWORD fParity:为1的话激活奇偶校验检查DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位然后再末尾调用SetCo米米State就可以了,还是比较方便的.这样可不必构造一个完整的DCB 结构.SetCo米米State()用途:设置串口状态,包括常用的更改串口号、波特率、奇偶校验方式、数据位数等原型:BOOL SetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.要更改的串口参数包含在此结构中.然后调用SetCo米米米ask,用来指定程序接收特定的串口事件,调用SetupCo米米函数,设置串口缓冲区大小:SetCo米米米ask()说明:用途:设置串口通信事件.原型:BOOL SetCo米米米ask(HANDLE hFile,DWORD dwEvt米ask);参数说明:-hFile:串口句柄-dwEvt米ask:准备监视的串口事件掩码该参数有如下信息掩码位值:EV_BREAK:收到BREAK信号EV_CTS:CTS(clear to send)线路发生变化EV_DSR:DST(Data Set Ready)线路发生变化EV_ERR:线路状态错误,包括了CE_FRA米E\CE_OVERRUN\CE_RXPARITY 3钟错误.EV_RING:检测到振铃信号.EV_RLSD:CD(Carrier Detect)线路信号发生变化.EV_RXCHAR:输入缓冲区中已收到数据.EV_RXFLAG:使用SetCo米米State()函数设置的DCB结构中的等待字符已被传入输入缓冲区中.EV_TXE米PTY:输出缓冲区中的数据已被完全送出.还有,串口因为是I/O操作,可能会产生错误,这时候需要用SetCo米米Ti米eouts()设置超时限制,以避免阻塞现象.设置超时设置需要一个结构体CO米米TI米EOUTS.SetCo米米Ti米eouts()BOOL SetCo米米Ti米eouts( hCo米米Dev, lpct米o );Lpct米o指向包含新的超时参数的CO米米TI米EOUTS结构.CO米米TI米EOUTS结构定义如下:typedef struct _ CO米米TI米EOUTS{DWORD ReadIntervalTi米eout;DWORD ReadTotalTi米eout米ultiplier;DWORD ReadTotalTi米eoutconstant;DWORD WriteTotalTi米eout米ultiplier;DWORD WriteTotalTi米eoutconstant;}CO米米TI米EOUTS, LPCO米米TI米EOUTS;ReadIntervalTi米eout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间.在ReadFile操作其间,收到第一个字符时开始计算时间.若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据.0值表示不用间隔限时.若该成员为米AXDWORD,且ReadTotalTi米eoutconstant和ReadTotalTi米eout米ultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回.ReadTotalTi米eout米ultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间.每个读操作的总限时时间等于读操作所需的字节数与该值的乘积.ReadTotalTi米eoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间.每个操作的总限时时间等于ReadTotalTi米eout米ultiplier成员乘以读操作所需字节数再加上该值的和.ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant成员的值为0表示读操作不使用限时时间.WriteTotalTi米eout米ultiplier和WriteTotalTi米eoutconstant的意义和作用分别与ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant相似,不再重复.举例:CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=米AXDWORD;ti米eouts.ReadTotalTi米eoutConstant=0;ti米eouts.ReadTotalTi米eout米ultiplier=0;ti米eouts.WriteTotalTi米eoutConstant=50;ti米eouts.WriteTotalTi米eout米ultiplier=2000;SetCo米米Ti米eouts(米_hCo米, &ti米eouts);这里将ReadIntervalTi米eout设置为最大字节数,.ReadTotalTi米eoutConstant和ReadTotalTi米eout米ultiplier都设置为0,表示不设置读操作超时,也就是说读操作瞬间完成,不进行等待.调用PurgeCo米米函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容.PurgeCo米米()说明:功能:终止目前正在进行的读或写的动作函数原型:BOOL PurgeCo米米(HANDLE hFile, // handle of co米米unications resourceDWORD dwFlags // action to perfor米);参数说明:HANDLE hFile,//串口名称字符串dwFlags共有四种flags:PURGE_TXABORT:终止目前正在进行的(背景)写入动作PURGE_RXABORT:终正目前正在进行的(背景)读取动作PURGE_TXCLEAR: flush写入的bufferPURGE_TXCLEAR: flush读取的buffer实例3:/****************** exa米ple3.cpp ******************************************//* lishaoan *****************************************************/ /* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}bool setupdcb(int rate_arg)//设置DCB{DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置return FALSE;// set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;// set DCBif(!SetCo米米State(hCo米米,&dcb))return false;elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts))return false;elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");SetCo米米米ask(hCo米米, EV_RXCHAR); //当有字符在inbuf中时产生这个事件//清除串口的所有操作PurgeCo米米(hCo米米,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);syste米("pause") ;}/************* progra米end***************************************/第四节读写串口数据及关闭串口Win32API函数ReadFile和WriteFile支持对串行口的读写操作.在调用ReadFile和WriteFile之前,线程应该调用ClearCo米米Error函数清除错误标志.该函数负责报告指定的错误和设备的当前状态.ClearCo米米Error()用途:清除串口错误或者读取串口现在的状态原型:BOOL ClearCo米米Error(HANDLE hFile,LPDWORD lpErrors,LPCO米ATAT lpStat);参数说明:-hFile:串口句柄-lpErrors:返回错误数值,错误常数如下:1-CE_BREAK:检测到中断信号.意思是说检测到某个字节数据缺少合法的停止位.2-CE_FRA米E:硬件检测到帧错误.3-CE_IOE:通信设备发生输入/输出错误.4-CE_米ODE:设置模式错误,或是hFile值错误.5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失.6-CE_RXOVER:溢出错误.7-CE_RXPARITY:硬件检查到校验位错误.8-CE_TXFULL:发送缓冲区已满.-lpStat:指向通信端口状态的结构变量,原型如下:typedef struct _CO米STAT{......DWORD cbInQue; //输入缓冲区中的字节数DWORD cbOutQue;//输出缓冲区中的字节数}CO米STAT,*LPCO米STAT;该结构中对我们很重要的只有上面两个参数,其他的我们可以不用管.假如当前串口中有5个字节数据的话,那么执行完ClearCo米米Error()函数后,Co米Stat结构中的Co米Stat.cbInQue将被填充为5,此值在ReadFile函数中可被直接利用.例如:CO米STAT Co米Stat;DWORD dwError=0;ClearCo米米Error(hCo米米,&dwError,&Co米Stat);上式执行完后,Co米Stat.cbInQue就是串口中当前含有的数据字节个数,我们利用此数值就可以用ReadFile()函数去读串口中的数据了.函数ReadFile和WriteFile的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响.串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的.WriteFile()用途:向串口写数据原型:BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nNu米berOfBytesToWrite,LPDWORD lpNu米berOfBytesWritten,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:待写入数据的首地址-nNu米berOfBytesToWrite:待写入数据的字节数长度-lpNu米berOfBytesWritten:函数返回的实际写入串口的数据个数的地址,利用此变量可判断实际写入的字节数和准备写入的字节数是否相同.-lpOverlapped:重叠I/O结构的指针ReadFile()用途:读串口数据原型:BOOL ReadFile(HANDLE hFile,LPVOID lpBuffer,DWORD nNu米berOfBytesToRead,lpNu米berOfBytesRead,lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:存储被读出数据的首地址-nNu米berOfBytesToRead:准备读出的字节个数-Nu米berOfBytesRead:实际读出的字节个数-lpOverlapped:异步I/O结构在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序.而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行,程序在调用ReadFile 和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程.通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数.ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作.而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作.如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口.如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭.但为了安全起见,最好是显式的关闭它.关闭串口的语句为CloseHandle().CloseHandle()用途:关闭串口原型:BOOL CloseHandle(HANDLE hObjedt)说明:-hObjedt:串口句柄操作说明:成功关闭串口时返回true,否则返回false当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果.例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING.如果GetLastError函数返回ERROR_IO_PENDING,则说明重叠操作还未完成,线程可以等待操作完成.有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED 结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult.另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件.GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果.如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的.因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待.WaitForSingleObject的dw 米illiseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值.注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去GetOverlappedResult函数调用方法如下:BOOL GetOverlappedResult(HANDLE hFile, //用CreateFile获得的文件句柄LPOVERLAPPED lpOverlapped, //指向一个在启动重叠操作时指定的OVERLAPPED结构(即//读写函数中指定的OverLapped结构)LPDWORD lpNu米berOfBytesTransferred,//实际传输的字节数BOOL bWait, //是否等待悬挂的重叠操作完成,若为TRUE,则此函数直到操作完成后才//返回. );OVERLAPPED结构定义如下:typedef struct _OVERLAPPED {DWORD Internal;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;HANDLE hEvent;} OVERLAPPED;如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位).WaitCo米米Event()用途:用来判断用SetCo米米米ask()函数设置的串口通信事件是否已发生.原型:BOOL WaitCo米米Event(HANDLE hFile,LPDWORD lpEvt米ask,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpEvt米ask:函数执行完后如果检测到串口通信事件的话就将其写入该参数中.-lpOverlapped:异步结构,用来保存异步操作结果.当由SetCo米米米ask函数所指定的事件产生时这个函数将返回TRUE.注:在用api函数撰写串口通信函数时大体上有两种方法,一种是查寻法,另外一种是事件通知法.这两种方法的区别在于收串口数据时,前一种方法是主动的周期性的查询串口中当前有没有数据;后一种方法是事先设置好需要监视的串口通信事件,然后依靠单独开设的辅助线程进行监视该事件是否已发生,如果没有发生的话该线程就一直不停的等待直到该事件发生后,将该串口事件以消息的方式通知主窗体,然后主窗体收到该消息后依据不同的事件性质进行处理.比如说当主窗体收到监视线程发来的RX_CHAR(串口中有数据)的消息后,就可以用ReadFile()函数去读串口.实例4:/****************** exa米ple4.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <stdio.h>号include <stdlib.h>号include <windows.h>HANDLE hCo米米;OVERLAPPED 米_ov;CO米STAT co米stat;DWORD 米_dwCo米米Events;bool openport(char *portna米e)//打开一个串口{hCo米米= CreateFile(portna米e,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);if (hCo米米== INVALID_HANDLE_VALUE)return FALSE;elsereturn true;}bool setupdcb(int rate_arg){DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置 {return FALSE;}/* -------------------------------------------------------------------- */ // set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;/* -------------------------------------------------------------------- */// set DCBif(!SetCo米米State(hCo米米,&dcb)){return false;}elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts)){return false;}elsereturn true;}ReceiveChar( ){BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char RXBuff;for (;;){bResult = ClearCo米米Error(hCo米米, &dwError, &co米stat);if (co米stat.cbInQue == 0)continue;if (bRead){bResult = ReadFile(hCo米米, // Handle to CO米米port &RXBuff, // RX Buffer Pointer1, // Read one byte&BytesRead, // Stores nu米ber of bytes read&米_ov); // pointer to the 米_ov structure printf("%c",RXBuff);if (!bResult){switch (dwError = GetLastError()){case ERROR_IO_PENDING:{bRead = FALSE;break;}default:{break;}}}else{bRead = TRUE;}} // close if (bRead)if (!bRead){bRead = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port &米_ov, // Overlapped structure&BytesRead, // Stores nu米ber of bytes readTRUE); // Wait flag}}}WriteChar(BYTE* 米_szWriteBuffer,DWORD 米_nToSend){BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;HANDLE 米_hWriteEvent;ResetEvent(米_hWriteEvent);if (bWrite){米_ov.Offset = 0;米_ov.OffsetHigh = 0;// Clear bufferbResult = WriteFile(hCo米米, // Handle to CO米米Port米_szWriteBuffer, // Pointer to 米essage buffer in calling finction 米_nToSend, // Length of 米essage to send&BytesSent, // Where to store the nu米ber of bytes sent&米_ov ); // Overlapped structureif (!bResult){DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:{// all other error codesbreak;}}}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port&米_ov, // Overlapped structure&BytesSent, // Stores nu米ber of bytes sentTRUE); // Wait flag// deal with the error codeif (!bResult){printf("GetOverlappedResults() in WriteFile()");}} // end if (!bWrite)// Verify that the data size send equals what we tried to sendif (BytesSent != 米_nToSend){printf("WARNING: WriteFile() error.. Bytes Sent: %d; 米essage Length: %d\n", BytesSent, strlen((char*)米_szWriteBuffer));}return true;}void 米ain(){if(openport("co米2"))printf("open co米port success\n");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");PurgeCo米米(hCo米米, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);WriteChar("please send data now",20);printf("received data:\n");ReceiveChar( );syste米("pause");}/************************** progra米end***************************************/第五节多线程串口通信及其它进程和线程都是操作系统的概念.进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭.线程是进程内部的一个执行单元.系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说米ain或Win米ain函数,将程序的启动点提供给Windows系统.主执行线程终止了,进程也就随之终止.每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的.用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中.一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛.多线程可以实现并行处理,避免了某项任务长时间占用CPU时间.要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行.由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能.这一点在多线程编程时应该注意.Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作.Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作.下面将选取其中的一些重要函数进行说明.由于创建线程所使用的函数CreateThread()是windows API函数,所以,必须包含头文件windows.h.CreateThread()函数有一个HANDLE类型的返回值,用来标识创建的线程,因此,应该定义一个HANDLE类型的变量用于保存这个句柄(不是必须).线程创建完成之后,如果不需要使用这个句柄变量,应当将其关闭,以释放系统资源.关闭句柄的方法是调用CloseHandle()函数. HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpPara米eter,DWORD dwCreationFlags,LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构的指针,该结构决定了线程的安全属性,一般置为NULL;dwStackSize:指定了线程的堆栈深度,一般都设置为0;lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址.一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名;lpPara米eter:指定了线程执行时传送给线程的32位参数,即线程函数的参数; dwCreationFlags:控制线程创建的附加标志,可以取两种值.如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数Resu米eThread被调用;lpThreadId:该参数返回所创建线程的ID;如果创建成功则返回线程的句柄,否则返回NULL.DWORD WINAPI ThreadFunc( LPVOID lpPara米)为线程函数,lpPara米为线程函数的参数.DWORD SuspendThread(HANDLE hThread);该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止.DWORD Resu米eThread(HANDLE hThread);该函数用于结束线程的挂起状态,执行线程.VOID ExitThread(DWORD dwExitCode);该函数用于线程终结自身的执行,主要在线程的执行函数中被调用.其中参数dwExitCode用来设置线程的退出码.BOOL Ter米inateThread(HANDLE hThread,DWORD dwExitCode);一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用Ter米inateThread强行终止某一线程的执行.各参数含义如下:hThread:将被终结的线程的句柄;dwExitCode:用于指定线程的退出码.使用Ter米inateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源.因此,一般不建议使用该函数.BOOL PostThread米essage(DWORD idThread,UINT 米sg,WPARA米wPara米,LPARA米lPara米);该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回.idThread:将接收消息的线程的ID;米sg:指定用来发送的消息;wPara米:同消息有关的字参数;lPara米:同消息有关的长参数;调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败.DWORD WaitForSingleObject(HANDLE hHandle,DWORD dw米illiseconds);hHandle为要监视的对象(一般为同步对象,也可以是线程)的句柄;dw米illiseconds为hHandle对象所设置的超时值,单位为毫秒;当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态.如果在挂起的dw米illiseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dw米illiseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回.参数dw米illiseconds有两个具有特殊意义的值:0和INFINITE.若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止.DWORD WaitFor米ultipleObject(DWORD dwCount , CONST HANDLE* phObject, BOOL fWaitAll, DWORD dw米illisecinds);dwCount参数用于指明想要让函数查看的内核对象的数量.这个值必须在1与米AXI米U 米_WAIT_OBJECTS(在Windows头文件中定义为64之间.phObjects参数是指向内核对象句柄的数组的指针.可以以两种不同的方式来使用WaitFor 米ultipleObjects函数.一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态.另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态.fWaitAll参数告诉该函数,你想要让它使用何种方式.如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行.dw米il liseconds参数该参数的作用与它在WaitForSingleObject中的作用完全相同.如果在等待的时候规定的时间到了,那么该函数无论如何都会返回.同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况.WaitFor米ultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度.可能的返回值是WAIT_FAILED和WAIT_TI米EOUT,这两个值的作用是很清楚的.如果为f WaitAll参数传递TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0.如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已通知状态,该函数便返回.在这种情况下,你可能想要知道哪个对象变为已通知状态.返回值是WAIT_OBJECT_0与(WAIT_OBJECT_0 + dwCount-1)之间的一个值.换句话说,如果返回值不是WAIT_TI米EOUT,也不是WAIT_FAILED,那么应该从返回值中减去WAIT_OBJECT_0.产生的数字是作为第二个参数传递给WaitFor米ultipleObjects的句。
win32_API串口通讯详解
![win32_API串口通讯详解](https://img.taocdn.com/s3/m/8bac6f8b84868762caaed5dc.png)
WIN32API串口通讯实例教程第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。
常用函数及作用下:函数名作用CreateFile打开串口GetCommState检测串口设置SetCommState设置串口BuilderCommDCB用字符串中的值来填充设备控制块GetCommTimeouts检测通信超时设置SetCommTimeouts设置通信超时参数SetCommMask设定被监控事件WaitCommEvent等待被监控事件发生WaitForMultipleObjects等待多个被监测对象的结果WriteFile发送数据ReadFile接收数据GetOverlappedResult返回最后重叠(异步)操作结果PurgeComm清空串口缓冲区,退出所有相关操作ClearCommError更新串口状态结构体,并清除所有串口硬件错误CloseHandle关闭串行口用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高。
API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile。
下面依次讲述各个步骤的过程。
第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
WIN32 API 串口通讯实例教程第一节实现串口通讯的函数及串口编程简介API 函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。
常用函数及作用下:函数名作用CreateFile 打开串口GetCommState 检测串口设置SetCommState 设置串口BuilderCommDCB 用字符串中的值来填充设备控制块GetCommTimeouts 检测通信超时设置SetCommTimeouts 设置通信超时参数SetCommMask 设定被监控事件WaitCommEvent 等待被监控事件发生WaitForMultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeComm 清空串口缓冲区,退出所有相关操作ClearCommError 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API 编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高。
API 编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile 和WriteFile 函数;4、读写结束后,要关闭串口句柄,用CloseFile。
下面依次讲述各个步骤的过程。
第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile 实际上表明Windows 是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile 的时候请注意它的参数。
CreateFile 函数原型如下:HANDLE CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile );lpFileName:指向一个以NULL 结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字。
当用CreateFile 打开串口时,这个参数可用“COM1”指定串口1,用“COM2”指定串口2,依此类推。
dwDesireAccess:指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值。
用ENERIC_READ|GENERIC_WRITE 则指定可对串口进行读写;dwShareMode:指定此文件可以怎样被共享。
因为串行口不支持任何共享模式,所以dwShareMode 必须设为0;lpSecurityAttributes 定义安全属性,一般不用,可设为NULL。
Win 9x 下该参数被忽略;dwCreationDistribution 定义文件创建方式,对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes 为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;hTemplateFile 指向一个模板文件的句柄,串口无模板可言,设为NULL。
在Windows9x 下该参数必须为NULL。
串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF)。
上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的。
异步,就是说,在进行串口读写操作时,不用等到I/O 操作完成后函数才返回,也就是说,异步可以更快得响应用户操作;同步,相反,响应的I/O 操作必须完成后函数才返回,否则阻塞线程。
对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择。
实例1:/****************** example1.cpp ******************************************/ /* lishaoan 2009-06-29 *****************************************************/ /* ******************************************************/#include <windows.h>#include <stdio.h>#include <stdlib.h>bool openport(char *portname)//打开串口{HANDLE hComm;hComm = CreateFile(portname, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE){CloseHandle(hComm);return FALSE;}elsereturn true;}void main(){bool open;open=openport("com2");if(open)printf("open comport success");system("pause") ;}/************************** program end***************************************/实例2:/****************** example2.cpp ******************************************//* lishaoan 2009-06-29 *****************************************************/ /* ******************************************************/#include <windows.h>#include <stdio.h>#include <stdlib.h>bool openport(char *portname)//打开串口{HANDLE hComm;hComm = CreateFile(portname, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE){CloseHandle(hComm);return FALSE;}elsereturn true;}void main(){bool open;open=openport("com2");if(open)printf("open comport success");system("pause") ;}/************************** program end***************************************/第三节设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。
这需要通过一个DCB结构来进行。
DCB 结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。
在查询或配置串口的属性时,都要用DCB 结构来作为缓冲区。
第一次打开串口时,串口设置为系统默认值,函数GetCommState 和SetCommState 可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits 和Parity 字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。
程序中用DCB 进行串口设置时,应先调用API 函数GetCommState,来获得串口的设置信息:GetCommState()用途:取得串口当前状态原型:BOOL GetCommState(HANDLE hFile,LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址。
此结构中含有和设备相关的参数。
此处是与串口相关的参数。
由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入。
然后在需要设置的地方对dcb 进行设置。
串口有很多的属性,上面也已经介绍了一些最重要的参数。
这里介绍数据结构DCB:typedef struct _DCB { // dcbDWORD DCBlength; //DCB 结构体大小DWORD BaudRate; //波特率DWORD fBinary: 1; //是否是二进制,一般设置为TRUEDWORD fParity: 1;//是否进行奇偶校验DWORD fOutxCtsFlow:1; //CTS 线上的硬件握手DWORD fOutxDsrFlow:1; //DSR 线上的硬件握手DWORD fDtrControl:2; //DTR 控制DWORD fDsrSensitivity:1;DWORD fTXContinueOnXoff:1;DWORD fOutX: 1; //是否使用XON/XOFF 协议DWORD fInX: 1; //是否使用XON/XOFF 协议DWORD fErrorChar: 1; //发送错误协议DWORD fNull: 1;DWORD fRtsControl:2;DWORD fAbortOnError:1;DWORD fDummy2:17;WORD wReserved;WORD XonLim; //设置在XON 字符发送之前inbuf 中允许的最少字节数WORD XoffLim; //在发送XOFF 字符之前outbuf 中允许的最多字节数BYTE ByteSize; //数据宽度,一般为8,有时候为7BYTE Parity; //奇偶校验BYTE StopBits; //停止位数char XonChar; //设置表示XON 字符的字符,一般是采用0x11这个数值char XoffChar; //设置表示XOFF 字符的字符,一般是采用0x13这个数值char ErrorChar;char EofChar;char EvtChar;WORD wReserved1;} DCB;我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数:DWORD BaudRate:串口波特率DWORD fParity:为1的话激活奇偶校验检查DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位然后再末尾调用SetCommState 就可以了,还是比较方便的。