基于LabVIEW应用1394板卡实现数据通信(四)——实现节点间数据通讯
具体的数据交互过程如下图所示,上面的循环是CC发送消息,下面的循环是RN接收消息,为了避免RN在监控接收消息的过程中出现错误数据(原因是,当CC节点没有发送数据时,RN节点如果读取消息,则会给本帧数据全部填零,造成数据资源冗余),在该参数设置下定时循环跑2千次,只有六百个有效数据,其余均是填充0的冗余数据。第2列的第11个数据“0”为健康状态(处于消息数据字0)第2列的第12个数据“1”为心跳字(
4.LabVIEW调用库函数操作板卡实现功能
(1)函数使用方法
使用LabVIEW调用板卡提供的库函数来实现功能其方式和使用板卡自带软件实现数据交互的方式基本一致,但在调用板卡是需要严格遵循板卡函数调用规则,函数的调用流程图如下图16所示:

图16 函数调用流程图
说明:
1. MIL1394_Find_Device,查找系统板卡数量,判断当前系统是否存在板卡;
2. MIL1394_Open 打开板卡,只有打开后板卡才能正常工作;
3. MIL1394_Bit 节点自检工作,如三节点卡可判断每个节点是否正常工作;
4.节点初始化(CC,RN,BM),其中 CC 和 RN 可以配置周期性发送消息及接收消息功能;
5. MIL1394_Start 启动节点工作,启动后,板块周期性运行配置工作;
6. 板卡启动后,可使用 MIL1394_Receive 读取消息,可定时或自定义方式使用;
7.MIL1394_Transmit 更新初始化配置的消息,可获取发送消息次数等功能;
8.MIL1394_Stop板卡指定节点停止工作。 对于CC节点,将不再发送STOF包和消息;对于RN节点,将不再接收STOF包和消息。
9.MIL1394_Close释放板卡资源并关闭板卡。
在LabVIEW中使用“调用库函数节点”函数,双击后进入如下界面17所示,在库名/路径中找到调用库函数的dll文件,在函数名处选择需要使用到的函数。操作完成后点击确定,退出该界面。

图17 调用库函数
在该VI中创建出板卡使用的多个动作,在每个动作下绑定对应的库函数,具体的编写如下图18所示:

图18 函数实现内容
这样就完成了板卡的应用,在软件运行中,需要板卡发生某个动作只需要触发该动作下的库函数即可。
(2)模拟CC-RN节点间数据通信
模拟CC-RN节点间交互任务,使用到了同一块板卡的两个节点来做数据通讯。连接好两个节点后,这里我们设置节点0为CC模式,节点1为RN模式。在数据交互之前我们需要配置板卡的各个重要参数,这个步骤中很多函数的调用是不必可少的,具体的使用方法如下图19所示。当然节点不同也存在不一样的配置细节,但大体的步骤都是一样的。

图19 参数设置过程
在具体的节点参数配置过程中,需要节点初始化,发送和接收消息初始化等,由于CC-RN节点之间是可以互相通信的,所以两个节点都可以进行发送接收消息初始化。
参数配置结束之后就可以进行数据通信了,这里以“CC发-RN收”为例,CC节点的发送消息初始化需要锁定目的通道(RN节点初始化的通道)、消息ID,RN节点的接收消息初始化需要与CC节点发送的消息ID一致,否则接收不到数据。具体的数据交互过程如下图所示,上面的循环是CC发送消息,下面的循环是RN接收消息,为了避免RN在监控接收消息的过程中出现错误数据(原因是,当CC节点没有发送数据时,RN节点如果读取消息,则会给本帧数据全部填零,造成数据资源冗余),在该参数设置下定时循环跑2千次,只有六百个有效数据,其余均是填充0的冗余数据。
为了避免这种现象,我们在进行读取数据之前先进行判定,如果RN接收到了新的数据,那么进行读取。如果没有接收到新的数据,则不读取,保持上一次的数据状态直到有新的数据发送过来。

图20 数据通信过程
可以看到,在程序数据下发处将第0个元素从数值0改成了获取计算机启动以来所经过的毫秒数,如下图所示21所示,每一行为一帧数据在一直自加的心跳字(249到264)之后的数据就是负载数据。

图21 数据读取结果
(3)读取数据的元素分析
在这里我们对1394板卡规定的异步流数据包中相关位的定义与我们实际设置读取的数据进行对比分析,以便我们更好理解该板卡下对数据包的定义,另外我们也可以以板卡的数据包定义佐证采集数据的正确性。
本次数据帧分析是基于单节点CC模式下自发自收进行的,基于前面内容的铺垫,我们知道在1394板卡进行数据通讯之前,需先进行节点初始化、写入消息初始化、读取消息初始化已经更新消息等操作,这里我再将一些设置中需要特别留意的重要参数做简单介绍。

图22 CC节点初始化
本次测试中对CC节点初始化过程中,如图22所示,设置CC节点通道为0(系统默认),速度代码选择2(400M),STOF周期选择12500。
CC节点初始化结束后,接下来进入到CC发送消息配置和CC接收消息配置。
首先在CC发送消息配置中,这里选择发送十条消息,该十条消息是通过消息ID进行区分的(消息ID:101、2......10);目的通道选择1,负载长度选择100、200、400不等,以便后续可以直观看到数据效果;消息类型选择2(表示周期消息);这里需要特别注意一点,发送偏移需要大于50,该参数的作用是假如某节点收到了一个消息设置发送偏移为100的数据包,则会在收到STOF包后100ns后发送这个消息进行通信。而接受、数据泵、实际发送偏移对数据发送没有任何影响,只是消息里面填入的数据。具体设置的效果如下图23所示。

图23 发送消息初始化
其次在CC接收消息配置中,如下图24所示,该参数也是10个元素,只需要设置好正确的消息ID与CC发送消息配置中的对应即可。

图24 接收消息初始化
另外在更新消息中,我们这里选择前五条消息进行更新,具体做法是按照消息ID,对指定的消息内容进行更新,消息更新长度不会超过初始化发送消息中的有效负载长度。对于周期消息,消息更新后消息内容将以最新负载内容周期性发送,直到下一次更新为止;消息内容指纯负载内容,不包括健康状态字和心跳字。更新的消息设置如下图25所示。

图25 更新消息
将以上信息配置完后,运行程序,即可进行单节点CC模式自发自收的测试,采集到的数据如下图26所示。

图26 读取的数据包
可以看出,每一列即是读取到的一帧数据包,其中蓝色圈中的列是STOF数据包,绿色圈中的列是10个消息的数据包。按照下图25所示的接收消息头结构我们对采集到的一帧数据的每一个元素做一个详细解析。图26中数据包中的元素与图27中接收消息的头结构说明是对应的。

图27 接收数据头结构
首先在图26中第1列中的第0个元素“22287”与接收消息头结构的说明进行计算对比,经过转换可知十进制的22287转化为十六进制为570F很显然说明本消息为STOF消息,同理对第二列中的第一个元素“1151865748”将其转换为十六进制便知该消息为常规消息。具体关系如下图28所示。

图28 进制转换
由于STOF包不包含数据负载部分,起不到典型的说明作用,接下来我们选择在图26中第2列的信息进行分析,第二列的第1个元素对应的是消息状态,其具体位的对应说明如下图29所示。

图29 消息状态结构
这里我们以第二列的数据“1610678327”为例解析,该数据转化为二进制后为“0110 0000 0000 0001 0000 0000 0011 0111”(从左到右依次为31位至0位)。由此可见VPC状态有效(改包为流包),数据CRC、头CRC状态正常,速度代码为10即为400M(这里和CC初始化在速度代码设置为2相匹配)。消息SVPC状态有效。数据包状态指示正常。消息符合1394包和5643标准。
在图26中第1列中的第2个元素“1001”对应的是消息接收小时包(以最近的STOF数据包作为起始时间),由于该板卡的时间默认单位是100ns可以看出隔100us发送一帧数据,十组数据在1000us中发送完毕,剩下11500us不发送数据,直到下一个周期。
在图26中第1列中的第3个元素“160”对应的是消息长度,该长度包含消息头长度,这个数据的计算与后面的数据长度、负载长度计算方法一致,这里显示长度160,则一帧数据有40(160/4)个元素,对应到图24中即就是一列(一帧数据)有40行。
在图26中第1列中的第4个元素“1073741869”转化为二进制为“0100 0000 0000 0000 0000 0000 0010 1101”,其中第高4位表示当前消息是否为经过接收过滤标的消息。第16位表示消息接收是标高16位,以板卡上电或复位后为起始时间。
在图26中第1列中的第5个元素我们以图30解析,下图中每一行为一帧数据,其中第五列就是对应的该元素,我们以消息ID“101”的两次不同的第5个元素相减得到了125000,(红色圈中的两个数值),这便是一个周期的时间。由于该板卡的时间默认单位是100ns,因此乘以0.1得到的值便是在图22中CC节点初始化配置的STOF周期12500。

图30 周期数据解析
第6个元素对应的是1394异步流数据包包头,前面在异步流数据包结构中可以知道1394数据包头包括数据长度(16-31位)、标签(14-15位)、通道(8-13位)、事务代码(4-7位)、同步码(0-3位)。这里我们以第二列的第七个数据“8651168”为例解析,该数据转化为二进制后为“1000 0100 0000 0001 1010 0000”,可以得到它的数据长度为132(十进制),通道为1(目的通道),事务代码为A(异步数据流包事务代码)。具体的对应关系如下图31所示。

图31 数据包头代码结构
第7个元素往后即就是1394内容的开始,首先我们以第2列的第8个数据“101”可知,该位置便是消息ID,查阅前面的图7(异步流数据包使用格式)也可知该位置即为消息ID。
同理第2列的第8个数据“0”为安全字,第2列的第9个数据“1”为节点ID,第二列的第10个数据“100”为优先级(24-31位)和消息负载长度(0-23位),其中消息负载长度为100,这也与我们在消息发送配置中设置的负载长度一致。
第2列的第11个数据“0”为健康状态(处于消息数据字0)第2列的第12个数据“1”为心跳字(处于消息数据字1),第2列的第13个数据“0”开始即为消息数据(处于消息数据字2至消息数据字负载长度-1)。
以负载长度100为例,该负载长度100除以4得到的值(25)才是对应的图26(读取的数据包)的每一个元素,具体是从第11个数据到第35个数据,25个长度,效果如下图32所示。另外在板卡自带的软件中也可以清楚地看到这一关系,如下图33所示。

图32 负载长度对应位置

图33 自带软件中字段显示位置
最后继续介绍几个参数分别是STOF发送偏移、接受偏移和实际发送偏移,以图29第4列为例,该列的消息ID为3,在图23 发送消息初始化中分别设置这三个参数为300、400和500,分别对应着第4列第36个元素、第4列第37个元素、第4列第38个元素。
最后一个元素VPC以第4列为例,即就是第39个元素。
负载长度如此计算,前面提到的1394数据头包中的数据长度的计算方法也是如此,十六进制下的84转化成十进制下的132,然后除以4得到的便是数据包该有的大小。如下图34所示,数据长度应该有33个大小。即从消息ID到VPC数据长度为33。
(总结:异步流数据包中涉及到长度的三个参数以消息ID-101为例,消息长度:40、数据长度:33、负载长度:25)。


图34异步数据包布局显示
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐


所有评论(0)