用Visual C++编制串行通信程序.docx

上传人:赵** 文档编号:50933297 上传时间:2022-10-16 格式:DOCX 页数:8 大小:27.76KB
返回 下载 相关 举报
用Visual C++编制串行通信程序.docx_第1页
第1页 / 共8页
用Visual C++编制串行通信程序.docx_第2页
第2页 / 共8页
点击查看更多>>
资源描述

《用Visual C++编制串行通信程序.docx》由会员分享,可在线阅读,更多相关《用Visual C++编制串行通信程序.docx(8页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。

1、用Visual C+编制串行通信程序摘要: 本文介绍了在Win32环境下用Visual C+的MFC实现串行通信方法,用类实现多线程编程,较好地将32位串口通信的API函数封装在一个类中实现串行通信,并给出示例程序。关键词:串行通信多线程 Visual C+ MFC随着计算机应用深入,经常需要通过计算机RS-232串口与外部设备通信,采集如温度、压力、重量等模拟数据,或发出控制信息,用Visual C+编制串行通信程序可有三种方法:1、采用Microsoft Win32应用程序编程接口(API)所提供串行通信函数,用SDK思路编写。2、用ActiveX通讯控件开发串行通信程序。3、用C+的MF

2、C思路,将Win32串口通信的API函数封装在一个类中实现串行通信。前两种方法己有不少刊物已作过介绍,方法各有利弊,而第三种方法较为繁琐,不仅要了解Win32位串行通信的API函数,还要掌握多线程编程,但控制灵活,既涉及到底层编程、纠错能力强,又有C+风格,为专业C+开发人员所采用。本文就在Win32环境下串行通信、多线程编程概念作简单叙述,并给出相应的示例程序,以供参考。一、串口通信1串口通信步骤 :一般编制串行通信程序分四个部分:A 打开串行端口:打开通信资源,设置通信参数、设置通信事件、创建读、写事件、进入等待串口消息循环。B 读取串行端口信息,当串口发生EV_RXCHAR(接收到字符并

3、放入了输入缓冲区)消息后读取串口、数据传输错误处理、字符串处理如回车符、空格并相应转化成数据,如果模拟量还要进行数据检验等功能。C 写串行端口信息:将要发送的信息写入串口,相应进行错误处理。D 断开串行端口连接:关闭事件,清除通信事件,丢弃通信资源并关闭。2 串口通信函数在Win32环境下,由于Windows禁止应用程序直接和硬件打交道,所以程序员只能用Win32API提供的串行通信函数与串行端口打交道,主要函数有:打开、关闭通信资源CreateFile();CloseHandle( );设置通信资源SetCommState(()等待串口事件WaitCommEvent()创建、关闭事件对象 C

4、reateEvent();CloseHandle()串口读写ReadFile(),WriteFile()以上函数具体如何使用见示例或联机帮助。在Windows3.1-16位通信函数有一个WMCOMMNOTIFY消息,每当发生一个串行端口事件,通信设备驱动器就发送此消息,以便程序读、写串信端口,在Win32中已被取消,而串行端口事件(特别接收串口数据)与外部设备有关,计算机要保证及时接收数据又不使主程序暂停,就要引入多线程编程。3 多线程现实生活中,许多事情都时同时进行的,在我们设计应用程序时,也就常常需要采用并行编程机制多线程,在本示例中,主线程负责创建子线程、向串口发送信息,子线程等待串口E

5、V_RXCHAR(收到字符放入缓冲区)事件,读取缓冲区字符并显示。一般MFC将线程分两类:用户界面线程和工作者线程,工作者线程没有消息循环,只是一般函数,本示例中采用是用户界面线程,其实现方法为:4从CWinThread派生新的子类。必须用宏DECLARE_DYNCREATE()和IMPLEMENT_DYNCREATE声明和实现CwinThread5 在CwinThread派生类覆盖以下函数。. InitInstance:执行线程实例的初始化。. ExitInstance:在线程终止时执行清理工作。. Run:控制线程的函数,包含消息循环。.OnIdle:执行线程的空闭处理。a)调用全局函数A

6、fxBeginThread启动用户界面线程。此时,采用以下原型:CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );其中,参数pThreadClass为从CWinThread派生类对象的RUNTIME_CLASS宏调用;nPriority用于指定线程优先级(可选)可以调用A

7、PI函数SetThreadPriority设置优先级;nStackSize用于指定线程的堆栈大小;dwCreateFlags为控制线程创建的附加标记,如果为CREATE_SUSPENDED,则创建线程为挂起状态,必须调用成员函数ResumeThread恢复;lpSecurityAttrs用于指定安全属性。要保证线程之间数据正常传输,还要涉及线程间通信、线程间同步等内容,有兴趣读者可参阅有关资料。6 串行通信程序流程左边是主线程,右边为子线程。实线框为视类函数,虚线为通信类函数响应菜单“打开串口”启动用户界面线程(挂起状态)打开通信资源,串口参数设置构造通信类初始化启动子线程等待串口事件显示接收

8、的数据读串口数据EV_RXCHAR连接标记控制线程函数RUN创建读、写串口事件断开关闭事件子线程结束子线程开始运行断开线程终止(获取退出码)连接标记“断开”向串口发送空事件关闭串口响应菜单“关闭串口”响应菜单“发送数据”写数据到串口7 示例程序编制a)建工程文件ComTest打开VisualC+5.0(6.0),利用MFC AppWizard新建ComTest工程文件,选中单文档,其余为缺省值。并在视类建立“串口测试”下拉菜单项,包括“打开串口”、“关闭串口”和“写串口测试”三项菜单。b)建立串口通讯类选择“Insert”菜单项中“New Class”弹出“建新类”对话框,输入类名为“Ccom

9、CUnic”选中CwinThread为基类,并相应编写如下函数/线程循环主函数,当线程被启动执行int CcomCUnic:Run() DWORD dwEvtMask ;int nLength ;BYTE abIn 80 ;/创建事件句柄osRead.hEvent= CreateEvent( NULL, TRUE, FALSE, NULL ) ;if (osRead.hEvent = NULL)AfxMessageBox( NULL, 建立事件失败!) ;return ( FALSE ) ;/设置串口 “收到字符放入缓冲区”事件if (!SetCommMask(COMFile, EV_RXCH

10、AR ) return ( FALSE )/bCONNECTED串口连接标记while ( bCONNECTED )dwEvtMask = 0 ;/等待串口事件WaitCommEvent( COMFile, &dwEvtMask, NULL );if (dwEvtMask & EV_RXCHAR) = EV_RXCHAR)do/读取串口字符nLength=ReadCommBlock( (LPSTR)abIn );/输出接收字符if(nLength0)pView-OutChar(LPSTR)abIn,nLength);while ( nLength 0 ) ;/子线程结束CloseHandle(

11、 osRead.hEvent ) ;return CWinThread:Run();/打开串行端口,设置端口参数,被视类“打开串口”调用BOOL CcomCUnic:OpenConnection( ) BYTE bSet;DCB dcb ; BOOL fRetVal ;COMMTIMEOUTS CommTimeOuts;if (COMFile=CreateFile( COM1, GENERIC_READ | GENERIC_WRITE,/可读、可写0, / 不共享NULL, / 无安全描OPEN_EXISTING,/打开已存在文件FILE_ATTRIBUTE_NORMAL |FILE_FLAG

12、_OVERLAPPED, / 文件属性NULL ) = (HANDLE) -1 )return ( FALSE ) ;/ 指定监视事件_收到字符放入缓冲区SetCommMask( COMFile, EV_RXCHAR ) ;/ 设置缓冲区SetupComm( COMFile,4096,4096) ;/ 刷清缓冲区PurgeComm( COMFile, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ;meOuts.ReadIntervalTimeout = 0xFFFFFFFF ;CommTimeOuts.ReadT

13、otalTimeoutMultiplier = 0 ;CommTimeOuts.ReadTotalTimeoutConstant = 1000 ;CommTimeOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600/9600 ;CommTimeOuts.WriteTotalTimeoutConstant = 0 ;/给定串口读与操作限时SetCommTimeouts( COMFile, &CommTimeOuts ) ;/设置串口参数:波特率=9600;停止位 1个;无校验;8位dcb.DCBlength = sizeof( DCB ) ;GetCommS

14、tate( COMFile, &dcb ) ;dcb.BaudRate =CBR_9600;dcb.StopBits =ONESTOPBIT;dcb.Parity = NOPARITY;dcb.ByteSize=8;dcb.fBinary=TRUE;dcb.fOutxDsrFlow = 0 ;dcb.fDtrControl = DTR_CONTROL_ENABLE ;dcb.fOutxCtsFlow = 0 ;dcb.fRtsControl = RTS_CONTROL_ENABLE ;dcb.fInX = dcb.fOutX = 1 ;dcb.XonChar = ASCII_XON ;dcb.

15、XoffChar = ASCII_XOFF ;dcb.XonLim = 100 ;dcb.XoffLim = 100 ;dcb.fBinary = TRUE ;dcb.fParity = TRUE ;/根据设备控制块配置通信设备fRetVal = SetCommState( COMFile, &dcb ) ;if(!fRetVal) return FALSE; /指定串口执行扩展功能EscapeCommFunction( COMFile, SETDTR ) ;return TRUE ;/关闭串行端口BOOL CcomCUnic:CloseConnection()bCONNECTED = FAL

16、SE ;/禁止串行端口所有事件SetCommMask( COMFile, 0 ) ;/清除数据终端就绪信号EscapeCommFunction( COMFile, CLRDTR ) ;/丢弃通信资源的输出或输入缓冲区字符并终止在通信资源上挂起的读、写操/场作PurgeComm( COMFile, PURGE_TXABORT | PURGE_RXABORT |PURGE_TXCLEAR | PURGE_RXCLEAR ) ;CloseHandle( COMFile );return TRUE;/读串行端口数据-被RUN调用int CcomCUnic:ReadCommBlock(LPSTR lps

17、zBlock)DWORD dwErrorFlags;COMSTAT ComStat ;DWORD dwLength;ClearCommError( COMFile, &dwErrorFlags, &ComStat ) ;dwLength = ComStat.cbInQue;if (dwLength 0)ReadFile( COMFile, lpszBlock, dwLength, &dwLength, &osRead )return ( dwLength ) ;/写数据到串行端口-被视类“发送数据”调用BOOL CcomCUnic:WriteTTYBlock(LPSTR lpBlock, in

18、t nLength )DWORD dwLength;WriteFile( COMFile, lpBlock,nLength, &dwLength, &osRead );return true;a) 编写视类“打开串口”、“关闭串口”和“发送数据”菜单响应函数;/打开串口函数void CComTestView:OnOpenCom() /创建等待线程,因要设置串行端口参数m_pCcomCUnic=(CcomCUnic*)AfxBeginThread(RUNTIME_CLASS(CcomCUnic), THREAD_PRIORITY_NORMAL,0, CREATE_SUSPENDED);if(m_

19、pCcomCUnic=NULL)m_bLineCom=FALSE;else/保存视类指针,显示读取串口的字符用m_pCcomCUnic-pView=this;/打开串口准备读串口m_bLineCom=m_pCcomCUnic-OpenConnection( );/串口初始化,读取串口数据m_pCcomCUnic-bCONNECTED=TRUE; /线程开始执行m_pCcomCUnic-ResumeThread();/发送串口通信DTR信号/EscapeCommFunction(m_pCcomCUnic-COMFile, SETDTR ) ;/关闭串口函数void CComTestView:On

20、CloseCom() DWORDdwStatus;VERIFY(:GetExitCodeThread(m_pCcomCUnic-m_hThread, &dwStatus);m_pCcomCUnic-CloseConnection();/输出字符“Test OK”到串口void CComTestView:OnWriteCom() if(m_pCcomCUnic0)m_pCcomCUnic-WriteTTYBlock(Test OK,7);/显示读取串口的字符void CComTestView:OutChar(LPSTR abIn,int iLength)CClientDC dc(this);dc

21、.TextOut(10,20,abIn,iLength);以上示例输入完后,编译就可运行该程序,可直接与有RS232串口的设备直接相连,并注意与本示例串口设置要一致,也可直接将计算机COM1串口2、3(数据发送、数据接收)两脚相连,执行“打开串口”后,就可读取串口数据,再执行“发送数据”,这时屏幕显示“Test OK”,最后执行“关闭串口”( 注意:“打开串口”与“关闭串口”应为互斥,先执行“打开串口”,才可以执行“关闭串口”)。 本示例仅仅简单说明用MFC类编制串行通信程序,在实际编制时还有增加以下功能1、多线程同步,因子线程读取串行端口数据存放的变量,要被主线程使用,多个线程访问同一内存变量数据,会造成数据存、取错误,解决办法可用互斥信号灯,在MFC类库中,Cmutex封装了互斥信号灯对象,可用此类解决。2、实时错误处理:当计算机实时数据通信时,由于干扰等原因,数据传输可能发生错误时,程序要及时检测错误并清除,才能保证数据正常传输。3、串口参数设置,如COM1COM4, 波特率、停止位、奇、偶校验;停止位等参数,对此感兴趣者,可与本人联系。

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 高考资料

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号© 2020-2023 www.taowenge.com 淘文阁