在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 异步