基于多线程技术的串口通信的设计与研究

  • 格式:doc
  • 大小:30.00 KB
  • 文档页数:5

基于多线程技术的串口通信的设计与研究摘要本文以VC++ 6.0为开发平台,讲述了如何使用32位的Windows API 串口通信函数,编程实现高效的多线程全双工串口通信,并在阐述中给出了相关函数或代码。

实验证明,该方法有着较好的灵活性、可靠性与高效性。

关键词VC++;串口通信;多线程;重叠I/O0 引言串口是常用的计算机与外部设备之间的数据传输通道,由于使用其通信方便易行,且能实现数据的长远距离传输,故应用极其广泛。

为此,根据不同的使用环境灵活地编写出串口通信处理程序是必要的工作。

在Windows上,微软专门提供了相应的文件I/O函数和通信函数,以方便我们编写出所需的串口通信程序。

目前,实现串口通信的方法有两种。

第一种,使用VC++提供的串口通信控件MSComm;第二种,使用32位的API 通信函数。

本文采用了第二种方法,且结合多线程技术,实现了更加灵活的串口通信程序设计。

1 编程实现过程1.1 初始化端口在Windows操作系统中,串行口是被作为文件来进行处理的,而不是直接对端口进行操作,为此我们使用某一个串口进行通信时,需首先调用API函数CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING ,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,NULL );获取一个串口通信设备句柄hCom。

其中,该函数的第一个参数szPort标识将要开启的端口号,第二个参数规定了端口读写属性,剩下的参数中较重要的是设置FILE_FLAG_OVERLAPPED标识,即开启重叠I/O的方式。

在该模式下,当我们调用读写函数时,即使操作还未完成,被调用的函数也会立即返回,这样费时的I/O操作会在后台进行,使系统在这段时间可以去干别的事情,提高了系统的执行效率,且借用多线程技术还能实现读、写的同时进行。

接下来,需要根据需求,调用SetCommTimeouts(hCom, &m_CommTimeouts);函数,设置COMMTIMEOUTS类型的结构体变量m_CommTimeouts。

更改COMMTIMEOUTS结构体里面的成员变量,可以设置串口读写超时时间,以实现系统若未在指定时间内读出或写入指定数量的字符,就不再继续,立即返回执行下一次的任务。

然后,还需要分别调用SetCommState和SetupComm函数,设置端口的速率、数据位、输入输出缓冲区大小等配置信息。

至此,就完成了串口的初始化并开启操作。

1.2 串口读写的实现1.2.1 多线程全双工通信想要编写高效率的串口通信程序,除了设置重叠I/O外,再结合多线程技术,可以起到更好的效果。

所谓多线程,就是指要计算机并行的处理不同的事情。

在VC 中线程分为用户界面线程和工作者线程,其主要区别是前者能够提供界面和用户的交互,而后者没有界面,用于处理后台任务。

本文在设计通信程序时,建立了两个工作者线程,一个用于不断监视数据的接收,一个用于数据的发送。

这样,使程序实现了收发同时进行的全双工工作方式,在实际应用中更有效率。

另外,值得注意的是使用重叠I/O需要创建OVERLAPPED结构以供读写函数,即ReadFile和WriteFile使用。

而OVERLAPPED结构中最重要的成员是hEvent。

hEvent是一个事件对象句柄,通过CreateEvent函数来创建,被用作线程的同步对象使用。

如果读写函数未完成操作就返回,那么会将hEvent置为无信号状态。

只有操作完成后(包括超时),hEvent才会置为有信号状态,这样我们就可以通过hEvent知晓当前通讯设备的读写状态。

实际程序运行时,若发现读、写函数的返回值为假,由于开启了重叠I/O方式,那么未必是指读写失败,此时需要通过GetLastError函数的返回值做进一步判断。

若返回为ERROR_IO_PENDING,说明当前读或写操作还未完成,这时就可以挂起读、写线程,等待操作完成。

而程序设计时有两种等待方法:一种是用WaitForSingleObject等待函数来等待OVERLAPPED结构体中的成员hEvent为有信号状态;另一种办法是调用GetOverlappedResult函数等待,注意需要将该函数的bWait参数设为TRUE,那么该函数将会一直等待hEvent 事件,直到其有信号才返回。

同时,利用GetOverlappedResult还可以返回一个OVERLAPPED结构体,里面包含有实际发送、接收字节等重叠操作的结果。

下面将分别给出读、写线程的关键代码,并作适当分析。

1.2.2 串口读操作DWORD WINAPI readdata(LPVOID data)/////////////接收数据工作者线程{ CTestDlg *dlg=(CTestDlg *)data;byte *lpBuffer=NULL;DWORD dwError=0;COMSTAT ComStat ;DWORD dwLength; //存储输入缓冲区字节数DWORD dw_Length;//存储实际读到的字节数ClearCommError(dlg->hCom, &dwError, &ComStat ) ;dwLength = ComStat.cbInQue ; //获取输入缓冲区有多少字节数据if (dwLength > 0) //有数据时开始读{ lpBuffer = new byte[dwLength];//申请内存空间,用于存放读到的数据bool fReadStat;//读操作状态fReadStat = ReadFile( dlg->hCom, lpBuffer,dwLength, &dw_Length, &dlg->m_OverlappedRead);if (!fReadStat)//状态为假时{ if (GetLastError() == ERROR_IO_PENDING)//确认读操作是否还未完成{ //挂起该线程,等待数据读完GetOverlappedResult(dlg->hCom, &dlg->m_OverlappedRead, &dw_Length, TRUE );}}CStringstr_t,str_final;for (DWORD i=0;iGetDlgItem(IDC_EDIT_Receive)->SetWindowText(str_final);//以字符串形式显示接收的数据delete []lpBuffer;}return 0;}以上给出的即是接收数据线程的主要代码,由于在实际使用中,我们想实时监控端口的数据输入情况,做到输入缓冲区一有数据传来就立即执行读取操作,故在程序中要建立一个定时器,设定一个监控的时间间隔,定点不断执行以上工作者线程的代码,以实现对端口的监控。

另外,我们在线程中需要使用ClearCommError 函数获取输入缓冲区的数据状态,以判断是否该开始读取数据。

1.2.3 串口写操作DWORD WINAPI writedata(LPVOID data) /////////////发送数据工作者线程{ CTestDlg *dlg=(CTestDlg *)data;BOOL bWriteStat;DWORD dwBytesWritten,dwBytes;// dwBytesWritten记录实际发送字节数,dwBytes记录应发送字节数CString str_data;dlg->GetDlgItemText(IDC_EDIT_Send,str_data);//获取要发送的数据dwBytes=str_data.GetLength();//得到要发送的数据长度char *send_data=new char[dwBytes];send_data=str_data.GetBuffer(0);//将要发送的数据拷贝到以send_data为头指针的内存空间bWriteStat = WriteFile(dlg->hCom, send_data,dwBytes, &dwBytesWritten,&dlg->m_OverlappedWrite );if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) )//写操作还未完成{ if( WaitForSingleObject( dlg->m_OverlappedWrite.hEvent, 2000 ) )//挂起该线程,等待写结束dwBytesWritten = 0; //超时了else //未超时{ GetOverlappedResult( dlg->hCom, &dlg->m_OverlappedWrite, &dwBytesWritten, FALSE );AfxMessageBox(“send ok”);}}str_data.ReleaseBuffer();return 0;}以上所示的数据发送线程,我们只需在想要发送数据时创建、启动线程即可。

2 结论本文描述了在VC++上如何使用Win32 API中相关的通信函数,编程实现串口通讯程序,且采用多线程的程序设计思想,在重叠I/O的方式下,不仅提高了串口通信的效率,而且还实现了收发同时进行的全双工工作方式,为计算机与外部设备通过串口通信提供了更灵活的方案。

参考文献[1]胡春燕.基于VC的串口通信的实现[J].福建电脑, 2005(10).[2]阚能琪. VC ++ 串口通信中多线程技术的应用研究[J]. 西华大学学报:自然科学版,2005,7.[3]孙鑫,余安萍. VC++深入详解[M].北京:电子工业出版社,2006,6.[4]Microsoft Corporation. Microsoft Developer Network Library[DB/DK].Microsoft Corporation,2001.。