Win32串口编程(2)

 在使用ReadFile和WriteFile重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过


OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEvent。hEvent是读写事件。当串口使用异步通讯


时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。
  当调用ReadFile, WriteFile 函数的时候,该成员会自动被置为无信号状态;当重叠操作完成后,该成员变


量会自动被置为有信号状态。 GetOverlappedResult函数
BOOL GetOverlappedResult(
    HANDLE hFile, // 串口的句柄    
    // 指向重叠操作开始时指定的OVERLAPPED结构
    LPOVERLAPPED lpOverlapped,    
    // 指向一个32位变量,该变量的值返回实际读写操作传输的字节数。
    LPDWORD lpNumberOfBytesTransferred,
    // 该参数用于指定函数是否一直等到重叠操作结束。
    // 如果该参数为TRUE,函数直到操作结束才返回。
    // 如果该参数为FALSE,函数直接返回,这时如果操作没有完成,    // 通过调用GetLastError()函数会


返回ERROR_IO_INCOMPLETE。
    BOOL bWait 
   ); 该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断OVERLAPPED结构中的hEvent是否


被置位来实现的。异步读串口的示例代码: char lpInBuffer[1024];
DWORD dwBytesRead=1024;
COMSTAT ComStat;
DWORD dwErrorFlags;
OVERLAPPED m_osRead;
memset(&m_osRead,0,sizeof(OVERLAPPED));
m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);


ClearCommError(hCom,&dwErrorFlags,&ComStat);
dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
if(!dwBytesRead)
return FALSE;
BOOL bReadStatus;
bReadStatus=ReadFile(hCom,lpInBuffer,
      dwBytesRead,&dwBytesRead,&m_osRead);


if(!bReadStatus) //如果ReadFile函数返回FALSE
{
 if(GetLastError()==ERROR_IO_PENDING)
 //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
 {
  WaitForSingleObject(m_osRead.hEvent,2000);
  //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟
  //当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
  PurgeComm(hCom, PURGE_TXABORT|
   PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
  return dwBytesRead;
 }
 return 0;
}
PurgeComm(hCom, PURGE_TXABORT|
    PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
return dwBytesRead;


  对以上代码再作简要说明:在使用ReadFile 函数进行读操作前,应先使用ClearCommError函数清除错误。


ClearCommError函数的原型如下: BOOL ClearCommError(


    HANDLE hFile, // 串口句柄
    LPDWORD lpErrors, // 指向接收错误码的变量
    LPCOMSTAT lpStat // 指向通讯状态缓冲区
   );


该函数获得通信错误并报告串口的当前状态,同时,该函数清除串口的错误标志以便继续输入、输出操作。
参数lpStat指向一个COMSTAT结构,该结构返回串口状态信息。 COMSTAT结构 COMSTAT结构包含串口的信息,结


构定义如下: typedef struct _COMSTAT { // cst 
    DWORD fCtsHold : 1;   // Tx waiting for CTS signal
    DWORD fDsrHold : 1;   // Tx waiting for DSR signal
    DWORD fRlsdHold : 1;  // Tx waiting for RLSD signal
    DWORD fXoffHold : 1;  // Tx waiting, XOFF char rec'd
    DWORD fXoffSent : 1;  // Tx waiting, XOFF char sent
    DWORD fEof : 1;       // EOF character sent
    DWORD fTxim : 1;      // character waiting for Tx
    DWORD fReserved : 25; // reserved
    DWORD cbInQue;        // bytes in input buffer
    DWORD cbOutQue;       // bytes in output buffer
} COMSTAT, *LPCOMSTAT;


本文只用到了cbInQue成员变量,该成员变量的值代表输入缓冲区的字节数。  最后用PurgeComm函数清空串口


的输入输出缓冲区。 这段代码用WaitForSingleObject函数来等待OVERLAPPED结构的hEvent成员,下面我们再演


示一段调用GetOverlappedResult函数等待的异步读串口示例代码:


char lpInBuffer[1024];
DWORD dwBytesRead=1024;
 BOOL bReadStatus;
 DWORD dwErrorFlags;
 COMSTAT ComStat;
OVERLAPPED m_osRead;


 ClearCommError(hCom,&dwErrorFlags,&ComStat);
 if(!ComStat.cbInQue)
  return 0;
 dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);
 bReadStatus=ReadFile(hCom, lpInBuffer,dwBytesRead,
  &dwBytesRead,&m_osRead);
 if(!bReadStatus) //如果ReadFile函数返回FALSE
 {
  if(GetLastError()==ERROR_IO_PENDING)
  {
   GetOverlappedResult(hCom,
    &m_osRead,&dwBytesRead,TRUE);
           // GetOverlappedResult函数的最后一个参数设为TRUE,
           //函数会一直等待,直到读操作完成或由于错误而返回。


   return dwBytesRead;
  }
  return 0;
 }
 return dwBytesRead;


异步写串口的示例代码: char buffer[1024];
DWORD dwBytesWritten=1024;
 DWORD dwErrorFlags;
 COMSTAT ComStat;
OVERLAPPED m_osWrite;
 BOOL bWriteStat;


 bWriteStat=WriteFile(hCom,buffer,dwBytesWritten,
  &dwBytesWritten,&m_OsWrite);
 if(!bWriteStat)
 {
  if(GetLastError()==ERROR_IO_PENDING)
  {
   WaitForSingleObject(m_osWrite.hEvent,1000);
   return dwBytesWritten;
  }
  return 0;
 }
 return dwBytesWritten;


(4)、关闭串口
  利用API函数关闭串口非常简单,只需使用CreateFile函数返回的句柄作为参数调用CloseHandle即可:


BOOL CloseHandle(
    HANDLE hObject; //handle to object to close
);


串口编程的一个实例
  为了让您更好地理解串口编程,下面我们分别编写两个例程(见附带的源码部分),这两个例程都实现了工控


机与百特显示仪表通过RS485接口进行的串口通信。其中第一个例程采用同步串口操作,第二个例程采用异步串口


操作。
  我们只介绍软件部分,RS485接口接线方法不作介绍,感兴趣的读者可以查阅相关资料。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值