设为首页 加入收藏

TOP

13.5.3 读写串口(2)
2013-10-07 14:36:41 来源: 作者: 【 】 浏览:48
Tags:13.5.3 读写 串口

13.5.3  读写串口(2)

(2)同步写串口示例代码如下:

  1. 01  bool WriteCom(char *str, int len)  
  2. 02  {  
  3. 03      DWORD dwBytesWriten = 0;                    //写入的字节数  
  4. 04      COMSTAT ComStat;  
  5. 05      DWORD dwErrorFlags;  
  6. 06      BOOL bWriteStat;  
  7. 07      ClearCommError( hCom, &dwErrorFlags, &ComStat);  
  8. 08      bWriteStat=WriteFile( hCom, str, len, &dwBytesWriten, NULL);  
  9. 09      if( !bWriteStat )  
  10. 10      {   //写串口失败  
  11. 11          AfxMessageBox(  "写串口失败!  ");  
  12. 12          return false;  
  13. 13      }  
  14. 14      PurgeComm( hCom,  
  15. 15                  PURGE_TXABORT| PURGE_RXABORT| PURGE_TXCLEAR|   
  16. 16                  PURGE_RXCLEAR);         //清空读写缓冲区  
  17. 17  } 

异步读写串口的实现就比较灵活了,既可以实现非阻塞读写,也可以实现阻塞读写。有两种方法可以等待操作完成而实现阻塞读写。

用像WaitForSingleObject()等待函数一样来等待OVERLAPPED结构的hEvent成员。

调用GetOverlappedResult()函数等待,后面将演示说明。

在OVERLAPPED结构中包含了重叠I/O的一些信息,定义如下:

  1. typedef struct _OVERLAPPED  
  2. {         
  3. DWORD  Internal;        //操作系统保留,指出一个和系统相关的状态  
  4. DWORD  InternalHigh;    //指出发送或接收的数据长度  
  5. DWORD  Offset;          //文件传送的开始位置  
  6. DWORD  OffsetHigh;      //文件传送的字节偏移量的高位字  
  7. HANDLE  hEvent;         //指定一个I/O操作完成后触发的事件  
  8. }OVERLAPPED; 

在使用ReadFile()或WriteFile()函数进行异步重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEvent。hEvent是读写事件。当串口使用异步通信时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。当调用ReadFile()或WriteFile()函数的时候,该成员会自动被置为无信号状态;当重叠操作完成后,该成员变量会自动被置为有信号状态。

GetOverlappedResult()函数返回重叠操作的结果,通过判断OVERLAPPED结构中的hEvent是否被置位,来判断异步操作是否完成,函数原型如下:

  1. BOOL GetOverlappedResult(     
  2.     HANDLE  hFile,                      //串口的句柄  
  3.     LPOVERLAPPED  lpOverlapped,         //重叠操作开始时指定的OVERLAPPED结构  
  4.     LPDWORD  lpNumberOfBytesTransferred,//实际读写操作传输的字节数  
  5.     BOOL  bWait                         //用于指定函数是否一直等到重叠操作结束  
  6. ); 

在异步操作前应先使用ClearCommError()函数获取尚未读取的字节数,函数的原型如下:
  1. BOOL ClearCommError(      
  2.     HANDLE   hFile,         //串口句柄  
  3.     LPDWORD  lpErrors,  //指向接收错误码的变量  
  4.     LPCOMSTAT lpStat    //指向通信状态缓冲区  
  5. ); 

根据以上信息给出异步读串口的示例代码如下:
  1. 01  bool ReadCom(char * str, DWORD *len)  
  2. 02  {  
  3. 03      COMSTAT        ComStat;  
  4. 04      DWORD          dwErrorFlags;  
  5. 05      OVERLAPPED     m_osRead;  
  6. 06      memset(&m_osRead,0,sizeof(OVERLAPPED));  
  7. 07      m_osRead.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);    //创建事件  
  8. 08      ClearCommError(hCom,&dwErrorFlags,&ComStat);      
  9. 09      dwBytesRead=min(len,(DWORD)ComStat.cbInQue); //获取尚未读取的字节数  
  10. 10      if(!dwBytesRead)  
  11. 11          return FALSE;  
  12. 12      BOOL bReadStatus;  
  13. 13      bReadStatus=ReadFile(hCom,str,len,&len,&m_osRead);  
  14. 14      if(!bReadStatus)                               //读取失败  
  15. 15      {  
  16. 16          if(GetLastError()==ERROR_IO_PENDING)  
  17. 17          {   //串口正在进行读操作  
  18. 18              //等到读操作完成或延时已达到2秒钟  
  19. 19              WaitForSingleObject(m_osRead.hEvent,2000);  
  20. 20              PurgeComm(hCom, PURGE_TXABORT|  
  21. 21                              PURGE_RXABORT|PURGE_TXCLEAR|  
  22. 22                              PURGE_RXCLEAR);        //清空串口缓冲  
  23. 23          }  
  24. 24          return false;  
  25. 25      }  
  26. 26      PurgeComm(hCom, PURGE_TXABORT|PURGE_RXABORT|  
  27. 27                      PURGE_TXCLEAR|PURGE_RXCLEAR); //清空串口缓冲  
  28. 28      return true;  
  29. 29  } 

【代码解析】

第9行获取将要读取的字节数。第13行读取数据。第14行判断读取是否成功,如不成功则在第13~26行进行错误处理。最后在第26、27行清空串口缓冲区。


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇13.2 图标工具栏 下一篇13.5.3 读写串口(1)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: