异步方式winAPI串口通信
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
使用winAPI串口通信(二)
分类:Windows转载2009-09-23 16:51 263人阅读评论(0) 收藏举报
采用同步方式的查询方式读取串口数据时,若由于串口操作耗费较长的时间,则程序会被挂起.为解决这种问题,可以在读取数据时采用重叠I/O操作.此时,读写数据的操作在单独的线程中进行,发出读写要求的主线程可以继续运行.当读写数据成功后,读写数据线程可以通过某种方式通知主线程.两个线程协调工作 ,可以明显提高程序的效率.
为了实现重叠I/O操作,主要有如下几个编程步骤: 定义全局变量、创建串口、发出读写操作、读写线程函数的建立、关闭串口等.
1. 定义全局变量
HANDLE hCom; //串口句柄
DWORD ThreadProcWrite(LPVOID pParam); //写线程函数
DWORD ThreadProcRead(LPVOID pParam); //读线程函数
OVERLAPPED Wol = { 0 }; //写操作OVERLAPPED结构变量
OVERLAPPED Rol = { 0 }; //读操作OVERLAPPED结构变量
HANDLE hThreadWrite; //写线程句柄
HANDLE hThreadRead; //读线程句柄
HWND hWnd; //窗口句柄
2. 创建串口
hCom = CreateFile ( "COM2",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,//使用重叠方式
NULL );
if( hCom != INVALID_HANDLE_VALUE)
{
SetupComm(hCom,1024,512);
DCB myDCB;
GetCommState( hCom,&myDCB);
myDCB.BaudRate=CBR_19200;
myDCB.fBinary=TRUE;
myDCB.fParity=TRUE;
myDCB.ByteSize=8;
myDCB.Parity=ODDPARITY;
myDCB.StopBits=ONESTOPBIT;
SetCommState(hCom,&myDCB);
}
else
{
AfxMessageBox("创建串口失败!");
}
hWnd = GetSafeHwnd(); //获取当前窗口的句柄
3. 发出读写操作
(1) 读操作
在读操作中,只是启动读线程.实际的读操作在读线程函数中完成.
DWORD dwThreadID;
DWORD dwParam;
hThreadRead = CreateThread ( NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadProcRead,
&dwParam,
0, //创建线程后,立即执行该线程
&dwThreadID);
if(hThreadRead==NULL)
{
AfxMessageBox("读线程创建失败!");
}
CreateThread()函数用于创建一个线程.
HANDLE CreateThread (
//线程安全属性,NULL表示该线程不能被继承
LPSECURITY_ATTRIBUTES lpThreadAttributes,
//初始化栈大小.0表示默认值或按调用栈线程配置
DWORD dwStackSize,
//执行函数名称
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, //向新线程传递的参数
DWORD dwCreationFlags, //创建标志.0表示创建后立即执行
LPDWORD lpThreadId
);
(2) 写操作
在写操作中,同样只是启动写线程.实际的写操作在写线程函数中完成.
DWORD dwThreadID;
DWORD dwParam;
hThreadWrite = CreateThread( NULL,
0,
(LPTHREAD_START_ROUTINE)ThreadProcWrite,
&dwParam,
0,
&dwThreadID);
if(hThreadWrite==NULL)
{
AfxMessageBox("写线程创建失败!");
}
4.读写线程函数的建立
读写的实际操作在读写线程函数中执行. 这两个函数都是全局函数.
(1) 读线程函数
在读线程函数中,首先应初始化重叠结构Rol的成员hEvent,将其设置为无信号状态.当读操作完成或出现通信错误时,该变量会被自动设置为有信号状态.接下来就可以使用ReadFile()函数发出读命令.若该读函数返回TRUE,说明读操作已经完成,可以处理读取的数据.若该读函数返回FALSE,说明读操作未完成.此时使用WaitForSingleObject()函数等待读操作的结构。根据返回结果的不同,采取相应的处理代码即可.
DWORD ThreadProcRead(LPVOID pParam)
{
BYTE myByte[20];
CString myStr;
DWORD dwRes;
DWORD dwRead;
BOOL fRes;
char myChar[10];
Rol.hEvent = CreateEvent ( NULL, //创建Rol的hEvent成员为无信号状态
TRUE;
FALSE;
NULL);
if (Rol.hEvent == NULL)
{
AfxMessageBox ("hEvent 空");