便携式航电实时系统测试平台实时脚本(C++)扩展API

第一章 实时脚本(C++)扩展API

实时脚本在ETest中作为下位机脚本,运行在VXWorks环境下。

实时脚本为C++脚本,符合C++ 17规范。

同时,实时脚本还带有ETest提供的扩展API,提供了一系列服务和支持。本章主要介绍这些扩展API。

1

1

2

3

4

5

6

1

1.1 接口操作

本节介绍对ETest下位机接口设备硬件进行操作,完成通信的接口API。

所有接口类均在命名空间 Kiyun::LowerComputer::Rasl::Device 中。

所有接口都采用设备与通道两层结构,通道统一命名为 Channel_T,作为设备的内嵌类。如串行通信口,类名为 Com_T,其通道为 Com_T::Channel_T。

每个接口的方法主要有两组,分别是 read/write 和 intRead/asyncWrite。其中前一组是阻塞式读/写,后一组是异步(非阻塞式)读/写。其中,异步读/写均为立即返回,不等待读写操作完成;读/写完成后调用回调函数。注意有的设备没有异步读/写API。

在正常使用中,接口对象由 ETest 根据测试连接图自动构造,并以图中的通道名为对象名,可在代码中直接使用。

1.1.1 AD接口

使用模数转换通道主要用到的类型是Ad_T类型。本节对模数转换通道进行介绍。

本节所描述的类型所在命名空间均为:Kiyun::LowerComputer::Rasl::Device。

1.1.1.1 使用方法及范例

在ETest系统中,模数转换操作主要由Ad_T::Channel_T类型完成。

在使用ETest进行仿真模型设计和设备规划过程中,可以建立模数转换通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建Ad_T::Channel_T类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的采集操作。

如,在以下范例中,对象f_ad即为Ad_T::Channel_T类型的对象,可以用来完成模拟量采集功能。

单次采集:

编辑

添加图片注释,不超过 140 字(可选)

单次采集多个点:

编辑

添加图片注释,不超过 140 字(可选)

连续采集:

if (!f_ad.isValid()) {
KYIO(err) <<
"AD channel initial failed.";
return -1; //返回值需要根据该代码片段所处函数返回值类型设定
}
if (f_ad.isRunning())
{
KYIO(err) << "AD
channel is sampling.";
return -2; //返回值需要根据该代码片段所处函数返回值类型设定
}

Os::Semaphore_T semAd; //需引入"Kiyun::LowerComputer::Rasl"命名空间
f_ad.intRead([&](float* buf, size_t size,
Error_T error) {
if (error) {
KYIO(err) << "Occur
errors in intRead:" <<
error.message();
return false;
}

//通过发送信号量的方式终止连续采集任务的执行,需自行给定终止的条件
/*
if(...){
semAd.notifyOne();
return false;
}
*/
return true; //返回true时会一直执行连续采集直到采集出错或有其他的终止条件
}
);

f_ad.start(); //开始连续采集
semAd.wait(); //等待信号量,接收到信号量后终止连续采集任务
f_ad.stop(); //停止连续采集

1.1.1.2 Ad_T类

本类型是模数转换操作类型。它包含了IntReader_T类型和Channel_T类。

1) IntReader_T类型

在进行中断读取的时候,需要用到一个函数类型作为参数,当读取操作完成的时候,本函数会被调用。

类型定义为:

typedef std::function<bool(float*,size_t,Error_T)> IntReader_T;

1.1.1.3 Ad_T::Channel_T类

本类型的对象是进行AD采集的主体。具有以下方法:

1) isValid方法

检测通道是否有效。强烈建议使用前判断通道合法性。

函数原型:bool isValid() const

参数说明:无

返回值:true:通道有效,fasle:通道无效

1) path方法

返回通道的标识,可用于在数据上传时构造上传通道。

函数原型:Path_T path() const

参数:无

返回值:通道标识符(类型参加“通用类型介绍”)。

2) read方法一

采集一次数据。

函数原型:float read()

参数:无

返回值:采集到的数据

3) read方法二

多次同步采集数据。采集点数越多,函数返回时间越长。

函数原型:BOOL read(float* buf, size_t size)

参数:buf:存放采集到数据的地址;size:buf的长度(采集点数)

返回值:操作是否成功

4) intRead方法

进行通道注册连续采集。连续采集工作与单次采集工作不能同时进行。

函数原型:void intRead(const IntRead_T& hdl)

函数功能:

参数:hdl:回调函数,函数返回值表示“是否继续接收”,true继续,false停止;

返回值:无

5) isRuning方法

判断是否存在连续采集任务。

函数原型:BOOL isRuning()

参数:无

返回值:TRUE:存在连续采集任务,FALSE:不存在连续采集任务

6) start方法

开始连续采集任务。

函数原型:BOOL start()

参数:无

返回值:TRUE:成功打开或者已经存在任务,FALSE:打开失败

7) stop方法

停止连续采集任务。

函数原型:BOOL stop()

参数:无

返回值:TRUE:成功关闭或者不存在连续采集任务,FALSE:关闭失败

8) reset方法

重置连续采集通道

函数原型:BOOL reset ()

参数:无

返回值:TRUE:成功清除已注册的连续采集通道,FALSE:重置失败(采集任务正在进行)

1.1.2 DA接口

使用数模转换通道主要用到的类型是Da_T类型。本节对数模转换通道进行介绍。

1.1.2.1 使用方法及范例

在ETest系统中,数模转换操作主要由Da_T::Channel_T类型完成。

在使用ETest进行仿真模型设计和设备规划过程中,可以建立数模转换通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建Da_T::Channel_T类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的采集操作。

如,在以下范例中,对象da即为Da_T::Channel_T类型的对象,可以用来完成模拟量转换输出功能。

int kiyunMain() {
if(!da.isValid())
{
KYIO(err) <<
"DA channel initial failed.";
return -1;
}
da.write(5.0);

Timer_T::delay(5);// Da 保持输出5s

da.stop();// 禁止输出(Da退出会自动调用)
return 0;
}

1.1.2.2 Da_T::Channel_T类

本类型所在命名空间为:Kiyun::LowerComputer::Rasl::Device,是进行DA转换的主体。具有以下方法:

1) isValid方法

检测通道是否有效。强烈建议使用前判断通道合法性。

函数原型:bool isValid() const

参数:无

返回值:true:通道有效,fasle:通道无效

2) path方法

返回通道的标识,可用于在数据上传时构造上传通道。

函数原型:Path_T path() const

参数:无

返回值:通道标识符(类型参加“通用类型介绍”)。

3) write方法

设置输出幅值。

函数原型:void write(float value)

参数:value:输出幅值(电压值)。

返回值:无

注:Da32(AECDA-CPCI-32)写操作需要延迟 25ms,Da8(AECDA-CPCI-8-S2)输出间隔应至少1us

4) start方法

开始DA输出。

(write方法会自动调用start方法开始输出)。

函数原型:void start()

参数:无

返回值:无

5) stop方法

停止DA输出。之后可以调用start方法重新启动输出。

函数原型:void stop()

参数:无

返回值:无

1.1.3 串口

使用串口总线主要用到的类型是COM_T类型。本节对串口总线操作进行介绍。

1.1.3.1 使用方法及范例

ETest系统中,串口总线操作主要由Com_T::Channel_T类型完成。

在使用Etest进行仿真模型设计和设备规划过程中,可以建立串口总线通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建Com_T::Channel_T类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的采集操作。

如,交联环境如下配置:

编辑

添加图片注释,不超过 140 字(可选)

对象com0和com1即为Com_T::Channel_T类型的对象,可以用来完成串口总线功能。

示例代码如下:

/** 系统固定头文件 */
#include <Rasl/rasl.hpp>
#include <DataUploader/DataUploader.hpp>
#include "StaticVariable.h"
#include "rasl-dpd/user.hpp"
#include "UserChannels.rasi"
#include "DataCollect.hpp"
/** 系统固定头文件 */

//用户测试代码需要新增的头文件

namespace{
using
namespace Kiyun::LowerComputer;
using
namespace Kiyun::LowerComputer::Rasl;
using
namespace
Kiyun::LowerComputer::Rasl::Frame;
using
namespace
Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间
using
namespace
Kiyun::LowerComputer::DataUploader; //数据上传命名空间
using
namespace Kiyun::Channel;
using
namespace Kiyun::DataCollect; //数据采集接口命名空间
using
namespace Dpdp; //协议命名空间

//本地变量、本地函数声明
//Os::Semaphore_T
f_exitSem;
Os::Semaphore_T readDone;
std::string rs;
// 返回值表示“是否继续接收”
bool reader(char* buf, size_t size,
Error_T) {
std::string
temp(
buf, buf +
size);
rs += temp;
auto done =
rs.size() >= 7;
if (done)
readDone.notifyOne();
return !done;
}

void
whenWriteDone(size_t size,
Error_T) {
KYIO(log) <<
"Write done : " << size;
}

int
sync_rw() {
std::string
ws = "abcdefg";
com0.write(ws.data(),
ws.size());//同步写
std::string
rs(7, '\0');
com1.read(&rs[0], rs.size());//同步读(定量字节)
KYIO(out) <<
rs;
return 0;
}

int async_rw() {
com1.intRead(reader);//注册中断读
std::string
ws = "abcdefg";
//异步写
com0.asyncWrite(ws.data(),
ws.size(), whenWriteDone);
readDone.wait();
KYIO(out) <<
rs;
return 0;
}

}

//主函数入口
int Main()
{
//设置全局日志属性
KYLOG_GLOBAL().severity(Logging_T::Severity_E::TRAC_e);
KYLOG_SCOPE("ETestRT::Main").tag("发送").tag("检查");
KYLOG(INFO) << "Hello
world, Kiyun!\n"; //可保存到日志文件
KYIO(log) << "Hello
World,Kiyun!\n"; //发送到控制台

/*测试代码*/
if(!com1.isValid())
{
KYIO(err) <<
"COM232 channels initial failed.";
return -1; //返回值需要根据该代码片段所处函数返回值类型设定
}

KYIO(log) <<com1.path();

sync_rw();
async_rw();
//f_exitSem.wait();
return 0;
}

bool Exit(Os::Task_T)
{
//返回值为true,表示能中止正在运行的实时任务
//f_exitSem.notifyOne();
//return true;

return false; //默认情况下该实时任务不能被中止
}

1.1.3.2 Com::Channel_T类

本类型所在命名空间为:Kiyun::LowerComputer::Rasl::Device,是进行串口总线操作的主体。具有以下类型和方法:

1) isValid方法

检测通道是否有效。强烈建议使用前判断通道合法性。

函数原型:bool isValid() const

参数:无

返回值:true:通道有效,fasle:通道无效

2) path方法

在进行数据上传时获取通道标识。

函数原型:Path_T path() const

参数:无

返回值:通道标识符

3) WriteHandler_T类型

typedef std::function<void(size_t, Error_T)> WriteHandler_T;

4) asyncWrite方法

异步输出。

函数原型:void asyncWrite(const char* buf, size_t size, WriteHandler_T whenDone)

参数:buf:输出数据的首地址;size:数据长度;whenDone:回调函数。

返回值:无

5) IntRead_T类型

typedef std::function<bool(char*, size_t, Error_T)> IntReader_T;

6) intRead方法

中断读。读取结束时调用参数中的回调函数。

函数原型:void intRead(const IntRead_T& hdl)

参数:hdl:回调函数,函数返回值表示“是否继续接收”,true继续,false停止

返回值:无

7) read方法

同步读。

函数原型:Error_T read(char* buf, size_t size, Timeout_T timeout = 1_s)

参数:buf:存放输入数据的地址;size:读取的字节数;timeout:超时等待时间,默认为1s

返回值:错误码

8) write方法

同步写

函数原型:Error_T write(const char* buf, size_t size, Timeout_T timeout = 1_s)

参数:buf:存放输出数据的地址;size:输出的字节数;timeout:超时等待时间,默认为1s

返回值:错误码

9) clear方法

清除缓冲区

函数原型:void clear();

参数:无。

返回值:无。

10) empty方法

判断缓冲区是否为空

函数原型:bool empty();

参数:无。

返回值:布尔型,是/否为空。

1.1.4 CAN

使用CAN总线主要用到的类型是Can_T类型。本节对CAN总线操作进行介绍。

1.1.4.1 使用方法及范例

在ETest系统中,CAN总线操作主要由Can_T::Channel_T类型完成。

在使用ETest进行仿真模型设计和设备规划过程中,可以建立CAN总线通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建Can_T::Channel_T类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的采集操作。

如,交联环境图按照下图配置。

编辑

添加图片注释,不超过 140 字(可选)

对象f_can1和f_can2即为Can_T::Channel_T类型的对象,可以用来完成CAN总线功能。

示例脚本如下:

/**
系统固定头文件
*/
#include <Rasl/rasl.hpp>
#include <DataUploader/DataUploader.hpp>
#include "StaticVariable.h"
#include "rasl-dpd/user.hpp"
#include "UserChannels.rasi"
#include "DataCollect.hpp"
/** 系统固定头文件 */

//用户测试代码需要新增的头文件

namespace{
using namespace Kiyun::LowerComputer;
using namespace Kiyun::LowerComputer::Rasl;
using namespace Kiyun::LowerComputer::Rasl::Frame;
using namespace Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间
using namespace Kiyun::LowerComputer::DataUploader; //数据上传命名空间
using namespace Kiyun::Channel;
using namespace Kiyun::DataCollect; //数据采集接口命名空间
using namespace Dpdp; //协议命名空间
using namespace Frame;
using namespace std;

//本地变量、本地函数声明
//Os::Semaphore_T
f_exitSem;
//Can 2路通道,0~1
void f_can_asynRead(void);
void f_can_asynWrite(void);
void f_can_syncRead(void);
void f_can_syncWrite(void);
void f_can_printf(const Can_T::CanFrame_T&
frameWrite);
void f_can_printf(const vector<uint8_t>& vet);
}

//主函数入口
int Main()
{
KYIO(out) << "*******************Can
Test*******************";
if (!f_can1.isValid()||!f_can2.isValid())//使用通道前,建议判断通道是否可用
{
KYIO(err) << "can
channels is inVaild ,exit...";
return
-1;
}
//同步读写
f_can_syncWrite();
Timer_T::delay(0.1);
f_can_syncRead();
//中断读写
f_can_asynRead();
f_can_asynWrite();
Timer_T::delay(0.1);

KYIO(log)<<f_can1.path();
KYIO(log)<<f_can2.path();

return 0;
}

namespace {

void f_can_syncWrite()
{
Can_T::CanFrame_T frameWrite;//有默认值,标准帧数据帧
frameWrite.id = 1234;
frameWrite.dataCnt =
8;
for
(size_t i =
0; i
< frameWrite.dataCnt; i++) {
frameWrite.dataBuf[i] = i + 10;
}
Error_T err = f_can1.write(frameWrite);
if
(err)
KYIO(err) <<
"write err:" << err.message();
else
KYIO(log) <<
"write OK";
}

void f_can_syncRead()
{
Can_T::CanFrame_T frameRead;
auto
err = f_can2.read(frameRead);
if
(!err)
{

f_can_printf(frameRead);

KYIO(log) <<
"goto buf: ";
auto vet =
Can_T::toBuf(frameRead);
f_can_printf(vet);
}
else
{
KYIO(err) <<
"read err:" << err.message();
}
}

void f_can_asynWrite()
{

Can_T::CanFrame_T frameWrite;
frameWrite.idFormat =
Can_T::IdMode_E::EXTENDED_e;
frameWrite.frameFormat =
Can_T::FrameMode_E::DATA_e;
frameWrite.id = 0x02;
frameWrite.dataCnt =
8;
for
(size_t i =
0; i
< frameWrite.dataCnt; i++) {
frameWrite.dataBuf[i] = i + 50;
}

f_can1.asyncWrite(frameWrite,
[](Error_T err)
{
if(!err)
KYIO(out) <<
"async write OK";
});
}

void f_can_asynRead()
{
f_can2.intRead([&](Can_T::CanFrame_T frameRead,Error_T err)
{
static int
sum = 1;
f_can_printf(frameRead);
if (0 == (sum++) % 10)
return false;
return true;
});
}

void f_can_printf(const Can_T::CanFrame_T&
frameRead)
{
std::string str = "";
char
ch[20];
str.append("received | ");

sprintf(ch, "0x%04x | ",
frameRead.id);
str.append(ch);

if
(Can_T::FrameMode_E::REMOTE_e == frameRead.frameFormat) {
str.append("remote |
");
}
else
if(Can_T::FrameMode_E::DATA_e
== frameRead.frameFormat) {
str.append("data |
");
}

if
(Can_T::IdMode_E::EXTENDED_e == frameRead.idFormat) {
str.append("extended |
");
}
else
if(Can_T::IdMode_E::STANDARD_e
== frameRead.idFormat) {
str.append("standard |
");
}
sprintf(ch, "0x%x | ",
frameRead.dataCnt);
str.append(ch);
str.append("x| ");
for
(size_t i =
0; i
< frameRead.dataCnt; i++) {
sprintf(ch, "%02x
", frameRead.dataBuf[i]);
str.append(ch);
}
KYIO(log) << str;
}

void f_can_printf(const vector<uint8_t>& vet)
{
KYIO(log) << "buffer
size = " << vet.size();
string str;
char
buffer[20];
str.append("received | ");
for
(auto
ch : vet)
{
sprintf(buffer, "%02x
", ch);
str.append(buffer);
}
KYIO(log) << str;
}
}

bool Exit(Os::Task_T)
{
//返回值为true,表示能中止正在运行的实时任务
//f_exitSem.notifyOne();
//return true;

return false; //默认情况下该实时任务不能被中止
}

1.1.4.2 Can::Channel_T类

本类型所在命名空间为:Kiyun::LowerComputer::Rasl::Device,是进行CAN总线操作的主体。具有以下类型和方法:

1) isValid方法

检测通道是否有效。强烈建议使用前判断通道合法性。

函数原型:bool isValid() const

参数:无

返回值:true:通道有效,fasle:通道无效

2) path方法

获取通道标识,在数据上传时使用。

函数原型:Path_T path() const

参数:无

返回值:通道标识符

3) asyncWrite方法

异步输出。

函数原型:void asyncWrite(CanFrame_T& can, const WriteHandler_T& hdl)

参数:can:输出数据的首地址;hdl:回调函数。

返回值:无。

4) intRead方法

中断读。

函数原型:void intRead(const IntRead_T& hdl)

参数:hdl:回调函数,函数返回值表示“是否继续接收”,true继续,false停止。

返回值:无。

5) read方法

同步读。

函数原型:BOOL read(Can_T::CanFrame_T & frame, Timeout_T timeout = 1_s)

参数:frame:存放输入数据的地址;timeout:超时等待时间,默认为1s。

返回值:操作是否成功。

6) write方法

同步写。

函数原型:BOOL write(const Can_T::CanFrame_T & frame,Timeout_T timeout = 1_s);

参数:frame:存放输出数据的地址;timeout:超时等待时间,默认为1s

返回值:操作是否成功。

1.1.5 DI/DO接口

使用数字量输入/输出操作主要用到的类型是Dio_T类型。本节对数字量输入/输出操作进行介绍。

1.1.5.1 使用方法及范例

在ETest系统中,数字量输入/输出操作主要由Dio_T::Channel_T类型完成。

在使用Etest进行仿真模型设计和设备规划过程中,可以建立数字量输入/输出通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建Dio_T::Channel_T类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的采集操作。

如,在以下范例中,创建交联环境图如下:

编辑

添加图片注释,不超过 140 字(可选)

对象CH_数字输入_1和CH_数字输出_1即为Dio::Channel_T类型的对象,可以用来完成数字量输入/输出功能。

在设备规划中需要设置DI通道的属性“跳变检测模式”为正确的模式,才能在intRead函数中进行跳变沿检测处理。

示例代码如下:

/**
系统固定头文件 */
#include <Rasl/rasl.hpp>
#include <DataUploader/DataUploader.hpp>
#include "StaticVariable.h"
#include "rasl-dpd/user.hpp"
#include "UserChannels.rasi"
#include "DataCollect.hpp"
/** 系统固定头文件 */

//用户测试代码需要新增的头文件

namespace{
using namespace Kiyun::LowerComputer;
using namespace Kiyun::LowerComputer::Rasl;
using namespace Kiyun::LowerComputer::Rasl::Frame;
using namespace Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间
using namespace Kiyun::LowerComputer::DataUploader; //数据上传命名空间
using namespace Kiyun::Channel;
using namespace Kiyun::DataCollect; //数据采集接口命名空间
using namespace Dpdp; //协议命名空间

//本地变量、本地函数声明
//Os::Semaphore_T
f_exitSem;
}

//主函数入口
int Main()
{
//设置全局日志属性
KYLOG_GLOBAL().severity(Logging_T::Severity_E::TRAC_e);
KYLOG_SCOPE("ETestRT::Main").tag("发送").tag("检查");
KYLOG(INFO) << "Hello
world, Kiyun!\n"; //可保存到日志文件
KYIO(log) << "Hello
World,Kiyun!\n"; //发送到控制台

/*测试代码*/
if(!CH_数字输出_1.isValid())
{
KYIO(err) <<
"CH_数字输出_1 channels initial failed.";
return -1; //返回值需要根据该代码片段所处函数返回值类型设定
}

KYIO(log) <<CH_数字输出_1.path();

if(!CH_数字输入_1.isValid()) {
KYIO(err) <<
"CH_数字输出_1 channels initial failed.";
return -1; //返回值需要根据该代码片段所处函数返回值类型设定
}

KYIO(log) <<CH_数字输入_1.path();

CH_数字输入_1.intRead([](int
chID,int
state) {
KYIO(out) << "Notify
..." << chID << " "<< state;
return
true;
});

CH_数字输出_1.write(TRUE);
Timer_T::delay(1);
if
(CH_数字输入_1.read()) {
KYIO(log) <<
"DI HIGH";
}
else {
KYIO(log) <<
"DI LOW";
}
Timer_T::delay(5);

CH_数字输出_1.write(FALSE);
Timer_T::delay(1);
if
(CH_数字输入_1.read()) {
KYIO(log) <<
"DI HIGH";
}
else {
KYIO(log) <<
"DI LOW";
}
CH_数字输出_1.write(TRUE);
Timer_T::delay(1);

Timer_T::delay(5);

//f_exitSem.wait();
return 0;
}

bool Exit(Os::Task_T)
{
//返回值为true,表示能中止正在运行的实时任务
//f_exitSem.notifyOne();
//return true;

return false; //默认情况下该实时任务不能被中止
}

1.1.5.2 Dio::Channel_T类

该类所在的命名空间:Kiyun::LowerComputer::Rasl::Device。具有以下方法:

1) isValid方法

检测通道是否有效。强烈建议使用前判断通道有效性。

函数原型:bool isValid() const

参数:无

返回值:true:通道有效,fasle:通道无效。

2) path方法

获取通道标识。数据上传时会用到。

函数原型:Path_T path() const

参数:无

返回值:通道标识符

3) read方法

获取数字量输入或者状态。

函数原型:BOOL read();

参数:

返回值:输出状态,TRUE为高电平,FALSE为低电平。

4) write方法

设置数字量输出状态。

函数原型:void write(BOOL status)

参数:status:输出状态,TRUE为高电平,FALSE为低电平

返回值:无

5) intRead方法

数字量输入跳变检测。

函数原型:void intRead(Channel_T::IORVectorHandler_T inputRVector)

参数:inputRVector 跳变检测回调函数,函数说明为:

Bool inputRVector(int id,int state)

参数id为发生跳变的通道号。

参数state为当前通道的状态(0或者1)。

返回值表示“是否继续检测”,true继续,false停止。

返回值:

1.1.6 1553B接口

使用UDP接口操作主要用到的类型是M1553_T类型。本节对1553B接口操作进行介绍。

1.1.6.1 使用方法及范例

在ETest系统中,1553B接口操作主要由M1553_T类型完成。

在使用Etest进行仿真模型设计和设备规划过程中,可以建立1553BC、1553RT、1553MT、1553BSP通道,并且配置参数。当通道建立完成并且参数配置完成后,系统运行环境会自动创建对于类型的通道,名称和在“仿真模型”中建立的通道名称一致。在实时脚本中,即可直接使用该对象,进行数据的读/写操作。

创建仿真模型如下图所示。

编辑

添加图片注释,不超过 140 字(可选)

图 1 1553范例仿真模型

在设备规划中,选中设备,在“属性”窗体编辑属性,建立消息列表。

编辑

添加图片注释,不超过 140 字(可选)

图 2 1553范例设备规划

编辑

添加图片注释,不超过 140 字(可选)

图 3 1553范例消息编辑器

编写如下实时脚本,完成消息的收发。

同步读写:

/** 系统固定头文件 */
#include <Rasl/rasl.hpp>
#include <DataUploader/DataUploader.hpp>
#include "StaticVariable.h"
#include "rasl-dpd/user.hpp"
#include "UserChannels.rasi"
#include "DataCollect.hpp"
/** 系统固定头文件 */
//#define MC_APPNAME "M1553-TEST"
#include <Rasl/rasl.hpp>

namespace {

using
namespace Kiyun::LowerComputer;
using namespace Kiyun::LowerComputer::Rasl;
using namespace Kiyun::LowerComputer::Rasl::Frame;
using namespace Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间
using namespace Kiyun::LowerComputer::DataUploader; //数据上传命名空间
using namespace Kiyun::Channel;
using namespace Kiyun::DataCollect; //数据采集接口命名空间
using namespace Dpdp; //协议命名空间

using
namespace std;
using
namespace Mince::LowerComputer::Rasl;
using
namespace Mince::LowerComputer::Rasl::Frame;
using
namespace
Mince::LowerComputer::Rasl::Device;
void fc_msgPrint(M1553_T::RecvMsg_T* rmsg,
size_t size);
void fc_msgPrint(const std::vector<uint8_t>& buf);
}

int test1553()
{

MCIO(log) << "-------------1553
TEST-----------------";
if
(!mt.isValid())
{
MCIO(err) <<
"bm is inValid...exit";
return -1;
}
if
(!dsp.isValid())
{
MCIO(err) <<
"dsp is inValid...exit";
return -1;
}

uint16_t outData[32] = {0};
for
(int
i = 0; i < 32; i++)
outData[i] = 0x1234 + i;

//BC to RT
bc0.write(outData, 32);

//RT to BC
outData[0] = 0x4321;
rt5.write(outData, 32);

//RT to RT
outData[0] = 0x2134;
rt2.write(outData, 32);

//执行消息
dsp.write(0);
dsp.write(1);
dsp.write(2);


//延时保证消息已处理
Timer_T::delay(0.1);

MCIO(log) << "-------------BC
READ-----------------";
fc_msgPrint(bc0.read());
fc_msgPrint(bc1.read());
fc_msgPrint(bc2.read());



MCIO(log) << "-------------RT
READ-----------------";
MCIO(log) << "------rt
2,7 read";
fc_msgPrint(rt2.read());
MCIO(log) << "------rt
5,8 read";
fc_msgPrint(rt5.read());


MCIO(log) << "-------------MT
READ-----------------";

//fc_msgPrint(mt.read());
M1553_T::RecvMsg_T rmsg[10];
size_t res =
0;
auto
err = mt.read(rmsg, 10, res);
if
(!err)
fc_msgPrint(rmsg, res);
else
MCIO(err) <<
"BM read err:" << err.message();
return 0;
}

int Main()
{
return test1553();
}

namespace {

void fc_msgPrint(M1553_T::RecvMsg_T* rmsg,
size_t size)
{
char ch[100];
std::string
str;
for (size_t
i = 0; i <
size; i++)
{
str
= "";
snprintf(ch, sizeof(ch), "bsw = 0x%04x,", rmsg[i].bsw);
str.append(ch);
snprintf(ch, sizeof(ch), "cmd1 = 0x%04x,", rmsg[i].msgBlock.cmdWord1);
str.append(ch);
snprintf(ch, sizeof(ch), "cmd2 = 0x%04x,", rmsg[i].msgBlock.cmdWord2);
str.append(ch);
str.append(" data :
");
for (size_t
j = 0; j < 32; ++j)
{
snprintf(ch, sizeof(ch), "%04x ",
rmsg[i].msgBlock.dataBlk[j]);
str.append(ch);
}
MCIO(log) <<
str;
}
}

void fc_msgPrint(const std::vector<uint8_t>& buf)
{
char ch[100];
std::string
str;

auto wordBuf =
M1553_T::toWord(buf);

for (const auto& val: wordBuf)
{
snprintf(ch, 100, "%04x
", val);
str.append(ch);
}
MCIO(log) <<"data : "<<
str;
}
}

异步读写

/** 系统固定头文件 */
#include <Rasl/rasl.hpp>
#include <DataUploader/DataUploader.hpp>
#include "StaticVariable.h"
#include "rasl-dpd/user.hpp"
#include "UserChannels.rasi"
#include "DataCollect.hpp"
/** 系统固定头文件 */
//#define MC_APPNAME "M1553-TEST"
#include <Rasl/rasl.hpp>

namespace {

using
namespace Kiyun::LowerComputer;
using namespace Kiyun::LowerComputer::Rasl;
using namespace Kiyun::LowerComputer::Rasl::Frame;
using namespace Kiyun::LowerComputer::Rasl::Device; //通道设备命名空间
using namespace Kiyun::LowerComputer::DataUploader; //数据上传命名空间
using namespace Kiyun::Channel;
using namespace Kiyun::DataCollect; //数据采集接口命名空间
using namespace Dpdp; //协议命名空间

using
namespace std;
using
namespace Mince::LowerComputer::Rasl;
using
namespace
Mince::LowerComputer::Rasl::Frame;
using
namespace
Mince::LowerComputer::Rasl::Device;
void fc_msgPrint(M1553_T::RecvMsg_T* rmsg,
size_t size);
void fc_msgPrint(const std::vector<uint8_t>& buf);
}

int test1553()
{

MCIO(log) << "-------------1553
TEST-----------------";
if
(!mt.isValid())
{
MCIO(err) <<
"bm is inValid...exit";
return -1;
}
if
(!dsp.isValid())
{
MCIO(err) <<
"dsp is inValid...exit";
return -1;
}

uint16_t outData[32] = {0};
for
(int
i = 0; i < 32; i++)
outData[i] = 0x1234 + i;

//BC to RT
bc0.write(outData, 32);

//RT to BC
outData[0] = 0x4321;
rt5.write(outData, 32);

//RT to RT
outData[0] = 0x2134;
rt2.write(outData, 32);

//执行消息
dsp.write(0);
dsp.write(1);
dsp.write(2);


//延时保证消息已处理
Timer_T::delay(0.1);

dsp.write(0, false);
Timer_T::delay(1);

if
(!dsp.isRunning())
MCIO(log) <<
"bc stoped...";
else
MCIO(log) <<
"bc is running...";

uint32_t isRunning = 1;
while
(isRunning)
{
isRunning = dsp.isRunning();
}
printf("BC
stopped.\n");

bc0.intRead([&](uint16_t
* buf,
size_t size,Error_T err)->bool {
MCIO(log) <<
"-----------------------bc intRead:"
<< (int)buf[0];
return true;
});

rt2.intRead([&](uint16_t
* buf,
size_t size, Error_T err)->bool {
MCIO(log) <<
"-----------------------rt intRead:"
<< (int)buf[0];
return true;
});

mt.intRead([&](uint16_t
* buf,
size_t size, Error_T err)->bool {
MCIO(log) <<
"------------------------mt intRead:"
<< (int)buf[0];
return true;
});

return 0;
}

int Main()
{
return test1553();
}

namespace {

void fc_msgPrint(M1553_T::RecvMsg_T* rmsg,
size_t size)
{
char ch[100];
std::string
str;
for (size_t
i = 0; i <
size; i++)
{
str
= "";
snprintf(ch, sizeof(ch), "bsw = 0x%04x,", rmsg[i].bsw);
str.append(ch);
snprintf(ch, sizeof(ch), "cmd1 = 0x%04x,", rmsg[i].msgBlock.cmdWord1);
str.append(ch);
snprintf(ch, sizeof(ch), "cmd2 = 0x%04x,", rmsg[i].msgBlock.cmdWord2);
str.append(ch);
str.append(" data :
");
for (size_t
j = 0; j < 32; ++j)
{
snprintf(ch, sizeof(ch), "%04x ",
rmsg[i].msgBlock.dataBlk[j]);
str.append(ch);
}
MCIO(log) <<
str;
}
}

void fc_msgPrint(const std::vector<uint8_t>& buf)
{
char ch[100];
std::string
str;

auto wordBuf =
M1553_T::toWord(buf);

for (const auto& val: wordBuf)
{
snprintf(ch, 100, "%04x
", val);
str.append(ch);
}
MCIO(log) <<"data : "<<
str;
}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值