APP下载

基于DLL实现上位机与三自由度转台之间的串口通信

2019-02-14史礼婷皮本杰高佳隽李春权

数字通信世界 2019年1期
关键词:主程序调用线程

史礼婷,张 骞,皮本杰,高佳隽,李春权

(1.航天行云科技有限公司,武汉 430040;2.湖北航天科工集团总体设计所,武汉 430040)

1 引言

具有自动、章动、进动的三自由度转台,是飞行器进行动态性能测试的关键设备,广泛应用于各类飞行器模拟试验,特别是研究弹丸或引信在空中的飞行试验,经常需要利用转台进行地面飞行状况的模拟。

在转台的模拟试验中,需要通过计算机良好的人机界面和强大的数据处理功能,对其进行控制。而其他设备与计算机进行数据通信的方法中,串口通信是经常使用的方法之一,它具有实现简单、使用灵活、数据传输可靠等有点,因而应用广泛[1]。

在具体工程实践中,遇到两个较大问题:一是三自由度转台既要实现实时控制,又要周期返回大量状态信息,I/O数据量较大,导致程序处理速度降低。二是由于工程设计需要,转台程序需要在多个系统中复用。

为解决上述问题,本文设计了多线程的处理程序,并将串口和转台之间的通信协议进行了DLL封装,具有以下优点:一是提高内存利用率。采用多线程技术,大大提高程序I/O处理能力,提高工作效率。二是简化主程序开发。将协议解析和使用分开,简化主控制程序的开发工作量。将串口访问、协议解析、组帧等进行封装,主控制程序的调用相对简单,不必理解协议具体内容,简化了主程序的开发。三是采用模块化开发设计,便于升级和维护。将通信协议封装在DLL里,协议有修改时,动态链接库可独立升级调试,不影响主控制软件,便于维护。四是提高系统的适应性和安全性。DLL可以用不同的编程语言进行开发和调用,只要接口确定,内部可以独立设计,相对安全、适应性高。

2 多线程的设计

2.1 串口通信的设计

串口通信的实现通常有三个办法:一是利用mscomm通信控件;二是采用微软提供的内置的串口操作类System.IO.SerialPort;三是通过API函数。前两种方法编程实现起来简单,但是灵活性有所欠缺;第三种方法虽然编程难度较大,但是高效、自由、灵活,且能避免高速缓存中缓存溢出的缺点,因此,本文采用第三种方法。

图1 串口通信操作步骤

如图1所示,本文对串口使用采用以下几个步骤:

(1)打开转台串口。由于串口是独占性资源,因此,在应用程序设计中,需要避免因打开已占用的串口引发的错误。

(2)设置波特率等串口通信参数。利用GetCommState函数获取串口当前配置,根据需要更改BuildCommDCB结构中的参数,利用SetCommState函数设置串口通信参数。

(3)启动串口监控,即启动串口相关线程(具体见2.2节)。

(4)数据收发。向转台发送指令进行控制;对串口数据接收,将接收到转台的数据解析

(5)关闭串口。在不需要使用此串口时,需关闭串口,释放资源。

2.2 线程设计

现今主流操作系统大多是多进程系统,即系统内可同时运行多个进程,而每个进程也可以同时执行多个线程。每个进程都有一个主线程,同时,可以建立另外的多个线程,进程中的各个线程都是并行执行的[1]。对于本系统,有大量的I/O测试数据,要想获得较高的用户体验,创建多线程是最好的选择。

在转台模拟试验中,数据接收和发送是两个相对独立的过程,其中接收的部分数据是按设置的时间周期定时返回,接收频率有可能会比较高,发送控制指令相对来说比较随机,需要根据试验设计的操作流程来确定。根据这些特点,可以在程序中将读线程和写线程分开,创建两个专门的线程来分别读取和发送串口的数据,如图2所示,线程设计解释如下:

图2 通信线程设计

(1)主线程:用来响应用户的各种操作,处理其他线程的各种响应。

(2)读线程:监听串口,响应各种串口消息事件,如标准事件EX_RXCHAR,响应接收到字符事件;事件EX_RXFLAG,响应接收到事件字符、置入输入缓存区事件;事件EV_CTS,响应准许发送数据事件等。

(3)写线程:向串口写数据,采用API函数WriteFile实现,当有写入错误需要返回错误代码。

(4)中断线程:中断线程的优先级最高,用户或转台随时可以中断读和写操作信号,提高程序的安全性和健壮性。

2.3 线程间的同步

由于同一个进程中的所有的线程共享同一虚拟地址空间,且线程的中断是汇编语言级的,所以有可能会出现线程冲突、阻塞或错误,因此需要采取线程同步措施来避免这些问题[1]。

(1)重叠I/O方式。线程的执行采用重叠I/O方式,避免了程序因等待函数返回而阻塞线程的问题,本文在CreateFile时传递OVERLAPPED结构参数,如果进行I/O操作的API函数返回后并没有完成需要的操作,则调用GetOverLappedResult函数,来等待知道I/O操作完成后返回。

(2)临界区对象。临界区是一段代码,在任意给定的时刻只能被一个线程使用,如果有两个以上的线程同时访问临界区,只允许一个线程使用,其他线程保持等待或被阻塞。在初始化串口、读串口、写串口这些重要操作时,可以利用临界区,避免重要操作冲突或阻塞。

在实现时利用全局变量来统一控制临界区的使用,本文定义了全局变量CRITICAL_SECTION m_csComnuSync,用Enter-CriticalSection函数进入临界区,LeaveCriticalSection释放对临界区的使用权。

(3)事件对象。事件对象时指用户在程序中使用内核对象的有无信号状态实现线程间的同步。通过API函数CreateEvent用于创建事件对象;SetEvent设置其为有信号状态;ResetEvent设置无信号状态。

(4)等待函数。等待函数是用来暂时挂起线程,待到监控对象产生一定信号则继续执行该线程,避免对CPU的过多占用,提高程序的执行效率。利用WaitforSingleObject监控单个同步对象,用WaitForMultipleObject同时监控多个同步对象。

3 通信协议设计

本文将采用动态链接库(DLL)对通信协议进行封装,主测试程序负责提供给测试人员操作界面相关功能,如串口打开、指令发送、指令解析、日志记录等操作;DLL内实现具体的协议组帧、协议解析、串口初始化、线程启动、串口读、串口写、关闭串口等功能,程序流程设计如图3所示。

图3 程序设计流程图

具体设计如下:

(1)对于协议的实现,本文从协议发送和接收两个方面出发进行设计。

(2)设计了协议处理类CFrameData和指令参数结构体strOrderParam,strOrderParam定义如下:

(3)在主程序对指令进行发送时,只需设置外环、中环、内环的指令参数,统一调用协议处理类里面的SetOrder函数即可。

(4)协议的解析,采用解析函数MatchAnswerString来处理,如果协议解析成功,函数将返回CFrameData对象指针。

(5)CFrameData类定义了一系列协议解析的返回的参数,如利用GetMsg来返回帧解析字符串,GetAngel来获取外环、中环、内环的具体数值等。

4 DLL的调用

本文的DLL采用MFC规则的动态链接库,在DLL中有一些必须导出的函数,可以采用以下关键字将函数或类进行导出:可以使用导出关键字__declspec(dllexport)来声明导出;关键字AFX_EXT_CLASS来声明导出类;关键字extern “C”可以使编写的函数供其他编程语言使用。

由程序设计分析得出,需要导出的接口如下:

(1)串口控制类。包含串口控制对象,以及串口打开、配置串口、数据发送和接收、关闭串口等串口控制函数,便于主程序调用控制实现同时操作多个串口。

(2)串口中断函数。主程序可采用发送消息的方式,向DLL发送中断消息,从而触发DLL中的中断函数,停止串口收发数据。

(3)协议发送控制和接收解析函数。协议调用的接口函数主要包括以下两个部分:一是提供统一的指令发送接口函数,供主程序调用后,在DLL内完成组帧发送操作;二是提供统一的解析接口函数,将转台的状态数据返回,显示在主程序界面中。

5 试验与结论

程序采用Microsoft Visual Studio 2010开发平台,开发语言为VC++,主程序开发语言为同一语言。程序界面如图4所示。在工程实践中,用于飞行试验中对转台的通信控制试验,试验未出现信号中断或异常,控制效果良好。

图4 主程序界面

6 结束语

本文将协议和串口通信封装在DLL中,并基于DLL实现了上位机与三自由度转台之间的串口通信。这种处理方法通信速度快、节省资源、简化主程序的开发过程、遵循模块化程序设计思想,具有较强的可拓展性和实用性,在转台试验中得到了较好的应用。

猜你喜欢

主程序调用线程
自动升级程序在船舶监测系统中的应用
基于C#线程实验探究
基于国产化环境的线程池模型研究与实现
浅谈数控铣削技术代码程序的嵌套方式研究
核电项目物项调用管理的应用研究
线程池调度对服务器性能影响的研究*
系统虚拟化环境下客户机系统调用信息捕获与分析①
电控冰箱软件模块化设计
时光倒流 换回PotPlayer老图标
利用RFC技术实现SAP系统接口通信