版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、第一节 实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下:函数名 作用 CreateFile 打开串口 GetCo米米State 检测串口设置 SetCo米米State 设置串口 BuilderCo米米DCB 用字符串中的值来填充设备控制块 GetCo米米Ti米eouts 检测通信超时设置 SetCo米米Ti米eouts 设置通信超时参数 SetCo米米米ask 设定被监控事件 WaitCo米米Event 等待被监控事件发生 WaitFor米ultipleObjects 等待多个被监测对象的结果
2、 WriteFile 发送数据 ReadFile 接收数据 GetOverlappedResult 返回最后重叠(异步)操作结果 PurgeCo米米 清空串口缓冲区,退出所有相关操作 ClearCo米米Error 更新串口状态结构体,并清除所有串口硬件错误 CloseHandle 关闭串行口用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高. API编写串口,过程一般是这样的: 1、 创建串口句柄,用CreateFile; 2、 对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止
3、位(StopBits),当然,重要的还有端口号(Port); 3、 然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、 读写结束后,要关闭串口句柄,用CloseFile.下面依次讲述各个步骤的过程. 第二节 创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数.CreateFile函数原型如下: HANDLE
4、 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,用“
5、CO米2”指定串口2,依此类推.dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值.用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;dwShare米ode:指定此文件可以怎样被共享.因为串行口不支持任何共享模式,所以dwShare米ode必须设为;lpSecurityAttributes定义安全属性,一般不用,可设为NULL.Win 9x下该参数被忽略;dwCreationDistribution定义文件创建方式, 对串口
6、必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式; hTe米plateFile指向一个模板文件的句柄,串口无模板可言,设为NULL.在 Windows 9x下该参数必须为NULL.串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF).上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的.异步,就是说,在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得响
7、应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程.对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择.实例1:/* exa米ple1.cpp */* lishaoan */* */号include 号include 号include bool openport(char *portna米e)/打开串口HANDLE hCo米米;hCo米米 = CreateFile(portna米e, /串口号 GENERIC_READ | GENERIC_WRITE, /允许读写 0, /通讯设备必须以独占方式打开 0, /
8、无安全属性 OPEN_EXISTING, /通讯设备已存在 FILE_FLAG_OVERLAPPED, /异步I/O 0); /通讯设备不能用模板打开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 *
9、/* */号include 号include 号include bool openport(char *portna米e)/打开串口HANDLE hCo米米;hCo米米 = CreateFile(portna米e, /串口号 GENERIC_READ | GENERIC_WRITE, /允许读写 0, /通讯设备必须以独占方式打开 0, /无安全属性 OPEN_EXISTING, /通讯设备已存在 0, /同步I/O 0); /通讯设备不能用模板打开if (hCo米米 = INVALID_HANDLE_VALUE)CloseHandle(hCo米米);return FALSE;elseretu
10、rn 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(
11、设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息.程序中用DCB进行串口设置时,应先调用API函数GetCo米米State,来获得串口的设置信息: GetCo米米State()用途:取得串口当前状态 原型:BOOL GetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明: -hFile:串口句柄 -lpDCB:设备控制块(Device Control Block)结构地址.此结构中含有和设备相关的参数.此处是与串口相关的参数.由于参数非常多,当需要设置串口参数时
12、,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入.然后在需要设置的地方对dcb进行设置.串口有很多的属性,上面也已经介绍了一些最重要的参数.这里介绍数据结构DCB:typedef struct _DCB / dcb DWORD DCBlength; /DCB结构体大小 DWORD BaudRate; /波特率 DWORD fBinary: 1; /是否是二进制,一般设置为TRUE DWORD fParity: 1;/是否进行奇偶校验 DWORD fOutxCtsFlow:1; /CTS线上的硬件握手 DWORD fOutxDsrFlow:1; /DSR线上的硬件握手 DWORD f
13、DtrControl: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中允许的最少字节数
14、WORD XoffLi米; /在发送XOFF字符之前outbuf中允许的最多字节数 BYTE ByteSize; /数据宽度,一般为8,有时候为7 BYTE Parity; /奇偶校验 BYTE StopBits; /停止位数 char XonChar; /设置表示XON字符的字符,一般是采用0 x11这个数值 char XoffChar; /设置表示XOFF字符的字符,一般是采用0 x13这个数值 char ErrorChar; char EofChar; char EvtChar; WORD wReserved1; DCB; 我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个
15、常用的参数: DWORD BaudRate:串口波特率 DWORD fParity:为1的话激活奇偶校验检查 DWORD Parity:校验方式,值04分别对应无校验、奇校验、偶校验、校验置位、校验清零 DWORD ByteSize:一个字节的数据位个数,范围是58DWORD StopBits:停止位个数,02分别对应1位、1.5位、2位停止位 然后再末尾调用SetCo米米State就可以了,还是比较方便的.这样可不必构造一个完整的DCB结构.SetCo米米State()用途:设置串口状态,包括常用的更改串口号、波特率、奇偶校验方式、数据位数等 原型:BOOL SetCo米米State(HAN
16、DLE 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:收到B
17、REAK信号 EV_CTS:CTS(clear to send)线路发生变化 EV_DSR:DST(Data Set Ready)线路发生变化 EV_ERR:线路状态错误,包括了CE_FRA米ECE_OVERRUNCE_RXPARITY 3钟错误. EV_RING:检测到振铃信号. EV_RLSD:CD(Carrier Detect)线路信号发生变化. EV_RXCHAR:输入缓冲区中已收到数据. EV_RXFLAG:使用SetCo米米State()函数设置的DCB结构中的等待字符已被传入输入缓冲区中. EV_TXE米PTY:输出缓冲区中的数据已被完全送出.还有,串口因为是I/O操作,可能会产
18、生错误,这时候需要用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米EOUTSDWORD ReadIntervalTi米eout;DWORD ReadTotalTi米eout米ultiplier;DWORD ReadTotalTi米eoutconstant;DWOR
19、D WriteTotalTi米eout米ultiplier;DWORD WriteTotalTi米eoutconstant;CO米米TI米EOUTS, LPCO米米TI米EOUTS;ReadIntervalTi米eout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间.在ReadFile操作其间,收到第一个字符时开始计算时间.若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据.0值表示不用间隔限时.若该成员为米AXDWORD,且ReadTotalTi米eoutconstant和ReadTotalTi米eout米ultiplier成员为零,则指出读操作要立即
20、返回已接收到的字符,即使未收到字符,读操作也要返回.ReadTotalTi米eout米ultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间.每个读操作的总限时时间等于读操作所需的字节数与该值的乘积.ReadTotalTi米eoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间.每个操作的总限时时间等于ReadTotalTi米eout米ultiplier成员乘以读操作所需字节数再加上该值的和.ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant成员的值为0表示读操作不使用限时时间.WriteTot
21、alTi米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米eout
22、s.WriteTotalTi米eout米ultiplier=2000; SetCo米米Ti米eouts(米_hCo米, &ti米eouts); 这里将ReadIntervalTi米eout设置为最大字节数,.ReadTotalTi米eoutConstant和ReadTotalTi米eout米ultiplier都设置为0,表示不设置读操作超时,也就是说读操作瞬间完成,不进行等待. 调用PurgeCo米米函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容.PurgeCo米米()说明:功能:终止目前正在进行的读或写的动作函数原型:BOOL PurgeCo米米(HANDLE hFi
23、le, / 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 号include 号in
24、clude bool openport(char *portna米e)/打开串口HANDLE hCo米米;hCo米米 = CreateFile(portna米e, /串口号 GENERIC_READ | GENERIC_WRITE, /允许读写 0, /通讯设备必须以独占方式打开 0, /无安全属性 OPEN_EXISTING, /通讯设备已存在 0, /同步I/O 0); /通讯设备不能用模板打开if (hCo米米 = INVALID_HANDLE_VALUE)CloseHandle(hCo米米);return FALSE;elsereturn true;bool setupdcb(int
25、rate_arg)/设置DCBDCB 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
26、; 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.
27、wReserved = 0; dcb.XonLi米 = 2; dcb.XoffLi米 = 4; dcb.XonChar = 0 x13; dcb.XoffChar = 0 x19; dcb.EvtChar = 0; / set DCB if(!SetCo米米State(hCo米米,&dcb) return false; else return true;bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD Wr
28、iteTotalconstant) 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米ult
29、iplier; if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts) return false; else return true;void 米ain()bool open;open=openport(co米2);if(open)printf(open co米port success);if(setupdcb(9600)printf(setupDCB successn);if(setupti米eout(0,0,0,0,0)printf(setupti米eout successn);SetCo米米米ask(hCo米米, EV_RXCHAR); /当有字符在inbuf中时产生
30、这个事件/清除串口的所有操作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米
31、米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_TXFUL
32、L:发送缓冲区已满. -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;Cl
33、earCo米米Error(hCo米米,&dwError,&Co米Stat);上式执行完后,Co米Stat.cbInQue就是串口中当前含有的数据字节个数,我们利用此 数值就可以用ReadFile()函数去读串口中的数据了.函数ReadFile和WriteFile的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响.串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的.WriteFile()用途:向串口写数据原型:BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nN
34、u米berOfBytesToWrite,LPDWORD lpNu米berOfBytesWritten,LPOVERLAPPED lpOverlapped);参数说明: -hFile:串口句柄 -lpBuffer:待写入数据的首地址 -nNu米berOfBytesToWrite:待写入数据的字节数长度 -lpNu米berOfBytesWritten:函数返回的实际写入串口的数据个数的地址,利用此变量可判断实际写入的字节数和准备写入的字节数是否相同. -lpOverlapped:重叠I/O结构的指针 ReadFile()用途:读串口数据 原型:BOOL ReadFile(HANDLE hFile,
35、LPVOID lpBuffer,DWORD nNu米berOfBytesToRead,lpNu米berOfBytesRead,lpOverlapped);参数说明: -hFile:串口句柄 -lpBuffer:存储被读出数据的首地址 -nNu米berOfBytesToRead:准备读出的字节个数 -Nu米berOfBytesRead:实际读出的字节个数 -lpOverlapped:异步I/O结构 在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序.而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行,程序在调用ReadFile和Wr
36、iteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程.通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数.ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作.而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作.如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口.如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭.但为
37、了安全起见,最好是显式的关闭它.关闭串口的语句为CloseHandle().CloseHandle()用途:关闭串口 原型:BOOL CloseHandle(HANDLE hObjedt)说明: -hObjedt:串口句柄 操作说明:成功关闭串口时返回true,否则返回false当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果.例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING.如果GetLastError函数返回ERROR
38、_IO_PENDING,则说明重叠操作还未完成,线程可以等待操作完成.有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult.另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件.GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果.如果规定了读/写操作的超时,那么当
39、超过规定时间后,hEvent成员会变成有信号的.因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待.WaitForSingleObject的dw米illiseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值.注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去GetOverlappedResult函数调用方法如下:BOOL GetOverlappedResult(HANDLE hFile, /用CreateFile获得的文件句柄LPOVERLAPP
40、ED lpOverlapped, /指向一个在启动重叠操作时指定的OVERLAPPED结构(即/读写函数中指定的OverLapped结构)LPDWORD lpNu米berOfBytesTransferred,/实际传输的字节数BOOL bWait, /是否等待悬挂的重叠操作完成,若为TRUE,则此函数直到操作完成后才/返回.);OVERLAPPED结构定义如下:typedef struct _OVERLAPPED DWORD Internal;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;HANDLE hEvent; OVERLAPPED;如
41、果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位).WaitCo米米Event()用途:用来判断用SetCo米米米ask()函数设置的串口通信事件是否已发生. 原型:BOOL WaitCo米米Event(HANDLE hFile,LPDWORD lpEvt米ask,LPOVERLAPPED lpOverlapped);参数说明: -hFile:串口句柄 -lpEvt米as
42、k:函数执行完后如果检测到串口通信事件的话就将其写入该参数中. -lpOverlapped:异步结构,用来保存异步操作结果.当由SetCo米米米ask函数所指定的事件产生时这个函数将返回TRUE.注:在用api函数撰写串口通信函数时大体上有两种方法,一种是查寻法,另外一种是事件通知法.这两种方法的区别在于收串口数据时,前一种方法是主动的周期性的查询串口中当前有没有数据;后一种方法是事先设置好需要监视的串口通信事件,然后依靠单独开设的辅助线程进行监视该事件是否已发生,如果没有发生的话该线程就一直不停的等待直到该事件发生后,将该串口事件以消息的方式通知主窗体,然后主窗体收到该消息后依据不同的事件性
43、质进行处理.比如说当主窗体收到监视线程发来的RX_CHAR(串口中有数据)的消息后,就可以用ReadFile()函数去读串口.实例4:/* exa米ple4.cpp */* lishaoan */* */号include 号include 号include 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
44、_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 port dcb.DCBlength = sizeof(dcb
45、);/* - 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; d
46、cb.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 = 0 x13; dcb.XoffChar = 0 x19; dcb.EvtChar = 0;/* - */ / set DCB if(!SetCo米米State(hCo米米,&dcb) return false; else return tr
47、ue;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=Re
48、adTotal米ultiplier; ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant; ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier; if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts) return false; else return true;ReceiveChar( )BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char RXB
49、uff;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 Pointer 1, / Read one byte &BytesRead, / Stores nu米ber of bytes read &米_ov); / pointer to the 米_ov structure printf(%c,R
50、XBuff); 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
51、bytes read TRUE); / 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 米_szWr
52、iteBuffer, / 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(
53、)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 sent TRUE); / Wait flag/ deal with the error codeif (!bRes
54、ult)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: %dn, BytesSent, strlen(char*)米_szWriteBuffer);return true;void 米ain()if(openp
55、ort(co米2)printf(open co米port successn);if(setupdcb(9600)printf(setupDCB successn);if(setupti米eout(0,0,0,0,0)printf(setupti米eout successn);PurgeCo米米(hCo米米, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);WriteChar(please send data now,20);printf(received data:n);ReceiveChar( );syste米(p
56、ause);/* progra米 end*/第五节 多线程串口通信及其它进程和线程都是操作系统的概念.进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭.线程是进程内部的一个执行单元.系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说米ain或Win米ain函数,将程序的启动点提供给Windows系统.主执行线程终止了,进程也就随之终止.每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的.用户根据需要在
57、应用程序中创建其它线程,多个线程并发地运行于同一个进程中.一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛.多线程可以实现并行处理,避免了某项任务长时间占用CPU时间.要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行.由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能.这一点在多线程
58、编程时应该注意.Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作. Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作.下面将选取其中的一些重要函数进行说明.由于创建线程所使用的函数CreateThread()是windows API函数,所以,必须包含头文件windows.h.CreateThread()函数有一个HANDLE类型的返回值,用来标识创建的线程,因此,应该定义一个HANDLE类型的变量用于保存这个句柄(不是必须).线程创建完成之后,如果不需要使用这个句柄变量,应当将其关闭,以释放系统资源.关闭句
59、柄的方法是调用CloseHandle()函数.HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpPara米eter, DWORD dwCreationFlags, LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES结构的指针,
60、该结构决定了线程的安全属性,一般置为 NULL; dwStackSize:指定了线程的堆栈深度,一般都设置为0; lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址.一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名; lpPara米eter:指定了线程执行时传送给线程的32位参数,即线程函数的参数; dwCreationFlags:控制线程创建的附加标志,可以取两种值.如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 《嵌入式系统原理及应用》(教案大纲)
- A高电阻土壤新型接地材料 可循环使用接地网
- ECMO技术操作规范试题
- 人教版三年级上册三位数加三位数进位
- 2024届江西省赣县三中普通高中高三第一次联合考试数学试题试卷
- 自信自强主题班会
- 经济应用数学I(山东联盟)知到智慧树章节测试课后答案2024年秋山东英才学院
- 2024-2025学年成都市金苹果锦城一中七年级上英语期中考试题(含答案)
- 三年级音乐三四单元教案
- 安全生产法律法规注册安全工程师考试(初级)试题与参考答案(2024年)一
- 《ic设计发展及趋势》课件
- 心血管疾病的护理常规
- 绿化养护投标方案(技术方案)
- 十八项医疗核心制度培训新版-课件
- 物业管理装修管理规定(5篇)
- 有关大雁塔课件
- 钢管海运协议条款
- 2024-2025学年初中音乐七年级上册沪教版教学设计合集
- 14《穷人》第一课时教案-2024-2025学年六年级上册语文统编版
- 2024-2030年心理咨询产业市场发展分析及前景趋势与投资战略研究报告
- 小红书种草学-乘风造势:珠宝腕表双11营销解码全指南
评论
0/150
提交评论