关于ATS作业———利用LABWINDOWS/CVI显示波形并测量幅度、频率

2023-11-10 22:20

本文主要是介绍关于ATS作业———利用LABWINDOWS/CVI显示波形并测量幅度、频率,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

0 题目与题目分析

设计带有波形显示和幅度,频率测量的测试应用程序。要求波形数据和测量数据来自uvats。提交测试后截图,波形显示代码截图,测量代码截图。

分析:题目要求实现三个功能——波形显示、幅度测量和频率测量,其中波形、幅度和频率都来自于DSO.所以我们需要通过VISA接口,用指令的方式从仪器获取相关的数据。由于需要通过GUI显示结果,前端我们需要Graph控件、Message控件和Button控件,分别用于显示波形,显示测量结果,控制GUI是否显示数据。由于在这里Graph控件画图和VISA通信耗时很久,如果我们使用单线程编程来完成这道题目的话,可以实现基本功能,但是GUI响应各种事件,比如单击、拖动窗口等事件,都会有不能忍受的延迟

下图为我的GUI效果图:
在这里插入图片描述
总结一下我们工程的架构:

  1. 数据来源为DSO,VISA和Sock32不能少;
  2. GUI需要Graph、Message(或其他可替代的控件)和Button;
  3. 一定要多线程(除非你可以忍受以秒为单位的响应延迟)。

另外:白嫖作业不是好习惯,本文的主要目的是点拨。有细节上的问题可以私聊我QQ.

1.从DSO接收数据

1.1 幅度数据

根据仪器编程手册,我们要获取到波形数据,需要用到的指令为:

:WAVeform:DATA?

这个简单,我们只需要通过相关的函数将这个命令发送给仪器就行了。

但是我们接受到的信息是怎样的呢?通过查询仪器编程手册,可以得到这样的结论:

<header><waveform_data><NL>

<header>表示帧头,<waveform_data>表示数据,<NL>则表示消息结束符(\n).

帧头里面包含了两个信息:1.仪器发送了多少数据;2.仪器发送的数据是多少字节的。
在这里插入图片描述
如上图,我们发送:WAV:DATA?指令收到的帧头是#41000,其中蕴藏的含义为:1.一个数据由4个byte构成,那么我们的每一个接收指针则需要指向至少32bit的内存。2.这一帧数据发送了1000个波形数据,那么我们需要用长度为1000的数组来装下这些数据头。所以我们需要接收两次,一次接收帧头(6个bit),一次接收数据。

在这里,每个波形数据传回来的数字并不是直接的电压值,而是和测量的电压值成倍数关系的很大的整数值(但我不知道这个整数的意义,一旦研究出这个整数是什么了,一定会第一时间告诉读者的),所以我们要乘上一个数,将这个大整数转换为电压。

Warning: 在这里,由于老师提供的uviScanf函数可能会引起General Protection的错误,所以在这里建议用uviRead函数来实现接收功能。

1.2 波形幅度和信号频率接收

根据仪器编程手册,获得幅度和频率的指令分别为:

:MEASure:VAMPlitude?
:MEASure:FREQuency?

由于发送这两个指令,仪器返回的都是单值,没有太大的执行难度,只要用%lf(双精度浮点)格式接收即可。

Warning:在这里建议用老师给的uviScanf函数接收.

2.多线程编程

多线程编程主要分为三个步骤

  1. 生成线程池;
  2. 调度线程函数;
  3. Discard线程池。(discard想不到好的翻译)

2.1 线程池的生成

在这里用到了这个函数:

int CVIFUNC  CmtNewThreadPool (int maxNumThreads, CmtThreadPoolHandle *poolHandle); 

第一个输入参数为线程池中最大的线程数,第二个输入参数为线程池句柄,这个句柄需要自己在代码中定义,其中CmtThreadPoolHandle可以替换为int。返回值为0则说明线程池创建成功。

e.g.

int pool_handle;
CmtNewThreadPool(3,&pool_handle);

2.2 线程函数调度

首先我们需要写好辅助线程函数,比如在本次作业中,我将绘制波形和仪器通信函数都放在了辅助线程中。由于辅助线程函数在运行完之后就不会被自动重新调用,所以我们需要把相关代码放在while(1)中。格式大致如下:

e.g.

int CVICALLBACK Thread1 ()
{//需要定义的变量while(1){//相关操作...}return 0;
}

我们还需要告诉线程池,哪个函数是它需要调度的线程函数,在这里我们用到这个函数:

int CVIFUNC  CmtScheduleThreadPoolFunction 
(CmtThreadPoolHandle poolHandle, CmtThreadFunctionPtr threadFunction,void *threadFunctionData, CmtThreadFunctionID *threadFunctionID);

poolHandle即位线程池句柄,threadFunction为线程函数的函数名,threadFunctionData为函数的返回值传向的变量的指针,如果不关系返回值可以输入NULL,CmtThreadFunctionID为线程ID,在调用该函数之前定义即可,数据类型CmtThreadFunctionID依然可以用int替换。使用示例如下:

e.g.

int CVICALLBACK Thread1 ();/*...*/int pool_handle;
int thread_funcID;
CmtNewThreadPool(3,&pool_handle);
CmtScheduleThreadPoolFunction (pool_handle, Thread1, NULL, &thread_funcID); 

2.3 丢弃(Discard)线程

在结束程序的时候,同时也需要将线程池丢弃(没学过操作系统,要丢弃的原因是不是和打开文件后要关闭文件一样是为了把占用的内存释放?求解释)。

相关函数为:

int CVIFUNC CmtDiscardThreadPool (CmtThreadPoolHandle poolHandle); 

输入参数poolHandle为要丢弃的线程池的句柄。该函数在RunUserInterface()函数后面运行,即保证UIR关闭后,线程池也将被丢弃。

3.关于GUI

GUI是这次作业的三个部分中最简单的一个部分了,所以放在了最后一个讲,同时也不准备讲怎么用Graph、Button什么的,大家肯定都会,在这里讲点好玩点的。(这一部分在划水)

3.1 怎样更改GUI的图标(ICON)

用CVI打开你的工程文件,在Build选项卡中选择Target Setting.
在这里插入图片描述
然后在Application Icon File中,选择你希望修改为的图标文件,在这里我用pop子的头像作为图标。
在这里插入图片描述

Warning:在这里,必须用*.ico文件作为图标文件。百度上可以搜索到一些在线将图片文件转换为ico文件的网站,在这里就不细说了。

3.2 个性化你的标题栏

用CVI打开工程中的uir文件,在右侧边栏的PANEL的属性栏中的Title and Titlebar Appearance组中找到Title这一选项,将其修改为你希望你的GUI所拥有的标题名就行了。这里我就叫Eden’s GUI(不想动脑筋。在这里插入图片描述
同时,修改相关的属性设置,还可以让你的GUI尺寸不会发生改变,也可以禁用“最大化”按钮,让你的GUI变得更酷一点。

这篇关于关于ATS作业———利用LABWINDOWS/CVI显示波形并测量幅度、频率的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/385636

相关文章

作业提交过程之HDFSMapReduce

作业提交全过程详解 (1)作业提交 第1步:Client调用job.waitForCompletion方法,向整个集群提交MapReduce作业。 第2步:Client向RM申请一个作业id。 第3步:RM给Client返回该job资源的提交路径和作业id。 第4步:Client提交jar包、切片信息和配置文件到指定的资源提交路径。 第5步:Client提交完资源后,向RM申请运行MrAp

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

安卓链接正常显示,ios#符被转义%23导致链接访问404

原因分析: url中含有特殊字符 中文未编码 都有可能导致URL转换失败,所以需要对url编码处理  如下: guard let allowUrl = webUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else {return} 后面发现当url中有#号时,会被误伤转义为%23,导致链接无法访问

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

C# dateTimePicker 显示年月日,时分秒

dateTimePicker默认只显示日期,如果需要显示年月日,时分秒,只需要以下两步: 1.dateTimePicker1.Format = DateTimePickerFormat.Time 2.dateTimePicker1.CustomFormat = yyyy-MM-dd HH:mm:ss Tips:  a. dateTimePicker1.ShowUpDown = t

小程序button控件上下边框的显示和隐藏

问题 想使用button自带的loading图标功能,但又不需要button显示边框线 button控件有一条淡灰色的边框,在控件上了样式 border:none; 无法让button边框隐藏 代码如下: <button class="btn">.btn{border:none; /*一般使用这个就是可以去掉边框了*/} 解决方案 发现button控件有一个伪元素(::after

MFC中Spin Control控件使用,同时数据在Edit Control中显示

实现mfc spin control 上下滚动,只需捕捉spin control 的 UDN_DELTAPOD 消息,如下:  OnDeltaposSpin1(NMHDR *pNMHDR, LRESULT *pResult) {  LPNMUPDOWN pNMUpDown = reinterpret_cast(pNMHDR);  // TODO: 在此添加控件通知处理程序代码    if

R语言统计分析——重复测量方差分析

参考资料:R语言实战【第2版】         所谓重复测量方差分析,即受试者被测量不止一次。本例使用数据集市co2数据集:因变量是二氧化碳吸收量(uptake),自变量是植物类型(Type)和七种水平的二氧化碳浓度(conc)。Type是组间因子,conc是组内因子。Type已经被存储为一个因子变量,还需要将conc转换为因子变量。分析过程如下: # 将conc变量转化为因子变量CO2$c

微信小程序uniappvue3版本-控制tabbar某一个的显示与隐藏

1. 首先在pages.json中配置tabbar信息 2. 在代码根目录下添加 tabBar 代码文件 直接把微信小程序文档里面的四个文件复制到自己项目中就可以了   3. 根据自己的需求更改index.js文件 首先我这里需要判断什么时候隐藏某一个元素,需要引入接口 然后在切换tabbar时,改变tabbar当前点击的元素 import getList from '../