数据发送
数据发送利用WriteFile函数实现。对于同步I/O操作,它的最后一个参数可为NULL;而对异步I/O操作,它的最后一个参数必需是一个指向OVERLAPPED结构的指针,通过OVERLAPPED结构来获得当前的操作状态。
BOOL WriteComm(LPCVOID lpSndBuffer,DWORD dwBytesToWrite) { //lpSndBuffer为发送数据缓冲区指针, dwBytesToWrite为将要发送的字节长度 //设备已打开 BOOL bWriteState; //实际发送的字节数 DWORD dwBytesWritten; //设备未打开 if(!bOpen) return FALSE; bWriteState=WriteFile(hComDev,lpSndBuffer, dwBytesToWrite,&dwBytesWritten,NULL); if(!bWriteState || dwBytesToWrite!=dwBytesWritten) //发送失败 return FALSE; else //发送成功 return TRUE; } |
数据接收
接收数据的任务由ReadFile函数完成。该函数从串口接收缓冲区中读取数据,读取数据前,先用ClearCommError函数获得接收缓冲区中的字节数。接收数据时,同步和异步读取的差别同发送数据是一样的。
DWORD ReadComm(LPVOID lpInBuffer,DWORD dwBytesToRead) { //lpInBuffer为接收数据的缓冲区指针, dwBytesToRead为准备读取的数据长度(字 节数) //串行设备状态结构 COMSTAT ComStat; DWORD dwBytesRead,dwErrorFlags; //设备未打开 if(!bOpen) return 0; //读取串行设备的当前状态 ClearCommError(hComDev,&dwErrorFlags,&ComStat); //应该读取的数据长度 dwBytesRead=min(dwBytesToRead,ComStat.cbInQue); if(dwBytesRead>0) //读取数据 if(!ReadFile(hComDev,lpInBuffer,dwBytesRead,&dwBytesRead,NULL)) dwBytesRead=0; return dwBytesRead; } |
事件监视线程
事件监视线程对串口事件进行监视,当监视的事件发生时,监视线程可将这个事件发送(SendMessage)或登记(PostMessage)到对事件进行处理的窗口类(由pParam指定)中。
UINT CommWatchProc(LPVOID pParam) { DWORD dwEventMask=0; //发生的事件; while(bOpen) { //等待监视的事件发生 WaitCommEvent(hComDev, &dwEventMask, NULL); if ((dwEventMask & EV RXCHAR) == EV RXCHAR) ……//接收到字符事件后,可以将此消息登记到由pParam有指定的窗口类中进行处理 if(dwEventMask & EV ERR)==EV ERROR) ……//发生错误时的处理 } SetEvent(hEvent); //发信号,指示监视线程结束 return 0; } |
关闭串行设备
在整个应用程序结束或不再使用串行设备时,应将串行设备关闭,包括取消事件监视,将设备打开标志bOpen置为FALSE以使事件监视线程结束,清除发送/接收缓冲区和关闭设备句柄。
void CloseSynComm() { if(!bOpen) return; //结束事件监视线程 bOpen=FALSE; SetCommMask(hComDev,0); //取消事件监视,此时监视线程中的WaitCommEvent将返回 WaitForSingleObject(hEvent,INFINITE); //等待监视线程结束 CloseHandle(hEvent); //关闭事件句柄 //停止发送和接收数据,并清除发送和接收缓冲区 PurgeComm(hComDev,PURGE TXABORT| PURGE RXABORT|PURGE TXCLEAR| PURGE RXCLEAR); //关闭设备句柄 CloseHandle(hComDev); } |
小 结
以上给出了用Win32 API 设计串行通信的基本思路,对这个同步I/O操作的串行通信程序稍加改造就可进行异步I/O操作。在实际应用中,我们可以将这些串行通信函数和成员变量加到一个已有的CWnd类或其派生类中来实现串行通信,也可设计一个新的串行通信类来包含这些成员函数和成员变量。总之,利用Win32 API可以设计出满足各种需要的串行通信程序。 |