Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3966623
  • 博文数量: 408
  • 博客积分: 10227
  • 博客等级: 上将
  • 技术积分: 9820
  • 用 户 组: 普通用户
  • 注册时间: 2009-04-17 21:48
个人简介

非淡泊无以明志,非宁静无以致远

文章存档

2022年(1)

2021年(1)

2020年(2)

2019年(5)

2018年(4)

2017年(3)

2016年(24)

2015年(8)

2014年(7)

2013年(3)

2012年(1)

2011年(23)

2010年(179)

2009年(147)

分类:

2010-01-12 22:31:04

4.2 同步方式读写串口:

下面先例举同步方式读写串口的代码:

//同步读串口

char str[100];

DWORD wCount;//读取的字节数

BOOL bReadStat;

bReadStat=ReadFile(hCom,str,100,&wCount,NULL);

if(!bReadStat)

{

      AfxMessageBox("读串口失败!");

      return FALSE;

}

return TRUE;

//同步写串口

      char lpOutBuffer[100];

      DWORD dwBytesWrite=100;

      COMSTAT ComStat;

      DWORD dwErrorFlags;

      BOOL bWriteStat;

      ClearCommError(hCom,&dwErrorFlags,&ComStat);

      bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL);

      if(!bWriteStat)

      {

             AfxMessageBox("写串口失败!");

      }

      PurgeComm(hCom, PURGE_TXABORT|

             PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

4.3 重叠操作:

操作还未完成函数就返回。

重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。有两种方法可以等待操作完成:一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;另一种方法是调用GetOverlappedResult函数等待,后面将演示说明。

下面我们先简单说一下OVERLAPPED结构和GetOverlappedResult函数:

1) OVERLAPPED结构

OVERLAPPED结构包含了重叠I/O的一些信息,

定义如下: typedef struct _OVERLAPPED { // o 

    DWORD  Internal;

    DWORD  InternalHigh;

    DWORD  Offset;

    DWORD  OffsetHigh;

    HANDLE hEvent;

} OVERLAPPED;

在使用ReadFileWriteFile重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEventhEvent是读写事件。当串口使用异步通讯时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。

当调用ReadFile, WriteFile 函数的时候,该成员会自动被置为无信号状态;当重叠操作完成后,该成员变量会自动被置为有信号状态。

GetOverlappedResult函数

BOOL GetOverlappedResult(

    HANDLE hFile, // 串口的句柄 

     // 指向重叠操作开始时指定的OVERLAPPED结构

    LPOVERLAPPED lpOverlapped, 

     // 指向一个32位变量,该变量的值返回实际读写操作传输的字节数。

    LPDWORD lpNumberOfBytesTransferred, 

     // 该参数用于指定函数是否一直等到重叠操作结束。

    // 如果该参数为TRUE,函数直到操作结束才返回。

    // 如果该参数为FALSE,函数直接返回,这时如果操作没有完成,

    // 通过调用GetLastError()函数会返回ERROR_IO_INCOMPLETE

    BOOL bWait    

   );    

该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。

 

4.4 异步读串口的示例代码:

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_osReadhEvent事件会变为有信号

             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;

5.关闭串口

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

BOOL CloseHandle(

    HANDLE hObject; //handle to object to close

);

阅读(8643) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~