使用Win32API实现Windows下异步串口通讯.doc_第1页
使用Win32API实现Windows下异步串口通讯.doc_第2页
使用Win32API实现Windows下异步串口通讯.doc_第3页
使用Win32API实现Windows下异步串口通讯.doc_第4页
使用Win32API实现Windows下异步串口通讯.doc_第5页
已阅读5页,还剩20页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

使用Win32API实现Windows下异步串口通讯关键词: Win32API 串口通讯 使用Win32API实现Windows下异步串口通讯(上)- - 目录:1 异步非阻塞串口通讯的优点2 异步非阻塞串口通讯的基本原理3 异步非阻塞串口通讯的基础知识4 异步非阻塞串口通讯的实现步骤2005.01.05一,异步非阻塞串口通讯的优点读写串行口时,既可以同步执行,也可以重叠(异步)执行。在同步执行时,函数直到操作完成后才返回。这意味着在同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,调用的函数也会立即返回。费时的I/O操作在后台进行,这样线程就可以干别的事情。例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。重叠一词的含义就在于此。二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用 GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。 三,异步非阻塞串口通讯的基础知识下面来介绍并举例说明一下编写异步非阻塞串口通讯的程序中将会使用到的几个关键函数CreateFile()功能:打开串口设备函数原型HANDLE CreateFile(LPCTSTR lpFileName, / 串口名称字符串;如: COM1 或 COM2DWORD dwDesiredAccess, / 设置读写属性(访问模式 );一般为 GENERIC_READ|GENERIC_WRITE,DWORD dwShareMode, / 共享模式;必须为 0, 即不能共享LPSECURITY_ATTRIBUTES lpSecurityAttributes, / 安全属性;一般为NULLDWORD dwCreationDistribution, / 创建方式,串口设置必须设置此值; 在这里必须为 OPEN_EXISTINGDWORD dwFlagsAndAttributes, / 文件属性和标志;在这里我们设置成FILE_FLAG_OVERLAPPED ,实现异步I/OHANDLE hTemplateFile / 临时文件的句柄,通常为NULL );说明:如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。Forexample:Handle m_hComm = CreateFile(com1,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);CloseHandle();功能:关闭串口BOOL CloseHandle(HANDLE hObject / handle to object to close)这个,我想就不多说了吧!GetCommState()功能:获得串口状态BOOL GetCommState(HANDLE hFile, / handle of communications deviceLPDCB lpDCB / address of device-control block structure);SetCommState()功能:设置串口状态BOOL SetCommState(HANDLE hFile, / handle of communications deviceLPDCB lpDCB / address of device-control block structure);说明:在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。在查询或配置置串行口的属性时,都要用DCB结构来作为缓冲区。调用GetCommState函数可以获得串口的配置,该函数把当前配置填充到一个DCB结构中。一般在用CreateFile打开串行口后,可以调用 GetCommState函数来获取串行口的初始配置。要修改串行口的配置,应该先修改DCB结构,然后再调用SetCommState函数用指定的 DCB结构来设置串行口Forexample:DCB dcb;memset(&dec,0,dizeof(dcb);if(!GetCommState(HComm,&dcb)/获取当前DCB配置return FALSE;dcb.BaudRate = CBR_9600;/修改数据传输率.if(SetCommState(hComm,&dcb)/设置新参数./错误处理BuildCommDCB()功能:初始化DCB结构BOOL BuildCommDCB(LPCTSTR lpDef, / pointer to device-control stringLPDCB lpDCB / pointer to device-control block);Forexample:DCB dcb;memset(&dcb,0,sizeof(dcb);dcb.DCBlength = sizeof(dcb);if(!BuildCommDCb(9600,n,8,1,&dcb)/baud=9600 parity=N data=8 stop=1./参数修改错误return FALSE;else./己准备就绪说明:功能同上面的例子。SetupComm()功能:设置I/O缓冲区的大小函数原型:BOOL SetupComm( HANDLE hFile, / handle to communications device DWORD dwInQueue, / size of input buffer DWORD dwOutQueue / size of output buffer);说明:除了在DCB中的设置外,程序一般还需要设置I/O缓冲区的大小和超时。Windows用I/O缓冲区来暂存串行口输入和输出的数据,如果通信的速率较高,则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。先介绍一个结构:COMMTIMEOUTS typedef struct _COMMTIMEOUTS DWORD ReadIntervalTimeout; / 读间隔超时 DWORD ReadTotalTimeoutMultiplier; / 读时间系数 DWORD ReadTotalTimeoutConstant; / 读时间常量 DWORD WriteTotalTimeoutMultiplier; / 写时间系数DWORD WriteTotalTimeoutConstant; / 写时间常量 COMMTIMEOUTS,*LPCOMMTIMEOUTS; 再介绍两个函数GetCommTimeouts功能:读取TimeOut的值函数原型:BOOL GetCommTimeouts(HANDLE hFile, / handle of communications deviceLPCOMMTIMEOUTS lpCommTimeouts / address of comm. time-outs structure);SetCommTimeouts功能:设置TimeOUt的值函数原型:BOOL SetCommTimeouts(HANDLE hFile, / handle of communications deviceLPCOMMTIMEOUTS lpCommTimeouts / address of communications time-out structure);这里顺便介绍一下TimeOut机制的两个性质:超时函数说明:在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或 WriteFile的操作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。 有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为: COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是: 总超时=时间系数要求读/写的字符数 + 时间常量 例如,如果要读入10个字符,那么读操作的总超时的计算公式为: 读总超时ReadTotalTimeoutMultiplier10 + ReadTotalTimeoutConstant 可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。 如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果 ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。 在用重叠方式读写串行口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。 Forexample:COMMTIMEOUTS timeOver;memset(&timeOver.0.sizeof(timeOver);DWORDtimeMultiplier,timeConstant;timeOver.ReadTotalTimeoutMultiplier=timeMultiplier;timeOver.ReadTotalTimeoutConstant=timeConstant;SetCommTimeouts(hComport,&timeOver);ReadFile()功能:读取数据函数原型:BOOL ReadFile(HANDLE hFile, / 串口名称字符串(文件句柄 )LPVOID lpBuffer, / 读缓冲区 DWORD nNumberOfBytesToRead, / 要求读入的字节数LPDWORD lpNumberOfBytesRead, / 实际读入的字节数 LPOVERLAPPED lpOverlapped / 指向一个OVERLAPPED结构); /若返回TRUE则表明操作成功Forexample:char *pReciveBuf;DWORD nWantRead = 100,nReadRead;LPOVERLAPPED m_OverlappedRead;BOOL bReadStatus = ReadFile( m_hComm, preciveBuf,nWantRead, &nReadRead, &m_OverlappedRead );WriteFile() 功能:来将资料写入Serial port. 函数原型:BOOL WriteFile(HANDLE hFile, / handle to file to write toLPCVOID lpBuffer, / pointer to data to write to fileDWORD nNumberOfBytesToWrite, / number of bytes to writeLPDWORD lpNumberOfBytesWritten, / pointer to number of bytes writtenLPOVERLAPPED lpOverlapped / pointer to structure needed for overlapped I/O);说明:ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。当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的dwMilliseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去ClearCommError() 功能: 从字面上的意思看来, 它是用来清除错误情况用的, 但是实际上它还可以拿来取得目前通讯设备的一些信息.函数原型:BOOL ClearCommError(HANDLE hFile, / handle to communications deviceLPDWORD lpErrors, / pointer to variable to receive error codesLPCOMSTAT lpStat / pointer to buffer for communications status);说明:在调用ReadFile和WriteFile之前,线程应该调用ClearCommError函数清除错误标志。该函数负责报告指定的错误和设备的当前状态。 PurgeComm()功能:终止目前正在进行的读或写的动作函数原型:BOOL PurgeComm(HANDLE hFile, / handle of communications resourceDWORD dwFlags / action to perform);参数说明:HANDLE hFile,/串口名称字符串dwFlags 共有四种 flags:PURGE_TXABORT: 终止目前正在进行的(背景)写入动作PURGE_RXABORT: 终正目前正在进行的(背景)读取动作PURGE_TXCLEAR: flush 写入的 bufferPURGE_TXCLEAR: flush 读取的 buffer调用PurgeComm函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容。GetCommMask() 功能:得到设置的通信事件的掩码函数原型:BOOL GetCommMask(HANDLE hFile, / handle of communications deviceLPDWORD lpEvtMask / address of variable to get event mask);SetCommMask() 功能:设置想要得到的通信事件的掩码函数原型:BOOL SetCommMask(HANDLE hFile, / handle of communications deviceDWORD dwEvtMask / mask that identifies enabled events);说明:可设置的通信事件标志(即SetCommMask()函数所设置的掩码)可以有EV_BREAK、EV_CTS、EV_DSR、 EV_ERR、EV_RING、EV_RLSD、EV_RXCHAR、EV_RXFLAG、EV_TXEMPTY。 注:若对端口数据的响应时间要求较严格,可采用事件驱动I/O读写,Windows定义了9种串口通信事件,较常用的有: EV_RXCHAR: 接收到一个字节,并放入输入缓冲区。 EV_TXEMPTY: 输出缓冲区中的最后一个字符发送出去。 EV_RXFLAG: 接收到事件字符(DCB结构中EvtChar成员),放入输入缓冲区。 下面是MSDN上的解释:EV_BREAK A break was detected on input. EV_CTS The CTS (clear-to-send) signal changed state. EV_DSR The DSR (data-set-ready) signal changed state. EV_ERR A line-status error occurred. Line-status errors are CE_FRAME, CE_OVERRUN, and CE_RXPARITY. EV_RING A ring indicator was detected. EV_RLSD The RLSD (receive-line-signal-detect) signal changed state. EV_RXCHAR A character was received and placed in the input buffer. EV_RXFLAG The event character was received and placed in the input buffer. The event character is specified in the devices DCB structure, which is applied to a serial port by using the SetCommState function. EV_TXEMPTY The last character in the output buffer was sent. WaitCommEvent()功能:等待设定的通讯事件的发生函数原型:BOOL WaitCommEvent(HANDLE hFile, / handle of communications deviceLPDWORD lpEvtMask, / address of variable for event that occurredLPOVERLAPPED lpOverlapped, / address of overlapped structure);说明:WaitCommEvent() 会一直 block(阻塞) 到你所设定的通讯事件发生为止. 所以当 WaitCommEvent() 返回时, 你可以由 lpEvtMask 取得究竟是那一事件发生, 再来决定要如何处理.WaitForSingleObject()功能:保证线程同步的等待函数函数原型:DWORD WaitForSingleObject(HANDLE hHandle,/同步对象的句柄 DWORD dwMilliseconds/以毫秒为单位的超时间隔,如果设为INFINITE,则超时间隔是无限的);说明:返回值 含义 WAIT_FAILED 函数失败 WAIT_OBJECT_0 指定的同步对象处于有信号的状态 WAIT_ABANDONED 拥有一个mutex的线程已经中断了,但未释放该MUTEX WAIT_TIMEOUT 超时返回,并且同步对象无信号 WaitForMultipleObjects()功能:可以同时监测多个同步对象函数原型:DWORD WaitForMultipleObjects(DWORD nCount,/句柄数组中句柄的数目 CONST HANDLE *lpHandles,/代表一个句柄数组 BOOL bWaitAll, /说明了等待类型(),如果为TRUE,那么函数在所有对象都有信号后才返回,/如果为FALSE,则只要有一个对象变成有信号的,函数就返回DWORD dwMilliseconds/以毫秒为单位的超时间隔 );说明: 返回值 含义 WAIT_OBJECT_0到WAIT_ OBJECT_0+nCount-1 若bWaitAll为TRUE,则返回值表明所有对象都是有信号的。如果bWaitAll为FALSE,则返回值减去WAIT_OBJECT_0就是数组中有信号对象的最小索引。 WAIT_ABANDONED_0 到WAIT_ ABANDONED_ 0+nCount-1 若bWaitAll为TRUE,则返回值表明所有对象都有信号,但有一个mutex被放弃了。若bWaitAll为FALSE,则返回值减去WAIT_ABANDONED_0就是被放弃mutex在对象数组中的索引。 WAIT_TIMEOUT 超时返回CreateEventCreateEvent的用法HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, / SD BOOL bManualReset, / reset type BOOL bInitialState, / initial state LPCTSTR lpName / object name ); 该函数创建一个Event同步对象,并返回该对象的Handle lpEventAttributes 一般为NULL bManualReset 创建的Event是自动复位还是人工复位 ,如果true,人工复位, 一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复 为无信号. 如果为false,Event被设置为有信号,则当有一个wait到它的Thread时, 该Event就会自动复位,变成无信号. bInitialState 初始状态,true,有信号,false无信号 lpName Event对象名 一个Event被创建以后,可以用OpenEvent()API来获得它的Handle,用CloseHandle() 来关闭它,用SetEvent()或PulseEvent()来设置它使其有信号,用ResetEvent() 来使其无信号,用WaitForSingleObject()或WaitForMultipleObjects()来等待 其变为有信号. PulseEvent()是一个比较有意思的使用方法,正如这个API的名字,它使一个Event 对象的状态发生一次脉冲变化,从无信号变成有信号再变成无信号,而整个操作是原子的. 对自动复位的Event对象,它仅释放第一个等到该事件的thread(如果有),而对于 人工复位的Event对象,它释放所有等待的thread.使用Win32API实现Windows下异步串口通讯(下)- - 只一个框架性流程而矣.实现重叠模型的步骤下面就结合俺写的一个Console程序简单示例进行说明:【第一步】打开串口HANDLE m_hCom = CreateFile(com1,GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);if (m_hCom = INVALID_HANDLE_VALUE)coutCreateFile fail!return -1;coutCreateFile OK!【第二步】设置缓冲区大小if(!SetupComm(m_hCom,2048,2048)coutSetupComm fail! Close Comm!CloseHandle(m_hCom);return -1;coutSetupComm OK!【第三步】设置超时COMMTIMEOUTS TimeOuts;memset(&TimeOuts,0,sizeof(TimeOuts);TimeOuts.ReadIntervalTimeout = MAXDWORD;TimeOuts.ReadTotalTimeoutConstant = 0;TimeOuts.ReadTotalTimeoutMultiplier = 0;TimeOuts.WriteTotalTimeoutConstant = 2000;TimeOuts.WriteTotalTimeoutMultiplier = 50;SetCommTimeouts(m_hCom,&TimeOuts);【第四步】设置串口参数 DCB dcb;if (!GetCommState(m_hCom,&dcb)coutGetCommState fail! Comm closeCloseHandle(m_hCom);return -1;coutGetCommState OK!dcb.DCBlength = sizeof(dcb);if (!BuildCommDCB(9600,n,8,1,&dcb)/填充的数据传输率、奇偶校验类型、数据位、停止位/参数修改错误,进行错误处理coutBuileCOmmDCB fail,Comm close!CloseHandle(m_hCom);return -1;if(SetCommState(m_hCom,&dcb)coutSetCommState OK!【第五步】建立并初始化重叠结构OVERLAPPED wrOverlapped;ZeroMemory(&wrOverlapped,sizeof(wrOverlapped);if (wrOverlapped.hEvent != NULL)ResetEvent(wrOverlapped.hEvent);wrOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);【第六步】封装数据(按照自己的格式封装需要发送的数据,此步可以省略)typedef enumHEAT_BEAT, /心跳数据NET_STATE,/网络状态数据PACKET /正常数据包/支持可扩展性.ProtocolType;typedef enumTrain_No,/无线车次信息Attemper_Command,/调度命令信息Revert_Command,/调度命令回执信息Replay_Command,/重发的调度命令信息 KGL_SING /开关量数据/支持可扩展性.PacketDataType; /串口数据结构typedef struct SerialNetProtounsigned long PacketSize; /包总长度,不包括本身字段ProtocolType NetState; /协议包类型PacketDataType DataType; /数据类型unsigned long SourcedAddr; /数据包源地址unsigned long DestinationAddr; /数据包目的地址unsigned long DataLength; /包的数据段长度unsigned long Offset; / 数据在整个包中的偏移地址PacketHead;int DataLen = 100;char *pBuf = new charDataLen;strcpy(pBuf,Hello World!);DataLen = strlen(pBuf);PacketHead Myhead;Myhead.DestinationAddr = 11;Myhead.SourcedAddr = 10;Myhead.DataType = Attemper_Command;Myhead.DataLength = DataLen;Myhead.NetState = PACKET;Myhead.PacketSize = sizeof(PacketHead) - sizeof(unsigned long);Myhead.Offset = sizeof(Myhead.DestinationAddr) +sizeof(Myhead.SourcedAddr) + sizeof(Myhead.DataType) +sizeof(Myhead.DataLength) + sizeof(Myhead.NetState) + sizeof(Myhead.PacketSize);char *pSendBuffer = new charsizeof(Myhead)+DataLen+ 4;/发送的数据memcpy(pSendBuffer,#,2);/包头标志memcpy(pSendBuffer+2,(char*)&Myhead,sizeof(Myhead);/包头memcpy(pSendBuffer+2+sizeof(Myhead),pBuf,DataLen);/数据memcpy(pSendBuffer+2+sizeof(Myhead)+DataLen,2);/包尾标志【第七步】发送数据DWORD dwError;/DWORD dwWantSend = 100;DWORD dwRealSend = 0;char* pReadBuf = NULL;if (ClearCommError(m_hCom,&dwError,NULL)PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);coutPurgeComm OK!if (!WriteFile(m_hCom,pSendBuffer,sizeof(Myhead)+DataLen+ 4,&dwRealSend,&wrOverlapped)if (GetLastError() = ERROR_IO_PENDING)while (!GetOverlappedResult(m_hCom,&wrOverlapped,&dwRealSend,FALSE)if (GetLastError() = ERROR_IO_INCOMPLETE)/cout写未完成,继续!continue;elsecout发生错误,尝试恢复!ClearCommError(m_hCom,&dwError,NULL);break;【第八步】数据接收DWORD dwError;DWORD dwWantRead = 100;DWORD dwRealRead = 0;char* pReadBuf = new char100;if (ClearCommError(m_hCom,&dwError,NULL)PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);coutPurgeComm OK!if(!ReadFile(m_hComm,pReadBuf,dwWantRead,&RealRead,&wrOverlapped)if(dwError = GetLastError()=ERROR_IO_PENDING)While(GetOverlappedResult(m_hComm,&wrOverlapped,&dwRealRead,FALSE)/对接收到的数据进行数据解析,处理/【第九步】.coutdwRealRead = 【第九步】数据解析(数据解包处理)#define MAX_SERIAL_BUFFER 4096BOOL CanGetFullFrame(char* pReadBuf,int& dwRealRead)static char BufMAX_SERIAL_BUFFER*2;/自定义一个数据缓冲区static unsigned long nFrameStart = 0;/数据祯的开始位置static unsigned long nFrameEnd = 0;/数据祯的结束位置static unsigned long nCurrectPos = 0;/指针当前位置char *pdest = NULL;if (pReadBuf & (dwRealRead!= 0)memcpy(&BufnCurrectPos,pReadBuf,dwRealRead);nCurrectPos = nCurrectPos + dwRealRead;/更新当前位置/查找数据祯的开始标志pdest = (char*)Find(Buf,#,MAX_SERIAL_BUFFER*2,2);if (pdest)nFrameStart = unsigned long(pdest - Buf);/找到数据祯的开始位置else/没有找到开始祯标志#Buf0 = BufnCurrectPos;/丢弃数据nFrameStart = 0;return FALSE;/查找数据祯的结尾标志pdest = (char*)Find(Buf,MAX_SERIAL_BUFFER*2,2);if (pdest)nFrameEnd = unsigned long (pdest - Buf+2);dwRealRead= nFrameEnd - nFrameStart;memcpy(pReadBuf,&BufnFrameStart,dwRealRead);nFrameStart = nFrameEnd;/指向下一帧的开始位置nCurrectPos = nCurrectPos - dwRealRead;/修正nCurrentPos值memcpy(Buf,&BufnFrameEnd,nCurrectPos);/向前移动数据return TRUE;elsereturn FALSE;/一个在内存块中查找指定字符串的函数void* Find(const char *pSour,const char *pDest,int SourLen,int DestLen)int i = 0, j = 0;while(i SourLen & j DestLen)if(*(pSour + i) = *(pDest + j)i+;j+;elsei =i - j + 1;j = 0;if(j = DestLen)return (void*)(pSour + (i - DestLen);elsereturn NULL;【第十步】重新投递Overlapped,略.注:/VC实现串口通信例程作者:阮帮秋(2001.4) 摘要:WIN95界面下的VC+串口通讯程序在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是文件,串行口也不例外也是作为文件来进行处理的。关键词串行口,DWORD,缓冲区 WIN95界面下的VC+串口通讯程序在WIN32下是不建议对端口进行操作的,在WIN32中所有的设备都被看成是文件,串行口也不例外也是作为文件来进行处理的。这是我的一份关于串口编程的读书笔记,对于使 用VC进行编程的同行应该有一定的帮助。1.打开串口:在Window 95下串行口作为文件处理,使用文件操作对串行口进行处理。使用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 dwCreationDistribution, / how to createDWORD dwFlagsAndAttributes, / file attributesHANDLE hTemplateFile / handle to

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论