
坦率地说,大多数“普通”程序员对LabVIEW技术持attitude昧态度。 在这里,您可以争论很长时间,但无济于事。 网络上有许多LabVIEW程序示例,使情况更加恶化,但是它们全都面向初学者,归结为“哦,看它有多简单,将扭转连接到指示器,扭转旋钮,数字变化”,或者充其量是在循环图中显示一个随机数或正弦,所有这些都伴随着一个愤怒的界面,它以巨型拨动开关,旋钮和百分表为形式。 就个人而言,这种有意识的简化方法使我很烦。 在简短的系列文章中,我将尝试向读者介绍在LabVIEW中开发应用软件的过程。 为了不花太多时间在主题领域,我们将使用详细的算法以MPSSE模式通过FTDI将配置文件上传到FPGA( 通过USB将配置下载到FPGA或拆卸FTDI MPSSE )。 在本文中,我将展示如何使用LabVIEW语言实现相同的FPGA加载器。
如上所述,串行无源(SP)模式下的FPGA加载算法和FTDI操作原理在上一篇文章中已有很好的描述。 我不会重复自己。 我们认为该算法已经过测试并被认为是合适的。 是的,假设读者至少对LabVIEW概念有初步的了解,并且精通经典编程。
尽管创建引导加载程序的过程不需要花费很多时间,但是对该过程的描述并没有适合一篇文章的内容,因此将有一个小系列。 由于实验阶段已经完成,并且我对算法的可操作性充满信心,所以我将允许我自己从用户界面开始开发。 在第一篇文章中,我们将创建加载程序用户界面并实现程序结构。 在第二个-通过FTDI驱动程序dll中,我们实现了* .rbf文件的加载到FPGA中。
为了提高对话效率,回顾LabVIEW中采用的术语并不是多余的。 在LabVIEW中,应用程序称为虚拟仪器,也称为VI,也简称为虚拟仪器或VI。 VP有两个“方面”:控件和指示器所在的前面板,以及互连这些元素并实现功能和数据处理流程的框图(框图)。 通常,VP具有分层结构;顶级VP中的所有VP通常称为子设备或SubVI。
使用者介面
我们的应用程序应将配置文件加载到FPGA中。 同时,我们的意思是可以将多个FTDI同时连接到计算机,其中一些FTDI可能用于配置FPGA。 我建议从下拉列表中选择设备,通过带有路径输出的按钮选择文件。 要开始下载,请添加“程序”按钮。 虚拟LED将指示操作状态。 启动LabVIEW。
将所需元素添加到前面板(Front Panel)。 我将为副总裁使用“银色”样式。 下图显示了结果,所有元素均处于原始状态。 通过名称,如果有必要,它们很容易在调色板中找到。

我们编辑元素:我们转移,拉伸,添加题词-我们将其带到所需的形式。 实际上,这里需要设计师的手,但是我可以:

和框图:

我引起你的注意。 每个元素都有两个用于确定名称的属性-标签和标题。

第一个属性设置元素的名称,以该名称显示在程序框图上。 与Caption不同,Label在VI执行期间无法更改。 结合此功能,建议您在前面板的VI中隐藏标签并显示标题。 对于Label,想出一个有意义的名称,作为经典编程语言中的变量,最好是拉丁布局。 对于Caption,我们将引入一个以人为本的名称,该名称可能会很长,包括空格,并在必要时使用俄语。 使用LabVIEW,您可以自定义标题的显示字体。 我必须说,没有人会迫使我们惹上字幕:任何题词都可以在任何自由地方直接在FP上进行。
我们根据经典方案实现VP操作:While循环和事件处理程序。 While
程序框图中添加一个While
循环(编程->结构-> While循环),并添加一个事件处理程序结构(编程->结构->事件结构)。
事件结构的简要帮助该结构等待事件发生,然后执行相应的处理程序。 事件的结构具有一个或几个子图-事件处理程序,即所谓的案例,在事件发生时执行其中一种。 使用左上角的终端,您可以指定结构预期发生事件的毫秒数。 如果在此期间未发生任何事件,则将执行“超时”子图。 默认值为负1,表示超时永不过期。

- 事件选择器标签指示哪些事件触发了当前案例。 要查看其他处理程序,可以单击事件名称旁边的向下箭头。
timeout
终端设置等待事件的毫秒数。 如果该值不是-1,则必须实现“超时”子图。- 用于输入动态事件的终端。 默认情况下不显示此终端。 要显示它,请在上下文菜单中选择“显示动态事件终端”。
- 事件数据节点。 事件发生时,LabVIEW将生成与此事件相关的数据。 该节点将此数据提供给处理程序。 您可以使用鼠标垂直调整节点的大小并选择必要的元素。 一些数据(例如
Type
和Time
对于所有事件都是通用的,而其他数据(例如Char
和VKey
)则取决于所配置事件的类型。 - 事件过滤器节点定义事件数据,您可以在用户界面处理该数据之前对其进行修改。 该节点仅显示在可进行过滤的处理程序中。 您可以将项目从事件数据节点连接到事件过滤器节点并将其更改。 您也可以通过将新值连接到节点终端来更改这些事件。 如果我向
Discard?
终端提交了true
,是否可以完全取消接口对事件的反应Discard?
。 如果未将值连接到过滤器元素,则此数据元素保持不变。 - 与
Case
结构一样,事件结构也支持隧道。 如果在一种情况下添加隧道,则会为每个处理程序自动创建该隧道。 但是,默认情况下,不需要在每个处理程序中连接事件结构的输出隧道。 所有未连接的隧道均使用默认值作为隧道数据类型。 潜在地,这可能导致难以检测的错误。 您可以返回在所有处理程序中都应以有线方式连接隧道的模式,为此,请在上下文菜单中选择“使用默认,如果未有线”。
首先,我们将注意循环如何结束和退出程序。 最简单的方法是添加一个停止按钮,该按钮将停止循环,但是我认为习惯上是在窗口的右上角用一个红色的叉结束该程序。
将适当的处理程序添加到Event Structure
。 在上下文菜单中,选择“添加事件案例”。 作为事件的来源,选择“ This VI”,事件指示“ Panel Close?”。
编辑活动
可点击的图片
请注意,如果选择“面板关闭”(没有问题),则此事件没有过滤器,因此无法撤消。 如果有问题,那么当您单击十字架时,我们可以控制并独立正确地完成程序。 在“面板关闭?”中 通过隧道,我们将布尔常量true
与终端连接,以停止while
。 输入“放弃?” 也做到了。
现在没有明显的细微差别:如果当前的VI不是在LabVIEW环境中启动的,而是以已编译应用程序的形式启动的,则单击叉号不会关闭窗口,而是会停止应用程序,这是我们不需要的。 为了解决这个问题,在主循环完成之后,我们将检查我们是处于开发环境还是处于程序模式,如果仍处于程序模式,则将结束应用程序。 为了了解当前VI的运行位置,请使用属性节点(编程->应用程序控制->属性节点)。 该节点通过引用该对象提供对对象属性的访问。 在这种情况下,我们应该获得整个应用程序的链接。 从同一选板中选择VI Server Reference
常量。 将常量设置为框图后,需要将其类型更改为“ This Application
(鼠标左键)。 我们将结果链接与属性节点连接。 选择Application:Kind Property
属性Application:Kind Property
-返回运行当前VI的LabVIEW系统的类型。 我们将属性的输出连接到案例结构,添加“运行时系统”案例,在此结束应用程序( Quit LabVIEW
)。 为了使该块在循环之后而不是之前执行,我们将输入端子error in
通过隧道连接到循环中。

可点击的图片
现在,当您启动程序时,可以通过单击窗口的十字架来停止它。 启动的程序如下所示:

在我看来,很多多余的。 进入VI属性(文件-> VI属性菜单),选择“窗口外观”类别,设置自定义。
关闭菜单的显示(它保持在编辑模式),关闭滚动条,在应用程序运行时隐藏工具栏(运行时显示工具栏)。 我们禁止调整窗口大小,我们允许最小化和最小化窗口。 更好:

当然,删除“ National Instruments。LabVIEW Evaluation Software”字样是值得的,但是我还不想购买家用计算机的许可证,我们将忍受该字样并管理45天的试用期。
自然地,您可以调整背景颜色和每个元素,选择字体,但是我不是设计师,但是有些事情告诉我,我只会使它变得更糟。
仪器清单
VP应该向用户提供适合于FPGA固件的连接到计算机的设备列表,以便用户可以选择所需的设备。 在FTD2XX库中, FT_CreateDeviceInfoList
和FT_GetDeviceInfoDetail
函数用于此目的。 如前一篇文章所述 ,驱动程序库可用于使用FTD2XX API。 LabVIEW提供了一种与动态库进行交互的便捷机制-“调用库功能节点”节点,可在“连接性->库和可执行文件”选项板中找到。 应该配置函数调用节点:首先,指定dll的路径(“函数”选项卡),然后系统扫描库并提供在“函数名称”列表中选择函数名称的方法-选择FT_CreateDeviceInfoList
,调用约定-选择stdcall(WINAPI) 。 其次,在“参数”选项卡上,您需要输入功能参数列表,其中列表的第一个元素是返回值。 在这里最好记住API文档或头文件。 在“功能原型”区域中设置参数时,将显示导入功能的原型。 当文档中的签名与配置的原型匹配时,单击“确定”。
假设扫描应该每秒执行一次。 我们将调用节点放置在“超时”选项卡上事件处理程序的结构中,将等待时间设置为1000毫秒。 我们在节点引脚上添加了指示器,如果一切都正确完成,则在启动VI时,应显示已连接FTDI的设备数量:
前面板和框图
可点击的图片

同样,为FT_GetDeviceInfoDetail
函数创建一个节点。 该函数的原型是:
FTD2XX_API FT_STATUS WINAPI FT_GetDeviceInfoDetail( DWORD dwIndex, LPDWORD lpdwFlags, LPDWORD lpdwType, LPDWORD lpdwID, LPDWORD lpdwLocId, LPVOID lpSerialNumber, LPVOID lpDescription, FT_HAN
在描述参数时,应注意lpdwFlags
, lpdwType
, lpdwID
, lpdwLocId
作为指针传递给uint32
。 参数lpSerialNumber
和lpDescription
是字节字符串(具有空终止符的char
数组)的本质。 调用节点中的此类参数可以通过各种方式设置格式,您可以将其输入8位字的数组中,但是我认为最方便的是立即表明这是一个字符串并设置期望的大小。 在这种情况下,输出将立即是有效的“迷宫”行,并且不需要其他转换。

调用库功能
此函数通过dwIndex
序列号返回信息。 如果将多个FTDI连接到计算机,则为了读取每个转换器的信息,必须循环调用该功能。 循环的迭代次数将由先前的函数FT_CreateDeviceInfoList
。
前面板和框图
可点击的图片

有一个不愉快的功能:呼叫节点的所有端口必须至少在一侧连接。 因此,在环路中为不打算使用的输出端子建立了隧道。
Types
数组包含FTDI芯片类型,我们需要它们以将选择范围限制为仅支持MPSSE,并且有可能用于FPGA编程。 但是,使用“幻数”操作不方便-我建议以enum
的形式排列FTDI类型。 而且,这样的enum
已经在ftd2xx.h头文件中。 在LabVIEW中,可以使用两个控件来创建枚举:文本环和枚举本身。 两者都包含带有数字值的字符串列表,可以在它们之间进行切换。 主要区别在于“枚举”要求数字值是连续的整数,而“文本环”具有更大的自由度-您可以指定任何值。
枚举 创作
我们手动输入值,很遗憾没有从C导入enum
函数

在前面板上,该指示器如下所示

左键选择一个值
为了链接和同步创建列表的所有未来实例,使用“ Make Type Def”很方便。 (通过项目上下文菜单选择)。 结果,将创建一个自定义数据类型。 新类型放置在扩展名为* .ctl的单独文件中。 编辑此文件将修改此元素的所有实例。 我认为不应该解释这样做有多方便。 可以从实例的上下文菜单中选择“打开Type Def”来访问定义文件,在同一菜单中,您应注意“从Type Def自动更新”项。 和“从Type Def断开连接”。
我们将Types
指示器更改为FTDI Type
的指示器数组,因此,当VI启动时,将显示所连接转换器的类型:

找到三个设备
很容易注意到,在“超时”情况下,结果代码的功能已经完成,因此可以将其移至单独的SubVI。 选择我们要传输到子设备的元素,然后从主菜单“编辑”中选择“创建SubVI”。
已创建子仪器的框图所有指示均保留,并形成了一个带有标准图标的新VI来代替调用节点。

可点击的图片
双击新的子VI将启动其编辑窗口。 首先,我们将其保存并给出一个有意义的名称,例如“ FT_GetDeviceInfo”。 设置I / O端子。 为此,请使用连接器窗格:

面板是一组对应于控件和指示器VI的端子。
如果在连接面板上选择一个端子,则前面板上的相应元素将突出显示。 如果选择一个空终端,然后单击前面板上的元素,则该元素将附加到终端,但是在此之前,不应将其分配给其他终端。 在上下文菜单中,您可以单独或立即断开端子与元素的连接,还可以更改整个面板的样式。
我不喜欢创建当前子VI时如何分配端子,所以我选择“断开所有端子”并手动标记。 我建议将输入端子放在左侧,将输出放在右侧,可以将可选输入放在顶部,而将可选输出放在底部。 这样可以确保程序框图具有良好的代码可读性和视觉顺序。
要控制错误,请创建两个附加元素: Error in
和Error out
。 LabVIEW的错误控制主题非常广泛,已经超出了本文的讨论范围,因此,我们将自己限制在最低限度的解释范围内,并坚持“按我做”的原则。 因此,我们为错误创建了两个终端-输入和输出。
使用上下文菜单创建它们很方便右键单击任何节点的错误终端:

在LabVIEW中,通常将错误的输入端子放在连接面板的左下方,而输出端子放在右下方。
将输出组合到一个结构中会更加方便。 对于输出,我们将创建两个阵列:第一个阵列将包含找到的所有FTDI器件,第二个阵列将仅包含那些可以进行MPSSE的器件,并且理论上可以用于配置FPGA。
创建子乐器时的最后一步是配置图标。 双击窗口右上角的图标将启动编辑器。 我们正在尝试创建某种有意义的图像,以使我们能够在框图中明确解释设备的用途。
FT_GetDeviceInfo.vi
前面板

方块图
这是将事物整理好后的“超时”情况的样子:

可点击的图片
到目前为止,名称为“选择设备”的下拉列表为空,现在我们可以填充数据。 我们使用属性“ Strings []”为列表创建一个属性节点(上下文菜单->创建->属性节点->字符串[])。 任何属性都是可写和可读的;在属性节点的上下文菜单中选择当前模式。 默认情况下,在创建节点时,将属性配置为读取。 更改为写:“更改为写”。
从结构数组中,选择带有说明的数组,并将其提供给Strings[]
。 您可以使用For Loop
选择一个数组。
启动VI后,按下元素“选择设备”上的左键,即可指定要配置的设备。 在这种情况下,设备列表每秒更新两次。 当然,只有在列表已更新的情况下,才有可能更新属性,但是到目前为止,这将导致不必要的框图混乱。
怎么了
前面板

可点击的图片
之前,我忘了提到这样一个有趣的功能,For循环不必显式指定迭代次数,创建数组的输入隧道就足够了,并且该循环将对每个元素执行,此行为类似于C ++ 11中的foreach
。 但是,当多个数组到达循环输入时,您需要小心。
在事件结构中,添加一个用于按下“程序”按钮的处理程序。 虽然我们没有负责将文件加载到FPGA的VI,但我们将创建一个子设备“存根”。 假设它将配置文件的路径和FTDI描述符作为输入,并根据操作结果返回固件状态:成功与否。 为了使测试程序界面更有趣,我们将使此状态随机化。
存根FT_MPSSE_SP_FPGA.vi
前面板

方块图
我们将通过列表属性(上下文菜单->创建->属性节点->环形文本->文本)将FTDI描述符传递到存根输入,以将文件路径传输到“文件路径”元素,创建一个本地变量(上下文菜单->创建->本地)变量)并将其设置为已读(更改为已读)。 并将状态输出直接连接到Status
指示器。 将“ Programm
按钮拖到事件处理程序中。 优良作法是将在其上配置了事件的元素放置在处理程序中-现在双击前面板上的该元素将不仅在程序框图中显示相应的元素,而且还显示与该元素关联的事件处理程序。
现在,通过按下“程序”按钮,指示器变为绿色(成功)或深绿色(不成功)。 不太清楚。 在指示器属性中,将颜色“关”更改为红色。 这样更好 如果指示灯为绿色,则可以说所选设备上的FPGA由文件配置,该文件的路径在窗口中指示:

前面板
但是,如果我们更改文件或选择其他设备,则此语句将为false。 同时,由于没有发生编程错误,我们不能将指示器变成红色。 如果文件或设备发生更改,可以方便地强调指示符值无关紧要-将其变暗。 为此,您可以使用“ Disabled
指示器属性。 此属性可以采用三个值: Enabled
-正常显示,用户可以控制对象; Disabled
-该对象照常显示在前面板上,但是用户无法控制该对象; Disabled and Grayed Out
-前面板上显示的对象变暗,用户无法控制该对象。
我们为Devices list
和File Path
创建事件处理程序,并在其中使状态指示器变暗,在处理程序中,将“程序”按钮分配给Enabled
属性。
发生什么事了
“程序”处理程序:值更改。

设备列表处理程序:值更改

这是变暗的指示器的外观
让我们方便用户搜索配置文件-我们将配置文件视图窗口。 转到“ File Path
元素的属性,在“浏览选项”选项卡上,填写“提示”,“模式标签”,指定文件类型过滤器(“模式”)和按钮的名称(“按钮文本”)。
文件选择窗口
仅显示rbf文件

创建用户界面可以认为已完成。

运行引导程序
你今天见什么?
在本文中,以创建具有简约界面的功能完整的应用程序为例,我试图展示各种在LabVIEW中工作的方法。
结果,我们涉及到以下内容:
API FTD2XX MPSSE. .
- 通过USB将配置下载到FPGA或拆卸FTDI MPSSE
- labview_mpsse . .
- .
- Software Application Development D2XX Programmer's Guide . API D2XX.