CreateEvent

CreateEvent 定义:

  1. HANDLE WINAPI CreateEvent(

  2. _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性

  3. _In_ BOOL bManualReset, //设置信号复位方式为自动恢复为无信号状态(FALSE)还是手动恢复为无信号状态(TRUE)

  4. _In_ BOOL bInitialState, //初始状态

  5. _In_opt_ LPCTSTR lpName //信号名称,可以为Null

  6. );

方式一:

hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //复位方式为自动恢复到无信号状态,且初始状态为有信号.

此时当使用如下表达式后:

DWORD dReturn = WaitForSingleObject(hEvent, 等待时间);

hEvent 就会变为无信号状态,如果在某个时候再次需要上面的式子成立并通过,则需要使用下面的语句使其变为有信号状态(此方式只能解锁一个等待线程,如需继续解锁,则需要再次使用下面的式子)

SetEvent(hEvent)

方式二:

hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //复位方式为手动恢复到无信号状态,且初始状态为有信号.

此时当使用如下表达式后:

DWORD dReturn = WaitForSingleObject(hEvent, 等待时间);  

会自动再次变为有信号状态,上面的式子会直接执行并通过(同时有多个等待线程也会直接执行并通过),如果需要将hEvent设置为无信号状态,则需要手动使用下面的语句:

ResetEvent(hEvent);

注:上面的复位方式指的是恢复到无信号状态的方式,若设置为TRUE,则表示需要手动将其置为无信号,若为FALSE,则会自动变为无信号,千万别和信号量变为有信号状态的方式搞混了!


同步I/O方式打开串口的示例代码:

C++代码

  1. HANDLE hCom; //全局变量,串口句柄   
  2. hCom=CreateFile("COM1",//COM1口  
  3.  GENERIC_READ|GENERIC_WRITE, //允许读和写  
  4.  0, //独占方式  
  5.  NULL,  
  6.  OPEN_EXISTING, //打开而不是创建  
  7.  0, //同步方式  
  8.  NULL);   
  9. if(hCom==(HANDLE)-1)   
  10. {  
  11.    AfxMessageBox("打开COM失败!");  
  12.    return FALSE;   
  13. }  
  14. return TRUE;    

       重叠I/O打开串口的示例代码:

C++代码

  1. HANDLE hCom; //全局变量,串口句柄     
  2. hCom =CreateFile("COM1", //COM1口    
  3.  GENERIC_READ|GENERIC_WRITE, //允许读和写    
  4.  0, //独占方式    
  5.  NULL,    
  6.  OPEN_EXISTING, //打开而不是创建     
  7.  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式    
  8.  NULL);     
  9. if(hCom ==INVALID_HANDLE_VALUE)     
  10. {     
  11.    AfxMessageBox("打开COM失败!");     
  12.    return FALSE;     
  13. }     
  14. return TRUE;  

 

在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。
ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;如果未指定重叠标志,则读写操作应该是同步的。ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。
ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。
如果操作成功,这两个函数都返回TRUE。需要注意的是,当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。这说明重叠操作还未完成。

同步方式读写串口比较简单,下面先例举同步方式读写串口的代码: 
//同步读串口

char str[100];

DWORD wCount;//读取的字节数

BOOL bReadStat;

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

if(!bReadStat) {

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

return FALSE;

}

eturn 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);  
在重叠操作时,操作还未完成函数就返回。

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

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

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

BOOL bWait  // 该参数用于指定函数是否一直等到重叠操作结束。 // 如果该参数为TRUE,函数直到操作结束才返回。 // 如果该参数为FALSE,函数直接返回,这时如果操作没有完成, // 通过调用GetLastError()函数会返回ERROR_IO_INCOMPLETE。

);  
该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断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;  

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EmbededCoder

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值