CreateFile系类异步、并行(同一个串口发送接收)

944 阅读2分钟

  在Windows系统下,串口数据收发CreateFile系类方法对于我来说是最好用的方法,采用异步机制保证了串口读或写入不会使代码停在串口函数内(停在串口函数内原因可能是串口线的原因,或者串口没打开(这个是猜测)),并且可以达到同一个串口既发送并接收(测试方法:串联串口线)。

下面说下CreateFile函数串口创建打开、初始化串口以及串口关闭:

  函数定义如下:

WINBASEAPI
__out
HANDLE
WINAPI
CreateFile(
    __in     LPCWSTR lpFileName,
    __in     DWORD dwDesiredAccess,
    __in     DWORD dwShareMode,
    __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
    __in     DWORD dwCreationDisposition,
    __in     DWORD dwFlagsAndAttributes,
    __in_opt HANDLE hTemplateFile
    );

  函数使用如下:

 串口异步打开:
    
	m_hWriteFile = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
	if ((HANDLE)0 == m_hWriteFile || (HANDLE)-1 == m_hWriteFile)
	{
			MessageBox("没有打开串口,或者串口被占用!");
	}

 串口初始化配置:
  SetupComm(m_hWriteFile,4096,1);//设置输入输出缓冲区
			DCB dcb;
			GetCommState(m_hWriteFile,&dcb);
			dcb.BaudRate = 115200;//比特率
			dcb.ByteSize = 8;
			dcb.Parity = NOPARITY;
			dcb.StopBits = /*TWOSTOPBITS*/ONESTOPBIT;//停止位
			SetCommState(m_hWriteFile,&dcb);//设置串口状态
			PurgeComm(m_hWriteFile,PURGE_TXCLEAR | PURGE_RXCLEAR);

  串口关闭:
  if ((HANDLE)0 != m_hWriteFile && (HANDLE)-1 != m_hWriteFile)
		{
			CloseHandle(m_hWriteFile);
			m_hWriteFile = NULL;
		}

下面说下WriteFile异步写入串口数据方法:   函数定义如下:

WINBASEAPI
BOOL
WINAPI
WriteFile(
    __in        HANDLE hFile,
    __in_bcount_opt(nNumberOfBytesToWrite) LPCVOID lpBuffer,
    __in        DWORD nNumberOfBytesToWrite,
    __out_opt   LPDWORD lpNumberOfBytesWritten,
    __inout_opt LPOVERLAPPED lpOverlapped
    );

  函数使用如下:

OVERLAPPED ov;//异步数据储存的结构体
OMSTAT comstat;//串口结构体 ,用来清除串口错误 建议每次写数据前都清除一下
memset(&comstat,0,sizeof(comstat));
ClearCommError(collet->m_hWriteFile,&dwError,&comstat);

DWORD dwBytesRead = 0;
memset(&ov,0,sizeof(OVERLAPPED));
ov.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//创建一个事件
BOOL bGetRead = WriteFile(collet->m_hWriteFile,SendFileStr,1,&dwBytesRead,&ov);
DWORD wait = WaitForSingleObject(ov.hEvent,1000);//设置一个事件超时时间 
if (0 != ov.InternalHigh)//数据实际接收字节数
{
	nGetFilelength -= ov.InternalHigh;
}
else if (0 != dwBytesRead)
{
	nGetFilelength -= dwBytesRead;
}

下面说下ReadFile异步读取串口方法:   函数定义如下:

WINBASEAPI
BOOL
WINAPI
ReadFile(
    __in        HANDLE hFile,
    __out_bcount_part_opt(nNumberOfBytesToRead, *lpNumberOfBytesRead) __out_data_source(FILE) LPVOID lpBuffer,
    __in        DWORD nNumberOfBytesToRead,
    __out_opt   LPDWORD lpNumberOfBytesRead,
    __inout_opt LPOVERLAPPED lpOverlapped
    );

  函数使用如下:

DWORD dwError = 0;
COMSTAT comstat;//串口结构体 用来清除串口错误 ,建议每次读数据时都要先清除一下
memset(&comstat,0,sizeof(comstat));
ClearCommError(collet->m_hWriteFile,&dwError,&comstat);
if (0 == comstat.cbInQue)//判读是否有数据需要接收
{
	continue;
}
DWORD dwBytesRead = 0;
memset(&ov,0,sizeof(OVERLAPPED));
ov.hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);//创建事件
BOOL bGetRead = ReadFile(collet->m_hWriteFile,WriteFileStr,1,&dwBytesRead,&ov);
DWORD wait = WaitForSingleObject(ov.hEvent,1000);//设置事件超时时间
if (0 != ov.InternalHigh)
{
	nWriteTextLen += ov.InternalHigh;
}
else if (0 != dwBytesRead)
{
	nWriteTextLen += dwBytesRead;
}


使用说明:

  1.ReadFile与WriteFile方法使用同一个串口句柄(同一个串口)可以达到同一个串口边发送边接收。

  2.建议每次读或写串口的时候,先清空一下串口错误。

  3.建议专门做个函数用来管理串口的打开与关闭,方便'并行'的使用。

转载地址:CreateFile系类异步、并行(同一个串口发送接收)_大昱的博客-CSDN博客_createfile 异步