VC++16通道数据采集系统 - 图文

更新时间:2024-05-25 19:38:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

院系名称 仪器科学与光电工程学院

2011 年 6 月 2 日

目 录

中文摘要........................................................ - 1 - 英文摘要........................................................ - 2 - 1 绪 论....................................................... - 3 - 1.1 研究背景及其目的意义 .................................... - 3 -

1.2 国内外研究现状 .......................................... - 4 - 1.3 本课题研究的主要内容及所需的主要仪器和设备 .............. - 5 - 2 相关技术介绍................................................. - 6 -

2.1 开发工具与环境介绍 ...................................... - 6 -

2.1.1 Visual C++简介..................................... - 6 - 3.1.2 Visual C++的发展过程............................... - 6 - 3.1.3 Visual C++的特点................................... - 7 - 3.1.4 Visual C++的集成开发环境........................... - 7 - 2.2 数据采集的基本原理 ..................................... - 8 - 2.3 基于VC数据采集系统设计的主要过程 ...................... - 8 -

2.3.1 新建工程........................................... - 8 - 2.3.2 在工程中新建类.................................... - 10 - 2.3.3 在各类所对应的子对话框中布局控件.................. - 10 -

3 软件设计部分................................................ - 11 -

3.1 软件设计流程图 ........................................ - 11 -

3.2 数据采集系统主界面设计 ................................ - 12 - 3.3 各模块的设计与实现 .................................... - 13 -

3.3.1 用户登录模块...................................... - 13 - 3.3.2 数据通道选择模块.................................. - 16 - 3.3.3 实时动态曲线显示模块.............................. - 18 - 3.3.4 采集数据存储模块.................................. - 22 - 3.3.5 均值、最值处理模块................................ - 23 - 3.3.6 按钮控件控制模块.................................. - 25 -

3.3.7 采集系统标题及时间显示模块........................ - 26 -

3.3.8 数据通道切换模块.................................. - 28 -

结 论......................................................... - 29 - 谢 辞......................................................... - 31 - [参考文献]..................................................... - 32 - 附录一......................................................... - 33 -

16通道USB数据采集系统的设计

摘 要:通用串行总线USB(Universal Serial Bus)是一种新型的微机总线接

口规范。随着客户对系统数据采集速度要求的不断提高,USB以其使用方便、易于扩展、速度快等优点而越来越多的应用于数据采集系统中。本文介绍了一种16通道USB总线数据采集系统的设计过程,数据采集系统是模拟域与数字域之间必不可少的纽带,它的存在具有着非常重要的作用。该系统的组成分为硬件部分和软件部分。硬件部分主要是借助于USB数据采集卡,实现模拟量到数字量的转换,并通过USB端口输入到计算机中。本文重点介绍的是该系统软件部分的设计,该系统的设计所采用的是VC 6.0软件开发平台,利用VC++中MFC编程的思想方法,建立了友好的系统可视化通讯界面,本论文的研究方向主要是电脑接收到信号以后在界面中显示出来,具有动态显示,数据处理,保存等功能,并可对各通道进行选择显示。因此,该系统具有操作简单,实用性强,可视化程度高等优点。

关键词:通用串行总线 数据采集 USB数据采集卡 VC 6.0开发平台

- 1 -

The Design Of 16-channel USB Data

Acquisition System

Abstract:Universal Serial Bus USB (Universal Serial Bus) is a new type of

computer bus interface specification. As customer requirements for speed of data acquisition systems continue to improve, USB with its easy to use, easy to expand, speed, etc and more and more used in data acquisition system. This article describes a process of a 16-channel USB data acquisition system bus design, data acquisition system is the analog domain and the essential link between the digital domain, its existence has a very important role. The composition of the system is divided into hardware and software parts. With USB hardware component is the data acquisition card, the analog to digital conversion, and through input into the computer USB port. This article focuses on is the software part of the design, the system design are using the VC 6.0 software development platform using VC + +, MFC programming way of thinking, the establishment of a friendly visualization communication interface, the present study direction of the main after the computer receives the signal displayed in the interface with a dynamic display, data processing, preservation and other functions, and can choose to display for each

- 2 -

channel. Therefore,The system is simple, practical, advantages of visualization.

Keywords:Universal Serial Bus Data Acquisition USB Data Acquisition Card

VC 6.0 development platform

1 绪 论

1.1 研究背景及其目的意义

近年来,数据采集及其应用受到了人们越来越广泛的关注,数据采集系统也有了迅速的发展,它可以广泛的应用于各种领域。

数据采集系统起始于20世纪50年代,1956年美国首先研究了用在军事上的测试系统,目标是测试中不依靠相关的测试文件,由非成熟人员进行操作,并且测试任务是由测试设备高速自动控制完成的。由于该种数据采集测试系统具有高速性和一定的灵活性,可以满足众多传统方法不能完成的数据采集和测试任务,因而得到了初步的认可。大概在60年代后期,国内外就有成套的数据采集设备和系统多属于专用的系统。

20世纪70年代后期,随着微型机的发展,诞生了采集器、仪表同计算机溶为一体的数据采集系统。由于这种数据采集系统的性能优良,超过了传统的自动检测仪表和专用数据采集系统,因而获得了惊人的发展。从70年代起,数据采集系统发展过程中逐渐分为两类,一类是实验室数据采集系统,一类是工业现场数据采集系统。

20世纪80年代随着计算机的普及应用,数据采集系统得到了很大的发展,开始出现了通用的数据采集与自动测试系统。该阶段的数据采集系统主要有两类,一类以仪表仪器和采集器、通用接口总线和计算机组成。这类系统主要应用于实验室,在工业生产现场也有一定的应用。第二类以数据采集卡、标准总线和

- 3 -

计算机构成,这一类在工业现场应用较多。20世纪80年代后期,数据采集发生了很大的变化,工业计算机、单片机和大规模集成电路的组合,用软件管理,是系统的成本减低,体积变小,功能成倍增加,数据处理能力大大加强。

20世纪90年代至今,在国际上技术先进的国家,数据采集系统已成功的运用到军事、航空电子设备及宇航技术、工业等领域。由于集成电路制造技术的不断提高,出现了高性能、高可靠的单片机数据采集系统(DAS)。数据采集技术已经成为一种专门的技术,在工业领域得到了广泛的应用。该阶段的数据采集系统采用模块式结构,根据不同的应用要求,通过简单的增加和更改模块,并结合系统编程,就可扩展或修改系统,迅速组成一个新的系统。

1.2 国内外研究现状

数据采集系统是通过采集传感器输出的模拟信号并转换成数字信号,并进行分析、处理、传输、显示、存储和显示。它起始于20世纪中期,在过去的几十年里,随着信息领域各种技术的发展,在数据采集方面的技术也取得了长足的进步,采集数据的信息化是目前社会的发展主流方向。各种领域都用到了数据采集,在石油勘探、科学实验、飞机飞行、地震数据采集领域已经得到应用。

我国的数字地震观测系统主要采用TDE-124C型TDE-224C型地震数据采集系统。近年来,又成功研制了动态范围更大、线性度更高、兼容性更强、低功耗可靠性的TDE-324C型地震数据采集系统。该数据采集对拾震计输出的电信号模拟放大后送至A/D数字化,A/D采用同时采样,采样数据经DSP数字滤波处理后,变成数字地震信号。该数据采集系统具备24位A/D转化位数,采样率有50HZ、100HZ、200HZ。

由美国PASCO公司生产的“科学工作室”是将数据采集应用于物理实验的崭新系统,它由3部分组成:(1)传感器:利用先进的传感技术可实时采集技术可实时采集物理实验中各物理量的数据;(2)计算机接口:将来自传感器的数据信号输入计算机,采样速率最高为25万次/S;(3)软件:中文及英文的应用软件。

受需求牵引,新一代机载数据采集系统为满足飞行实验应用也在快速地发展。如爱尔兰ACRA公司2000年研发推出的新一代KAM500机载数据采集系统到了2006年。本系统采用16位(A/D)模拟数字变换,总采样率达500K/S,同步时间为+/-250ns,可以利用方式组成高达1000通道的大容量的分布式采集系统。

- 4 -

1.3 本课题研究的主要内容及所需的主要仪器和设备

数据采集技术是信息科学的重要分支之一, 它研究信息数据的采集、存储、处理以及控制等问题。它是对传感器信号的测量与处理, 以微型计算机等高技术为基础而形成的一门综合应用技术。数据采集也是从一个或多个信号获取对象信息的过程。随着微型计算机技术的飞速发展和普及,数据采集监测已成为日益重要的检测技术,广泛应用于工农业等需要同时监控温度、湿度和压力等场合。

本课题研究的主要内容是16通道USB数据采集系统的设计:

1.模拟信号范围为±3V,±8V,±10V,0-5V,0-10V,并采用实时显示。

2.能够显示每一通道的动态曲线,并且绘出采集信号在该时刻前的均值和方差。

3.该数据采集系统能够对数据进行保存,保存分为自动保存和手动保存。自动保存要求每隔一定的时间进行保存,并要求保存实时数据。

4.保存的数据格式要求两种:表格文件Excel格式,文本文件TXT格式。 5.系统要求有登陆界面,并设置用户名和密码进行登陆。 6.其他。

本课题所需的主要仪器和设备包括:

USB数据采集卡 Visual c++设计软件 计算机及其他辅助软件

- 5 -

2 相关技术介绍

2.1 开发工具与环境介绍

2.1.1 Visual C++简介

VC是microsoft公司的重要产品之一——Developer Studio工具集的重要组成部分。他用来在Windows(包括95、98、NT、2000、XP等)环境下开发应用的程序,是一种功能强大、行之有效地可视化编程工具。VC以可视化技术为基础,以C++语言为蓝本,以众多的集成工具为骨架,在计算机领域的诸多方面都发挥着重要的作用。VC提供了简洁实用的开发环境,集成的工具集能让用户高效率地开发应用程序。VC提供了MFC类库,一般性的工作可以全部交给VC来完成,用户只要在其基础上做出自己想要实现的功能即可。VC完成目标所花的时间要少的多。

3.1.2 Visual C++的发展过程

作为一种C/C++语言的集成开发环境(IDE),产生VC的最早的根源其实要追溯到DOS时代的Borland公司,当初Borland公司开发的Turbo Pascal和Turbo C让程序员们深刻感受到了把编辑器和编译器集成在一起的IDE是多么的方便,微软公司也看到了这一优点,于是相继开发了Quick C和Microsoft C/C++等多

- 6 -

个DOS版本的C/C++集成开发工具。随着Windows的不断成熟,Micrssoft公司 决定放弃DOS下的开发工作,正式推出Windows下的VC 1.0,早期的VC功能并不怎么强大,使用起来也不方便,1.0版和1.5版都是16位编程工具。VC的革命性改变得益于Windows95的推出,从VC2.0开始,微软公司又放弃了16位编程,以后的VC都只用于32位编程开发,为了与MFC类库的版本号保存一致,微软公司跳过了版本3,直接推出了VC4.0,这个版本及修订版4.2的部分界面风格一直保留到VC6.0。从VC4.0到VC6.0,VC的各种功能不断真强,MFC类库的内容也越来越丰富,现在利用VC开发应用程序已经是一种相对轻松的事情了。

3.1.3 Visual C++的特点

在VC发展的同时,Borland公司也在不断改进他的C/C++开发工具,并相继推出了Borland C++和C++ Builder等产品。其实,现在的C++ Builder也是一个非常优秀的开发工具,但是基于下边的几点原因,我们可以看出VC有着不可比拟的优越性:

1.VC的核心—MFC类库已经是事实上的行业标准,Borland自己开发的类库也在向MFC看齐。

2.VC与Visual Studio中的其他可视化开发工具紧密集成,可以于开发非常专业的应用程序。

3.VC的联机帮助已经被集成到MSDN库中去了,后者包含了微软公司大部分产品的技术文档和支持资料,内容相当丰富,是程序员不可多得的参考资料,现在MSDN库随着Visual Studio6.0一起发行,极大地方便了用户。

3.1.4 Visual C++的集成开发环境

从Visual Studio 6.0的程序组中运行VC6.0,便可启动VC6.0的开发环境—Developer Studio。每次运行VC6.0时,首先会弹出一个“Tip of the Day” 的对话框,其中介绍有很多关于开发环境的使用方法以及编程调试方面的小技巧,如果不想看他,可以选择在下一次启动时不再显示。

如图3.1.3所示,VC6.0的窗口被分成了几部分,最上边是标题条,菜单和工具栏,中间左边的窗口是工作区窗口,右边为文档窗口,显示正在编辑的文本文件(或资源),下方为输出窗口和状态栏。

除了主菜单和工具栏外,VC6.0开发环境还提供了大量的上下文联菜单,用鼠标右键单击窗口中的很多地方都会弹出一个关联菜单,此菜单包括与被单击项目相关的各种命令,从而可以加快一些常规操作的速度。

- 7 -

标题栏

工具栏 菜单栏

项目工作区窗口

文档窗口

输出窗口

输出窗口标签 状态栏

图3.1.3 Visual C++ 6.0开发环境

2.2 数据采集的基本原理

数据采集,又称数据获取,是利用一种装置,从系统外部采集数据并输入到系统内部的一个接口。数据采集技术广泛引用在各个领域。

70年代初,随着计算机技术及大规模集成电路的发展,特别是微处理器及高速A/D转换器的出现,数据采集系统结构发生了重大变革。原来由小规模集成的数字逻辑电路及硬件程序控制器组成的采集系统被微处理器控制的采集系统所代替。由微处理器去完成程序控制,数据处理及大部分逻辑操作,使系统的灵活性和可靠性大大地提高,系统硬件成本和系统的重建费用大大地降低。

在该系统中需要将模拟量转换为数据量,而 A/D是将模拟量转换为数字量的器件,他需要考虑的指标有:分辨率、转换时间、转换误差等等。

数据采集系统一般由信号调理电路,多路切换电路,采样保持电路,A/D,单片机等组成。本次设计部分主要则是对采集到得数据进行分析与处理。

2.3 基于VC数据采集系统设计的主要过程

2.3.1 新建工程 操作步骤如下:

(1)单击开始菜单按钮,运行Microsoft Visual C++ 6.0

- 8 -

(2)单击【文件】—>【新建】按钮,会弹出如图2.3.1所示对话框:

图 2.3.1

输入相应的工程名称及保存到适当的位置,选择所要创建的工程类型MFC AppWizard(exe)然后单击确定按钮进入下一步。

(3)选择所要创建的应用程序类型:基于单文档(S)应用程序按钮。点击进入下一步到步骤6。

(4)在步骤6中基类选择CFormView,对话框显示如图2.3.2所示:

图 2.3.2

单击【完成】按钮进入主界面部分。

- 9 -

2.3.2 在工程中新建类 操作步骤如下:

(1)单击左侧视图栏中ResourceView按钮,单击Dialog树状文件夹展开,右击,分别插入五个Dialog子对话框,其中一个用于绘制用户登录对话框,其余四个用于各通道子对话框的分布。

(2)分别选择每个对话框,单击菜单栏上【查看】->【建立类向导】按钮,每个对话框对应的类名分别为CMydialog,CPage1,CPage2,CPage3,CPage4。 (3)当建立了一个新类框架以后,就应该为该类添加成员,单击菜单栏【查看】->【建立类向导】按钮,选择【Member Variables】按钮,选择需要添加的控件ID,单击右边【Add Variables】按钮,点击完成,便实现了相对应的类的成员的添加过程。接下来的设计代码便可以在各类中进行实现。 注意:不同类中涉及到其他类必须包含该类的头文件。

2.3.3 在各类所对应的子对话框中布局控件 操作步骤如下:

(1) 单击左侧视图栏中ResourceView按钮,单击Dialog树状文件夹展开, 选中其中某个子对话框控件。

(2) 适当调节对话框的大小,保证所绘制的控件按钮能够均匀地分布于对话 框控件上。

(3) 正确选择按钮,文本框及其他控件大小,合理调节时期能够完美地分布 于对话框控件上。 其分布如图2.3.3所示:

- 10 -

图 2.3.3

注解:该图为采集系统部分控件分布绘制图

3 软件设计部分

3.1 软件设计流程图

数据采集,又称数据获取,通过USB数据采集卡实现模拟量到数字量的转换,输入到计算机,通过该系统对输入的信号进行处理,其中包括实时动态曲线显示模块,均值、最大值、最小值模块,数据存储模块,通道选择模块等各模块的处

- 11 -

理。绘制流程图如图3.1所示:

数据采集 失败

数据获取 成功

填充到主界面

否 是否退出 数据通道选择模块 采集数据存储模块 实时动态曲线模块 均值最值显示模块 其他数据处理模块 是

图 3.1

结 束 3.2 数据采集系统主界面设计

数据采集系统主界面框图如图3.2.1所示:

- 12 -

图3.2.1

设计实现功能如下:系统共有16个通道,分布于四个子对话框中,每个子对话框中对应的各通道可以相互切换,单击各个通道的单选按钮可以对所对应的通道进行选择,在选取通道的基础上然后单击所对应通道的开始采集与停止采集按钮,分别会对所要采集的实时数据进行采集与停止采集,所采集的数据可以在动态曲线图中动态显示出来,采集到的数据可以在所对应的文本框中显示出来,显示值为采集值,采集均值,采集最大值与采集最小值,并能实时保存所采集到得数据到指定的文件夹中。

3.3 各模块的设计与实现

3.3.1 用户登录模块

系统登录模块用于验证用户登录系统时输入的用户名、密码是否正确,只有合法的用户才可以进入系统。

该模块流程图如图3.3.1所示:

- 13 -

用户输入 失败 信息获取 成功

图 3.3.1

系统登录设计如图3.3.2所示:

打开控制界面

图3.3.2

为实现此功能,需对各按钮进行赋值声明如表1.14所示:

表 1.14

字段名称 IDC_EDIT1 IDC_EDIT2 数据类型 文本 文本 成员名 m_strUser 相关属性 字段大小12 备注 用户名 密码 m_setPassword 字段大小12 由于需要在应用程序窗体显示前,显示登录对话框。所以修改CMyDoc:Document()函数。

实现验证用户名,密码功能的代码如下: BOOL CMy16Doc::OnNewDocument() {

if (!CDocument::OnNewDocument())

- 14 -

return FALSE;

// TODO: add reinitialization code here // (SDI documents will reuse this document) CMyDlg dlg; dlg.DoModal(); return TRUE; }

重载OnOK()与OnCancel()函数,添加代码如下:

void CMyDlg::OnOK() {

// TODO: Add extra validation here UpdateData(TRUE);

if((m_strUser==\ {

CDialog::OnOK(); } else {

m_strUser=\ m_strPassword=\

AfxMessageBox(\密码输入错误,请重新登录!\ UpdateData(FALSE); }

}

/*****************************************************/

void CMyDlg::OnCancel()

{

// TODO: Add extra cleanup here

CDialog::OnCancel(); exit(0); }

用户名或密码输入错误会出现如图3.3.2所示:

- 15 -

图3.3.2

3.3.2 数据通道选择模块

系统采集得到的数据需对应于每一个通道,每个不同的通道对应一个不同ID的单选按钮,通过判断某个单选按钮是否被选中来判断该通道是否被选中,为实现此功能,需对各按钮控件进行赋值声明如表1.15所示:

表1.15

按钮ID IDC_RADIO1 IDC_RADIO2 IDC_RADIO3 IDC_RADIO4 该模块程序功能流程图如图3.3.3所示:

执行下一步 选择某通道 进行通道选择 备注 通道一选择 通道二选择 通道三选择 通道四选择 图 3.3.3

- 16 -

为实现各通道是否被选中,其代码如下:

/***********通道一选择******************/ void CPage1::OnButton1()

{

// TODO: Add your control notification handler code here CButton* theradio = (CButton*) GetDlgItem(IDC_RADIO1); bool check1=theradio->GetCheck();

if(check1==TRUE) // 如果单选按钮1被选中 {

SetTimer(1,1000,NULL); // 启动时钟触发器,每秒钟触发一次 }

} //其中部分代码略有删除

/***********通道二选择******************/ void CPage1::OnButton2() {

// TODO: Add your control notification handler code here CButton* theradio = (CButton*) GetDlgItem(IDC_RADIO1); bool check1=theradio->GetCheck(); if(check1==TRUE) {

SetTimer(1,1000,NULL); } }

/***********通道三选择******************/ void CPage1::OnButton3() {

// TODO: Add your control notification handler code here CButton* theradio = (CButton*) GetDlgItem(IDC_RADIO1); bool check1=theradio->GetCheck(); if(check1==TRUE) {

SetTimer(1,1000,NULL); } }

/***********通道四选择******************/ void CPage1::OnButton4() {

// TODO: Add your control notification handler code here

- 17 -

CButton* theradio = (CButton*) GetDlgItem(IDC_RADIO1); bool check1=theradio->GetCheck(); if(check1==TRUE) {

SetTimer(1,1000,NULL); } }

3.3.3 实时动态曲线显示模块

实时动态曲线,顾名思义就是曲线在坐标轴上随时间的动态显示过程。通过实时动态曲线能够较直观的反应出采集量的大致变化趋势,实时动态曲线有很多不同的显示方式,本设计所采用的是逐点移动式,绘制结果如图3.3.4所示:

图3.3.4 其软件流程图如图3.3.4所示:

数据采集 实时显示 超出范围 刷屏 重新绘图

图 3.3.4 其绘制过程及代码如下:

- 18 -

1.选定所要绘制的矩形区域绘制时间-采集数据的平面直角坐标系,

其绘制代码如下:

void CPage1::OnPaint() {

CPaintDC dc(this); // device context for painting

// TODO: Add your message handler code here CPen *pPenBlack=new CPen();

pPenBlack->CreatePen(PS_SOLID,3,RGB(0,0,0)); // 用于定义坐标系的画笔类型、颜色及粗细 CPen *oldpen=NULL;

oldpen=dc.SelectObject(pPenBlack); dc.MoveTo(250,20);

dc.LineTo(250,110); //第一通道坐标系轮廓绘制部分 dc.LineTo(700,110);

for(int i=0;i<=30;i++) {

CString str;

CFont font,*pOldFont;

font.CreateFont(10, // nHeight 4, // nWidth

0, // nEscapement 0, // nOrientation 500, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut

ANSI_CHARSET, // nCharSet

OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality

DEFAULT_PITCH | FF_SWISS, //

nPitchAndFamily _T( \

pOldFont=dc.SelectObject(&font); str.Format(\

dc.TextOut(250+15*i,115,str);// 第一通道绘制坐标系值部分 dc.SelectObject(pOldFont);

CPen *pPenBlack1=new CPen();

pPenBlack1->CreatePen(PS_SOLID ,1,RGB(88,88,88));

- 19 -

CPen *oldpen=NULL;

oldpen=dc.SelectObject(pPenBlack1);

dc.MoveTo(250+i*15,110); // 第一通道绘制纵轴系部分 dc.LineTo(250+i*15,20); }

for(int j=1;j<=9;j++) {

CString str;

CFont font,*pOldFont;

font.CreateFont(10, // nHeight 4, // nWidth

0, // nEscapement 0, // nOrientation 500, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut

ANSI_CHARSET, // nCharSet

OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality

DEFAULT_PITCH | FF_SWISS, //

nPitchAndFamily _T( \

pOldFont=dc.SelectObject(&font); str.Format(\

dc.TextOut(240,110-j*10,str);// 第一通道绘制部分 dc.TextOut(230,30,\数\ dc.TextOut(230,40,\值\

dc.TextOut(680,125,\时间(/s)\

dc.SelectObject(pOldFont);

dc.MoveTo(250,110-j*10); // 第一通道绘制横轴系部分 dc.LineTo(700,110-j*10);

CFont font,*pOldFont;

font.CreateFont(14, // nHeight 6, // nWidth

0, // nEscapement 0, // nOrientation 500, // nWeight FALSE, // bItalic

- 20 -

FALSE, // bUnderline 0, // cStrikeOut

ANSI_CHARSET, // nCharSet

OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality

DEFAULT_PITCH | FF_SWISS, //

nPitchAndFamily

_T( \

pOldFont=dc.SelectObject(&font); dc.SetTextColor(RGB(0,0,250));

dc.TextOut(420,6,\第一通道曲线图\ dc.SelectObject(pOldFont);

// Do not call CDialog::OnPaint() for painting messages

}

1.绘制曲线在坐标轴上的动态显示过程,当绘制曲线超出所绘制的框图时,采用刷新显示,即刷新原来的绘图曲线重新绘图,其代码如下:

void CPage1::OnTimer(UINT nIDEvent) { // TODO: Add your message handler code here and/or call default switch(nIDEvent) {

case 1: {

int offsetx=15; CClientDC dc(this); static int x=250; static int y=110;

CPen pen1(PS_SOLID,0,RGB(255,0,8)); CPen *oldpen1=NULL;

oldpen1=dc.SelectObject(&pen1); x=x+offsetx; if(x<=700) {

dc.MoveTo(x-offsetx,y); y=110-rand()?; dc.LineTo(x,y); } else {

CRect rect;

- 21 -

rect.SetRect(250,20,700,110); InvalidateRect(rect,TRUE); x=250;

y=110-rand()?; } } break;

CDialog::OnTimer(nIDEvent); }

3.3.4 采集数据存储模块

该模块用于对所采集的数据进行存储,存储过程为实时输出显示并存储于指定空间的.txt文件中,其软件流程图如图3.3.5所示:

数据显示 打开文件 数据保存 数据获取

图 3.3.5

实现代码如下:

void CPage1::OnPaint() {

CString strTmp;

strTmp.Format(\ str += strTmp ;

/*\ CStdioFile file( \

// 数据存储位置

file.WriteString(str); // 数据写入

- 22 -

file.Close(); // 关闭文件夹 }

3.3.5 均值、最值处理模块

该模块用于对采集数据均值、最值的实时显示,每个数据显示于相对应的文本控件中,各个控件所显示的值能随采集数值的变化而变化, 本例以第一通道各控件为例,各控件的赋值声明如表3.3.5所示: 表 3.3.5

控件ID IDC_EDIT10 IDC_EDIT11 IDC_EDIT12 IDC_EDIT13

各部分功能代码显示如下:

void CPage1::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

switch(nIDEvent) { case 1: {

int

offsetx=15; 数据类型 Int Float Int Int 成员名 m_caiji1 m_junzhi1 m_max1 m_min1 备注 采集数值 采集均值 采集最大值 采集最小值 CClientDC dc(this); static int x=250; static int y=110;

static int z=0;

static int j=0; static int max=0;

- 23 -

static int min=90;

CPen pen1(PS_SOLID,0,RGB(255,0,8)); CPen *oldpen1=NULL;

oldpen1=dc.SelectObject(&pen1); x=x+offsetx; if(x<=700) {

j++;

dc.MoveTo(x-offsetx,y); y=110-rand()?;

dc.LineTo(x,y);

m_caiji1=(110-y);

UpdateData(FALSE); // 采集数值显示部分 } else {

CRect rect;

rect.SetRect(250,20,700,110);

InvalidateRect(rect,TRUE); // 屏幕刷新区域

j++;

}

x=250;

y=110-rand()?; m_caiji1=(110-y);

UpdateData(FALSE); //采集数值显示部分

z+=m_caiji1;

if(max<=m_caiji1)

m_junzhi1=z/j;

UpdateData(FALSE); // 采集均值显示部分

- 24 -

{

max=m_caiji1;

m_max1=max;

UpdateData(FALSE); // 采集最大值显示部分

min=m_caiji1;

if(min>=m_caiji1) { }

m_min1=min;

UpdateData(FALSE); // 采集最小值显示部分

3.3.6 按钮控件控制模块

按钮控件主要分为开始采集和停止采集两部分,通过控制这两部分可以有效地控制数据的输入及采集的时间,本例以通道一控制部分为例,其软件流程图如图3.3.6所示:

停止数据采集 点击停止按钮 开始数据采集 点击采集按钮 }

图 3.3.6

各控件的赋值声明如表3.3.7所示:

- 25 -

表 3.3.7

控件ID IDC_BUTTON1 IDC_BUTTON2 实现代码如下:

备注 开始采集 停止采集 void CPage1::OnButton1() // 单击开始采集按钮 {

// TODO: Add your control notification handler code here

CButton* theradio = (CButton*) GetDlgItem(IDC_RADIO1); bool check1=theradio->GetCheck();

if(check1==TRUE) // 是否选择该通道 {

SetTimer(1,1000,NULL); // 如果是,每秒触发一次时钟脉冲 m_volt1=5000;

m_temp1=20;

UpdateData(FALSE); }

/********************************************************/

void CPage1::OnButton2() // 单击停止采集按钮

{

// TODO: Add your control notification handler code here }

KillTimer(1); // 停止一事件的采集

}

3.3.7 采集系统标题及时间显示模块

该模块主要为完善用户界面而设置的,各控件的赋值声明如表3.3.7所示:

表 3.3.7

- 26 -

控件ID IDC_STATIC1 IDC_STATIC2 实现代码如下:

void CMy16View::OnInitialUpdate() {

CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit(); CFont * f; // 字体类型自定

备注 标题显示控件 时间显示控件 GetDlgItem(IDC_STATIC1)->SetFont(f);

//IDC_STATIC1是静态文本框的ID

CFont * h; // 字体类型自定

GetDlgItem(IDC_STATIC2)->SetFont(h);

//IDC_STATIC2是静态文本框的ID SetTimer(1, 1000, NULL); }

/********用于文本框中的时间显示*********/ void CMy16View::OnTimer(UINT nIDEvent) {

// TODO: Add your message handler code here and/or call default

// TODO: Add your message handler code here and/or call default

CTime time = CTime::GetCurrentTime();

m_ShowNowTime = time.Format(\ UpdateData(FALSE);

CFormView::OnTimer(nIDEvent); }

- 27 -

3.3.8 数据通道切换模块

按照任务要求需要设计16个通道,考虑到界面设计的美观性及客户性,本设计中采用了tab控件按钮,通过四部分来实现,每个按钮对应一个在对话框,在每个子对话框上布有四个通道,通过切换各按钮可以显示所对应的各通道子对话框,各子对话框的类名分别为CPage1,CPage2,CPage3,CPage4,Tab控件按钮所对应的成员名为m_tab,通道切换实现代码见附录1所示。 其软件流程图如图3.3.8所示:

确认选择 通道选择 选择通道范围 预选通道

图 3.3.8

- 28 -

结 论

1 本课题结论

随着电子计算机的广泛应用,社会的数字化程度越来越高,数据采集也越来越重要,本系统为多通道USB总线数据采集系统,可用于电压、电流、温度等信号的实时采集、观察等场合。该基于USB总线的数据采集系统具有可靠性高、数据不丢失、抗干扰性强,便于数据传输和处理等优点,有良好的应用前景和很大的实用价值。

USB是一种IT行业新发展起来的通用接口标准,目前很多应用主要集中在PC机的外设和一些消费类电子上。其实,作为一种通用型串行总线标准,USB不仅仅适用于IT行业,它的应用空间很广泛,完全可以使用在不同的领域和行业。特别是由于USB的使用简单、即插即用、热插拔、开放性、高速、稳定、可靠性高等优点,它特别适用于仪器仪表、虚拟仪器、数据采集、数据采集设备、监控设备和加密设备等等场合。

2 研究工作的不足

尽管所设计的系统在功能上能够大致满足基本要求,但其功能的实现方式与所要求的方式却存在一定的差距。一方面主要是因为自己在VC掌握的层面上有一定的欠缺,只能对其基本功能基本代码进行操作与实现,一旦碰到复杂功能的实现便无从下手。另一方面主要在资料的收集方面存在一定的困难,不能或者很少能够找到相关的资料信息及应用相关资料信息能力的有限程度。正如在绘制实时动态曲线的显示的方式,我所采用的方式是逐点移动式,与曲线的推进式绘制方式不同,其实后者在显示上更能表现采集数据的动态显示特征,更直观、明确,唯一的缺憾就是其实现过程比较复杂,所以没有选择这种方法,取而代之的是采用了第一种方式来实现的,该方式虽然在技术层面上不如第二种方式,但其编程

的可靠性,易实现性,简明性则更好的为后面代码功能的实现提供了可靠的保证。

另一个不足之处在于框图的美化设计上有待于进一步的完善,主要在于控件按钮的布局及属性的选择,及界面色彩方案的选择上。相信做好这一点,能够更好地实现系统框图的个性化,人性化及客户性要求。

- 29 -

3 今后研究的方向的建议

本论文已基本实现了USB数据采集系统软件方面的功能要求,如果能够结合USB总线数据采集卡,相信在功能的实现上更能体现其完整性,其有待于今后进一步发展。

在不足之处方面如果能够加以改善,一方面界面设计能够更加美观,另一方面实时动态曲线的实现方式及其他功能的实现能够进一步提升,相信能够实现更加完美的数据采集系统。

- 30 -

谢 辞

这个设计论题对我来说是个很大的挑战,因为在此之前并没怎么接触过VC,一切都是从基础开始,要在这短短的时间里了解一门语言并且把它应用于实践中确实有一定的困难,所花的时间主要也在于前期工作中,包括资料的收集,方案的选定及系统框图的绘制。这次毕业设计之所以能够较顺利的完成,得益于各位老师的细心教导,特别是洪占勇老师,每个星期他都会抽时间来指导我们,了解我们的进度,帮助我们解决设计中的难题,在此对老师表示特别的感谢,也对曾指导我的老师表示感谢!

本次毕业设计主要有三方面的收获:

1. 通过对USB总线数据采集系统的设计,掌握了VC的基本编程方法,加深了对C++语言的认识,从而普及了计算机软件方面的知识,软件的运行机理及软件的实现方式。

2. 框图的构思是系统设计中极其重要的一个模块,框图的布局直接影响今后的设计工作及代码的编写,合理布局框图能够避免代码编写与框图布局的不一致性。

3. 软件设计过程中最好能在一定时间内对其进行保存,以免出现其他原因照成数据的丢失。

再次感谢各位老师,祝老师们工作顺利!

- 31 -

[参考文献]

[1] 陈天华.面向对象程序设计与Visual C++6.0教程.北京:清华大学出版社,

2006. [2] 郑阿奇,丁有和.Visual C++应用教程.北京:人民邮电出版社,2008. [3] 张立科.Visual C++6.0程序设计与开发技术大全.北京:人民邮电出版社,

2004.

[4] 幸长安,梅林.VC++编程技术与难点剖析.北京:清华大学出版社,2002. [5] 罗斌.Visual C++编程技巧精选.北京:中国水利水电出版社,2005.

- 32 -

附录一

系统主视图对话框代码:

// 16通道数据采集系统View.cpp : implementation of the CMy16View class //

#include \

#include \通道数据采集系统.h\#include \通道数据采集系统Doc.h\#include \通道数据采集系统View.h\#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE

static char THIS_FILE[] = __FILE__; #endif

///////////////////////////////////////////////////////////////////// // CMy16View

IMPLEMENT_DYNCREATE(CMy16View, CFormView) BEGIN_MESSAGE_MAP(CMy16View, CFormView)

//{{AFX_MSG_MAP(CMy16View)

ON_NOTIFY(TCN_SELCHANGE, IDC_TAB1, OnSelchangeTab1) ON_WM_TIMER() //}}AFX_MSG_MAP

// Standard printing commands

ON_COMMAND(ID_FILE_PRINT, CFormView::OnFilePrint) ON_COMMAND(ID_FILE_PRINT_DIRECT, CFormView::OnFilePrint)

ON_COMMAND(ID_FILE_PRINT_PREVIEW, CFormView::OnFilePrintPreview)

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////

////////

- 33 -

// CMy16View construction/destruction

CMy16View::CMy16View() { }

CMy16View::~CMy16View() { }

void CMy16View::DoDataExchange(CDataExchange* pDX) { }

BOOL CMy16View::PreCreateWindow(CREATESTRUCT& cs) { }

return CFormView::PreCreateWindow(cs);

// TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs

CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMy16View) DDX_Control(pDX, IDC_TAB1, m_tab); DDX_Text(pDX, IDC_EDIT1, m_ShowNowTime); //}}AFX_DATA_MAP

//{{AFX_DATA_INIT(CMy16View) m_ShowNowTime = _T(\//}}AFX_DATA_INIT

// TODO: add construction code here : CFormView(CMy16View::IDD)

- 34 -

void CMy16View::OnInitialUpdate() {

CFormView::OnInitialUpdate(); GetParentFrame()->RecalcLayout(); ResizeParentToFit();

if(!page1.m_hWnd||!page2.m_hWnd||!page3.m_hWnd||!page4.m_hWnd) //第一

次初始化m_tab 控件和page页的建立

{

//初始化m_tab控件

m_tab.InsertItem(0,\通道1-4\ m_tab.InsertItem(1,\通道5-8\ m_tab.InsertItem(2,\通道9-12\

m_tab.InsertItem(3,\通道13-16\ //建立属性页各页

page1.Create(IDD_DIALOG1,GetDlgItem(IDC_TAB1)); page2.Create(IDD_DIALOG2,GetDlgItem(IDC_TAB1)); page3.Create(IDD_DIALOG3,GetDlgItem(IDC_TAB1)); page4.Create(IDD_DIALOG4,GetDlgItem(IDC_TAB1));

//设置页面的位置在m_tab控件范围内

CRect rs;

m_tab.GetClientRect(rs); rs.top+=20; rs.bottom-=4; rs.left+=4; rs.right-=4;

page1.MoveWindow(rs); page2.MoveWindow(rs); page3.MoveWindow(rs); page4.MoveWindow(rs);

- 35 -

page1.ShowWindow(TRUE); m_tab.SetCurSel(0);

}

CFont * f; f = new CFont; f->CreateFont(40, 12, // nWidth 0, // nEscapement 0, // nOrientation FW_BOLD, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut

ANSI_CHARSET, // nCharSet

OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality

DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T(\

GetDlgItem(IDC_STATIC1)->SetFont(f); //IDC_STATIC1是静态文本框的ID

CFont * h; h= new CFont; h->CreateFont(20, 10, // nWidth 0, // nEscapement 0, // nOrientation FW_BOLD, // nWeight FALSE, // bItalic FALSE, // bUnderline 0, // cStrikeOut

- 36 -

ANSI_CHARSET, // nCharSet

OUT_DEFAULT_PRECIS, // nOutPrecision CLIP_DEFAULT_PRECIS, // nClipPrecision DEFAULT_QUALITY, // nQuality

DEFAULT_PITCH | FF_SWISS, // nPitchAndFamily _T(\

GetDlgItem(IDC_STATIC2)->SetFont(h); //IDC_STATIC1是静态文本框的ID SetTimer(1, 1000, NULL); }

///////////////////////////////////////////////////////////////////// // CMy16View printing

BOOL CMy16View::OnPreparePrinting(CPrintInfo* pInfo) { }

void CMy16View::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { }

void CMy16View::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/) { }

void CMy16View::OnPrint(CDC* pDC, CPrintInfo* /*pInfo*/) { }

// TODO: add customized printing code here // TODO: add cleanup after printing

// TODO: add extra initialization before printing // default preparation

return DoPreparePrinting(pInfo);

- 37 -

///////////////////////////////////////////////////////////////////// // CMy16View diagnostics

#ifdef _DEBUG

void CMy16View::AssertValid() const { }

void CMy16View::Dump(CDumpContext& dc) const { }

CMy16Doc* CMy16View::GetDocument() // non-debug version is inline { }

#endif //_DEBUG

//////////////////////////////////////////////////////////////////// // CMy16View message handlers

void CMy16View::OnSelchangeTab1(NMHDR* pNMHDR, LRESULT* pResult) {

// TODO: Add your control notification handler code here int CurSel;

ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy16Doc))); return (CMy16Doc*)m_pDocument; CFormView::Dump(dc); CFormView::AssertValid();

CurSel=m_tab.GetCurSel(); switch(CurSel) {

- 38 -

case 0:

page1.ShowWindow(TRUE); page2.ShowWindow(FALSE); page3.ShowWindow(FALSE); page4.ShowWindow(FALSE); break; case 1:

page1.ShowWindow(FALSE); page2.ShowWindow(TRUE); page3.ShowWindow(FALSE); page4.ShowWindow(FALSE); break; case 2:

page1.ShowWindow(FALSE); page2.ShowWindow(FALSE); page3.ShowWindow(TRUE); page4.ShowWindow(FALSE); break; case 3:

page1.ShowWindow(FALSE); page2.ShowWindow(FALSE); page3.ShowWindow(FALSE); page4.ShowWindow(TRUE); break; default: ; } }

void CMy16View::OnTimer(UINT nIDEvent)

{

*pResult = 0;

- 39 -

// TODO: Add your message handler code here and/or call default // TODO: Add your message handler code here and/or call default CTime time = CTime::GetCurrentTime();

m_ShowNowTime = time.Format(\ UpdateData(FALSE);

CFormView::OnTimer(nIDEvent);

}

- 40 -

本文来源:https://www.bwwdw.com/article/d3a7.html

Top