logo头像
Snippet 博客主题

1553B板卡详解

TODO:这段比较忙,先快速记录个大概,后面得空再详细整理下,尽量表述得通俗易懂~

简介

1553b板卡主要应用于航天航空工业领域,它的数据传输结构有点类似集中分布式服务器的设计,分为BC、RT、BM三类部件,BC有且仅有1个,类似我们的master管理服务节点,RT有0~32个,类似我们的各业务服务节点,BM则是监控节点。所以按传统服务器设计结构也很好理解1553B了。

环境安装

  1. 安装驱动,驱动盘里有个imsk的脚本执行一下就好了,需要注意的是驱动版本一定要与板卡一致。

  2. 接线,各通道的线通过耦合器连到一起就可以了。

模拟工具

在windows上提供了一个测试工具,FlightPack-1553B可以与自己封装的1553B模块对测。

BC设置,我一般用的子帧模式,添加需要的消息,主要是BC有些设置,其它基本没什么要设置的,像RT基本就是使能下就可以了。

模块封装

RT封装倒是比较简单,直接参考示例程序就行了,没什么特别的,主要是BC的封装,有几个点需要注意,它是一个管理类,消息个数是可以动态添加的,而且默认子帧模式,消息有开始和结束形成一个环。还一点特别注意在设置RT->RT消息时,消息块的cmd_wd1字段只能是接收,cmd_wd2只能是发送。

1. RT

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
#include "CtrlSysLibTool.h"
#include "Port_1553B_RT.h"

#ifdef WIN32
#include <windows.h>
#endif

#include "json.hpp"
#include "kl_common_info.h"
#include <stdio.h>
#include <string.h>

struct CAV1553B_RT_INFO {
CAV1553B_RT_INFO(CORE_U16 dev_num, CORE_U32 channel_num, CORE_U16 rt_addr, CORE_U16 sub_addr)
: dev_num_(dev_num), channel_num_(channel_num), rt_addr_(rt_addr), sub_addr_(sub_addr)
{
memset(&rt_sabuf_, 0, sizeof(rt_sabuf_));
rt_sabuf_.legal_wc = 0xFFFFFFFF;
data_size_ = sizeof(rt_sabuf_.data_wds);
}

CORE_RT_SA_BUFFER rt_sabuf_; // rt读写buffer
int data_size_; // data_wds数据的长度,这里会默认32个CORE_U16(unsigned short)
CORE_U16 dev_num_; // 设备号
CORE_U32 channel_num_; // 通道号
CORE_U16 rt_addr_; // RT 地址,取值范围 0~31;
CORE_U16 sub_addr_; // RT 子地址,取值范围 0~31;
std::map<std::pair<CORE_U16, CORE_U32>, bool>
*init_info_1553b_; // 记录通道初始化情况,相同的dev_num及channel_num只初始化一次
std::vector<std::string> vars; // 存储协议字段的类型
};

/***********************************
内部变量初始化
内部变量:rtinfo_
***********************************/
int32_t Block_Port_1553B_RT::initInternalVariable()
{
LOG_INFO("CAV1553BInit start...\n");
// Devnum 由设备编号和 1553 板卡类型组成。其中:
// 1)设备编号:设备编号(从 0 开始编号),取值范围 0~3。
// 2)1553 板卡类型:
// devnum = (0 | PCI_1553_TYPE),代表的是 PCI1553 板卡,设备 0;
// devnum = (1 | PCI_1553_TYPE),代表的是 PCI1553 板卡,设备 1;
// devnum = (0 | USB_1553_TYPE),代表的是 USB1553 板卡,设备 0;
// devnum = (1 | USB_1553_TYPE),代表的是 USB1553 板卡,设备 1。
CORE_U16 dev_num = (CORE_U16)P(devNum) | PCI_1553_TYPE;
CORE_U32 channel_num = P(channelNum);
CORE_U16 rt_addr = P(rtAddr);
CORE_U16 sub_addr = P(subAddr);

rtinfo_ = new CAV1553B_RT_INFO(dev_num, channel_num, rt_addr, sub_addr);
CAV1553B_RT_INFO *rtinfo = static_cast<CAV1553B_RT_INFO *>(rtinfo_);
rtinfo->init_info_1553b_ = GetInitInfo_1553b();

auto iter = rtinfo->init_info_1553b_->find({ dev_num, channel_num });
// 没有找到,或者找到了但是为false,则表示未初始化,那么进行相关初始化操作
if (iter == rtinfo->init_info_1553b_->end()) {
// 该函数用于初始化某一个板卡的通道。三个参数分别为:设备号、通道号、中断队列长度(取值:4,8,16,32,64,128,256。)
// SUCCESS:设备初始化成功;FAILURE:设备初始化失败。
if (FAILURE == CORE_GEN_Full_Init(dev_num, channel_num, 16)) {
return false;
}
LOG_INFO("CORE_GEN_Full_Init finished...\n");

// CORE_RT_Multiple_Is_Supported 用于查看板卡是否支持多 RT 功能。
// 1:支持多 RT;0:不支持多 RT。
int multiple = CORE_RT_Multiple_Is_Supported(dev_num, channel_num);
if (!multiple && rt_addr > 0) {
LOG_ERROR("not support multiple,channel_num = %d\n", (int)channel_num);
return false;
}
LOG_INFO("CORE_RT_Multiple_Is_Supported finished...\n");

// CORE_RT_Init 用于初始化板卡中的 RT 功能,进行 RT 内存分配,在用 RT 功能之前,需要调用此函数。
// SUCCESS:RT 初始化成功;FAILURE:RT 初始化失败。
if (FAILURE == CORE_RT_Init(dev_num, channel_num)) {
LOG_ERROR("Initializing RT Failure,channel_num = %d\n", (int)channel_num);
return false;
}

rtinfo->init_info_1553b_->insert({ { dev_num, channel_num }, true });

LOG_INFO("CORE_RT_Init finished...\n");
}

// CORE_RT_Enable 用来使能某一特定的 RT 地址,使其有效。使用任何 RT 之前都需要使能这个 RT 地址,否则 RT
// 将不工作。
CORE_RT_Enable(dev_num, channel_num, rt_addr);

// CORE_RT_Allocate_SA_Buffers 为特定的 RT 的子地址分配一个或者多个缓冲区,用于存储相关数据
// SUCCESS:RT 缓冲分配成功;FAILURE:RT 缓冲分配失败。
// devnum:见上面注释;
// channel_num:通道编号(从 0 开始编号),取值范围 0~3;
// rt:RT 地址,取值范围 0~31;
// tr:发送还是接收。 1:发送;0:接收;
// sa:RT 子地址,取值范围 0~31;
// num_bufs:要分配多少个缓冲 buffer。
CORE_U16 tr = 0;
if (P(bsend)) {
tr = 1;
}
if (FAILURE == CORE_RT_Allocate_SA_Buffers(dev_num, channel_num, rt_addr, tr, sub_addr, 1)) {
LOG_ERROR("Allocating Failure,channel_num = %d\n", (int)channel_num);
return false;
}
LOG_INFO("CORE_RT_Allocate_SA_Buffers finished...\n");

if (FAILURE == CORE_RT_Write_SA_Buffer(dev_num, channel_num, rt_addr, tr, sub_addr, 0, &rtinfo->rt_sabuf_)) {
return false;
}

// CORE_RT_Start运行已经配置好的 RT 。
CORE_RT_Start(dev_num, channel_num);

/*****************************解析协议json文件, 将协议字段的类型放入数组中***********************/
nlohmann::ordered_json root;
#ifdef _WIN32
std::ifstream(P(filename).c_str()) >> root;
#else
std::string strfilePath = P(filename).c_str();
std::string strfile = "protocol/" + strfilePath.substr(strfilePath.find_last_of("/") + 1);
if (access(strfile.c_str(), F_OK) == -1) {
return false;
}
std::ifstream(strfile.c_str()) >> root;
#endif

nlohmann::ordered_json child = root["Protocol fields"];
for (auto &item : child.items()) {
rtinfo->vars.push_back(item.value()["type"]);
// std::string tp = item.value()["type"];
// LOG_ERROR("type=%s\n", tp.c_str());
}

bool bi = P(bsend) && I(p_dynamic_Input_).size_ != rtinfo->vars.size();
bool bo = !P(bsend) && O(p_dynamic_Output_).size_ != rtinfo->vars.size();
if (bi || bo) {
// 如果动态输入端口的个数与协议字段的个数不一致则有错误
return false;
}

binit_ = true; // 标识已完成初始化
LOG_INFO("CAV1553BInit success...\n");
return true;
}

/**********************************
在此函数中编写自定义代码
输入变量:
输出变量:
参数:bsend, channelNum, devNum, filename, rtAddr, subAddr
状态变量:
示例:O(输出变量) = I(输入变量) + P(参数)
***********************************/
void Block_Port_1553B_RT::runAlgorithm(void *extra)
{
CAV1553B_RT_INFO *rtinfo = static_cast<CAV1553B_RT_INFO *>(rtinfo_);

//memset(&rtinfo->rt_sabuf_, 0, sizeof(rtinfo->rt_sabuf_)); // 清空上次数据
if (P(bsend)) {
// 作为发送模块
size_t offset = 0;
for (size_t i = 0; i < rtinfo->vars.size(); i++) {
if (1 == P(checkType) && i == rtinfo->vars.size() - 1) {
// checkType==1时为crc校验
uint16_t crc = get_crc16((uint8_t *)rtinfo->rt_sabuf_.data_wds, offset);
memcpy(rtinfo->rt_sabuf_.data_wds + offset, &crc, sizeof(uint16_t));
offset += sizeof(uint16_t);
}

size_t var_len = type_len(rtinfo->vars[i]);
convert_var_to_buffer(rtinfo->vars[i], offset, (uint8_t *)rtinfo->rt_sabuf_.data_wds,
I(p_dynamic_Input_).ptr_[i], var_len);
offset += var_len;
}

// 不能超过缓存大小
if (offset <= rtinfo->data_size_) {
if (SUCCESS
== CORE_RT_Write_SA_Buffer(rtinfo->dev_num_, rtinfo->channel_num_, rtinfo->rt_addr_, 1,
rtinfo->sub_addr_, 0, &rtinfo->rt_sabuf_)) { }
}
} else {
// 作为接收模块
if (SUCCESS
== CORE_RT_Read_SA_Buffer(rtinfo->dev_num_, rtinfo->channel_num_, rtinfo->rt_addr_, 0, rtinfo->sub_addr_, 0,
&rtinfo->rt_sabuf_)) {
size_t offset = 0;
for (size_t i = 0; i < rtinfo->vars.size(); i++) {
if (1 == P(checkType) && i == rtinfo->vars.size() - 1) {
// checkType==1时为crc校验
uint16_t crc = get_crc16((uint8_t *)rtinfo->rt_sabuf_.data_wds, offset); // 先计算自己的crc
uint16_t *recv_crc = (uint16_t *)(rtinfo->rt_sabuf_.data_wds + offset); // 解析收到数据包的crc字段
if (crc != *recv_crc) {
// 错误信息
}
offset += sizeof(uint16_t);
}

size_t var_len = type_len(rtinfo->vars[i]);
*O(p_dynamic_Output_).ptr_[i] =
convert_buffer_to_var(rtinfo->vars[i], offset, (uint8_t *)rtinfo->rt_sabuf_.data_wds);
offset += var_len;
}
}
}
}

/**********************************
在此函数中编写自定义积分函数
***********************************/
int32_t Block_Port_1553B_RT::integral(int32_t msg, double t, double *state, double *derivative)
{
return 0;
}

/**********************************
在此函数中释放内部变量资源
内部变量:rtinfo_
***********************************/
void Block_Port_1553B_RT::destroyInternalVariable()
{
// 是否调用了初始化函数,默认为false(控制引擎会出现直接调用destroy的情况,而成员变量si_未初始化被使用会导致崩溃)
if (!binit_) {
return;
}
CAV1553B_RT_INFO *rtinfo = static_cast<CAV1553B_RT_INFO *>(rtinfo_);

CORE_RT_Disable(rtinfo->dev_num_, rtinfo->channel_num_, rtinfo->rt_addr_);

auto iter = rtinfo->init_info_1553b_->find({ rtinfo->dev_num_, rtinfo->channel_num_ });
if (iter == rtinfo->init_info_1553b_->end() || !iter->second) {
CORE_RT_Stop(rtinfo->dev_num_, rtinfo->channel_num_);
}

delete rtinfo;
}

2. BC

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
#include "CtrlSysLibTool.h"
#include "Port_1553B_BC.h"

#ifdef WIN32
#include <windows.h>
#endif

#include "json.hpp"
#include "kl_common_info.h"
#include <stdio.h>
#include <string.h>

struct CAV1553B_BC_INFO {
CAV1553B_BC_INFO(CORE_U16 dev_num, CORE_U32 channel_num, doubleVector& rt_addr, doubleVector& sub_addr, doubleVector& msg_type)
: dev_num_(dev_num)
, channel_num_(channel_num)
, init_info_1553b_(nullptr)
{
memset(&bc_sabuf_, 0, sizeof(bc_sabuf_));
data_size_ = sizeof(bc_sabuf_.data_wds);
for (int i = 0; i < 32; i++) {
rt_addr_[i] = (CORE_U16)rt_addr[i];
sub_addr_[i] = (CORE_U16)sub_addr[i];
msg_type_[i] = (CORE_U16)msg_type[i];
}
}

CORE_BC_MSG_BUFFER bc_sabuf_; // bc读写buffer
int data_size_; // data_wds数据的长度,这里会默认32个CORE_U16(unsigned short)
CORE_U16 dev_num_; // 设备号
CORE_U32 channel_num_; // 通道号
CORE_U16 rt_addr_[32]; // RT 地址,取值范围 0~31;
CORE_U16 sub_addr_[32]; // RT 子地址,取值范围 0~31;
CORE_U16 msg_type_[32]; // BC消息类型,如rt->bc,bc->rt,rt->rt
std::map<std::pair<CORE_U16, CORE_U32>, bool>* init_info_1553b_; // 记录通道初始化情况,相同的dev_num及channel_num只初始化一次
std::vector<std::vector<std::string>> bc_rt_vars; // 存储bc->rt协议字段的类型
std::vector<std::vector<std::string>> rt_bc_vars; // 存储rt->bc协议字段的类型
std::vector<int> bc_rt_nums; // bc->rt消息个数
std::vector<int> rt_bc_nums; // rt->bc消息个数
};

/***********************************
内部变量初始化
内部变量:bcinfo_
***********************************/
int32_t Block_Port_1553B_BC::initInternalVariable()
{
LOG_INFO("CAV1553B_BC_Init start...\n");
// Devnum 由设备编号和 1553 板卡类型组成。其中:
// 1)设备编号:设备编号(从 0 开始编号),取值范围 0~3。
// 2)1553 板卡类型:
// devnum = (0 | PCI_1553_TYPE),代表的是 PCI1553 板卡,设备 0;
// devnum = (1 | PCI_1553_TYPE),代表的是 PCI1553 板卡,设备 1;
// devnum = (0 | USB_1553_TYPE),代表的是 USB1553 板卡,设备 0;
// devnum = (1 | USB_1553_TYPE),代表的是 USB1553 板卡,设备 1。
CORE_U16 dev_num = (CORE_U16)P(devNum) | PCI_1553_TYPE;
CORE_U32 channel_num = (CORE_U32)P(channelNum);

bcinfo_ = new CAV1553B_BC_INFO(dev_num, channel_num, P(rtAddr), P(subAddr), P(msgType));
CAV1553B_BC_INFO* bcinfo = static_cast<CAV1553B_BC_INFO*>(bcinfo_);
bcinfo->init_info_1553b_ = GetInitInfo_1553b();

size_t block_count = P(msgType).size();
auto iter = bcinfo->init_info_1553b_->find({ dev_num, channel_num });
// 没有找到,或者找到了但是为false,则表示未初始化,那么进行相关初始化操作
if (iter == bcinfo->init_info_1553b_->end() || !iter->second) {
// 该函数用于初始化某一个板卡的通道。三个参数分别为:设备号、通道号、中断队列长度(取值:4,8,16,32,64,128,256。)
// SUCCESS:设备初始化成功;FAILURE:设备初始化失败。
if (FAILURE == CORE_GEN_Full_Init(dev_num, channel_num, 16)) {
return false;
}
LOG_INFO("CORE_GEN_Full_Init finished...\n");

/*
CORE_BC_Is_Supported 查看板卡是否支持 BC 功能。
1:支持 BC;
0:不支持 BC
*/
int surportBC = CORE_BC_Is_Supported(dev_num, channel_num);
if (!surportBC) {
LOG_ERROR("not support BC,channel_num = %d\n", (int)channel_num);
return false;
}

LOG_INFO("CORE_BC_Is_Supported finished...\n");

/*
CORE_BC_Init 用于初始化板卡中的 BC 功能,设置 BC 需要发送的消息个数
devnum:设备号;
channel_num:通道编号(从 0 开始编号),取值范围 0~3;
num_blocks:所需建立的 BC BLOCK 的个数;
frame_us:以 us 为单位的子帧时间间隔,取值范围 40~0xFFFFFFFF;
wTimeout1:无响应时间,单位 us,取值范围 0~31。当 wTimeout1 和 wTimeout2都为 0
时为不设置延时时间,使用系统默认时间); wTimeout2:最迟响应时间,单位 us,取值范围 0~31。(当 wTimeout1 和
wTimeout2都为 0 时为不设置延时时间,使用系统默认时间)
*/
if (CORE_BC_Init(dev_num, channel_num, block_count, 100000, 0, 0) == FAILURE) {
LOG_ERROR("Initializing BC Failure,channel_num = %d\n", (int)channel_num);
return false;
}
LOG_INFO("CORE_BC_Init finished...\n");
} else {
LOG_ERROR("BC is Initializing\n");
return false;
}

CORE_BC_BLOCK bc_block;
for (int i = 0; i < block_count; i++) {
/*
CORE_BC_Allocate_Msg_Buffers 为特定的 BC Block 分配 Message Buffers。
devnum:设备号;
channel_num:通道编号(从 0 开始编号),取值范围 0~3;
msg_num:BC Block 编号(需要为哪个 BLOCK 分配消息);
num_buffs:所需分配的消息的个数,默认值为 1。
*/
if (CORE_BC_Allocate_Msg_Buffers(dev_num, channel_num, i, 1) == FAILURE) {
LOG_ERROR("CORE_BC_Allocate_Msg_Buffers Failure,channel_num = %d\n", (int)channel_num);
return false;
}

memset(&bc_block, 0, sizeof(bc_block));
int bcMsgType = (int)P(msgType)[i];
if (0 == i) {
bc_block.next_msg_num = i + 1;
bc_block.bc_control_wd = bcMsgType | BC_BLOCK_FRAME_BEGIN | BC_BLOCK_FLAG_BUS_A;
} else if (block_count - 1 == i) {
bc_block.next_msg_num = 0;
bc_block.bc_control_wd = bcMsgType | BC_BLOCK_FRAME_END | BC_BLOCK_FLAG_BUS_A;
} else {
bc_block.next_msg_num = i + 1;
bc_block.bc_control_wd = bcMsgType | BC_BLOCK_FLAG_BUS_A;
}
/*
CORE_Set_BC_Command 组合 MIL-STD-1553B BC 的命令字。
devnum:设备号
channel_num:通道编号(从 0 开始编号),取值范围 0~3;
RT:RT 地址,取值范围 0~31;
tr:发送还是接收。1 代表发送,0 代表接收;
data_count:数据字个数,取值范围:0~31(0 代表 32 个字);
如果消息是 ModeCode 类型,data_count 代表的是模式代码。
subaddr:RT 子地址,取值范围 0~31
*/
if (bcMsgType == BC_BLOCK_TYPE_MSG_RTRT) {
// 当消息类型为RT->RT时,接收的RT必须设置到cmd_wd1中,发送的RT设置到cmd_wd2中
if (0 == P(rtType)[i]) {
bc_block.cmd_wd1 = CORE_Set_BC_Command(dev_num, channel_num, P(rtAddr)[i], P(rtType)[i], 0, P(subAddr)[i]);
bc_block.cmd_wd2 = CORE_Set_BC_Command(dev_num, channel_num, P(rtAddr)[i + 1], P(rtType)[i + 1], 0, P(subAddr)[i + 1]);
} else {
bc_block.cmd_wd1 = CORE_Set_BC_Command(dev_num, channel_num, P(rtAddr)[i + 1], P(rtType)[i + 1], 0, P(subAddr)[i + 1]);
bc_block.cmd_wd2 = CORE_Set_BC_Command(dev_num, channel_num, P(rtAddr)[i], P(rtType)[i], 0, P(subAddr)[i]);
}
} else {
bc_block.cmd_wd1 = CORE_Set_BC_Command(dev_num, channel_num, P(rtAddr)[i], P(rtType)[i], 0, P(subAddr)[i]);
}
bc_block.im_gap = 10;

/*
CORE_BC_Write_Block 函数将用户设置好的 BC BLOCK,通过向 API 函数传入结构体的方式写到板卡内存中。
devnum:设备号;
channel_num:通道编号(从 0 开始编号),取值范围 0~3;
msg_num:BC BLOCK 编号(需要为哪个 BLOCK 分配消息);
bc_block:需设置的 BC BLOCK 结构体
*/
if (CORE_BC_Write_Block(dev_num, channel_num, i, &bc_block) == FAILURE) {
LOG_ERROR("CORE_BC_Write_Block Failure,channel_num = %d\n", (int)channel_num);
return false;
}

if (bcMsgType == BC_BLOCK_TYPE_MSG_BCRT) {
/*
CORE_BC_Write_Buffer 函数将用户设置好的 BC BLOCK 对应的消息,通过向API 函数传入结构体的方式写到板卡内存中
devnum:设备号
channel_num:通道编号(从 0 开始编号),取值范围 0~3;
msg_num:BC BLOCK 编号(需要为哪个 BLOCK 分配消息); // 指定分配的通道
buffnum:BC BLOCK 对应的消息编号;
msg_buff:需设置的 CORE_BC_MSG_BUFFER 结构体的指针。
*/
if (CORE_BC_Write_Buffer(dev_num, channel_num, i, 0, &bcinfo->bc_sabuf_) == FAILURE) { // 这里自定义一个编号吧
LOG_ERROR("CORE_BC_Write_Buffer Failure,channel_num = %d\n", (int)channel_num);
return false;
}
bcinfo->bc_rt_nums.push_back(i);
} else if (bcMsgType == BC_BLOCK_TYPE_MSG_RTBC) {
bcinfo->rt_bc_nums.push_back(i);
}
}

// CORE_BC_Start 运行已经配置好的 BC
CORE_BC_Start(dev_num, channel_num, 0);

/*****************************解析协议json文件, 将协议字段的类型放入数组中***********************/
nlohmann::ordered_json root;
#ifdef _WIN32
std::ifstream(P(filename).c_str()) >> root;
#else
std::string strfilePath = P(filename).c_str();
std::string strfile = "protocol/" + strfilePath.substr(strfilePath.find_last_of("/") + 1);
if (access(strfile.c_str(), F_OK) == -1) {
return false;
}
std::ifstream(strfile.c_str()) >> root;
#endif

for (const auto& field : root["Protocol fields"]["bc_rt"]) {
std::vector<std::string> innerVector;
for (const auto& subfield : field) {
innerVector.push_back(subfield["type"]);
}
if (innerVector.size() > 0) {
bcinfo->bc_rt_vars.push_back(innerVector);
}
}

for (const auto& field : root["Protocol fields"]["rt_bc"]) {
std::vector<std::string> innerVector;
for (const auto& subfield : field) {
innerVector.push_back(subfield["type"]);
}
bcinfo->rt_bc_vars.push_back(innerVector);
}

binit_ = true; // 标识已完成初始化
LOG_INFO("CAV1553B_BC_Init success...\n");
return true;
}

/**********************************
在此函数中编写自定义代码
输入变量:
输出变量:
参数:bsend, channelNum, devNum, filename, rtAddr, subAddr
状态变量:
示例:O(输出变量) = I(输入变量) + P(参数)
***********************************/
void Block_Port_1553B_BC::runAlgorithm(void* extra)
{
CAV1553B_BC_INFO* bcinfo = static_cast<CAV1553B_BC_INFO*>(bcinfo_);

// BC->RT
size_t pos = 0;
for (size_t i = 0; i < bcinfo->bc_rt_nums.size(); i++) {
size_t offset = 0;
for (size_t j = 0; j < bcinfo->bc_rt_vars[i].size(); j++) {
size_t var_len = type_len(bcinfo->bc_rt_vars[i][j]);
convert_var_to_buffer(bcinfo->bc_rt_vars[i][j], offset, (uint8_t*)bcinfo->bc_sabuf_.data_wds,
I(p_dynamic_Input_).ptr_[pos], var_len);
offset += var_len;
pos++;
}

// 不能超过缓存大小
int msg_num = bcinfo->bc_rt_nums[i];
if (offset <= bcinfo->data_size_) {
if (SUCCESS == CORE_BC_Write_Buffer(bcinfo->dev_num_, bcinfo->channel_num_, msg_num, 0, &bcinfo->bc_sabuf_)) {
}
}
}

// RT->BC
pos = 0;
for (size_t i = 0; i < bcinfo->rt_bc_nums.size(); i++) {
int msg_num = bcinfo->rt_bc_nums[i];
if (SUCCESS == CORE_BC_Read_Buffer(bcinfo->dev_num_, bcinfo->channel_num_, msg_num, 0, &bcinfo->bc_sabuf_)) {
size_t offset = 0;
for (size_t j = 0; j < bcinfo->rt_bc_vars[i].size(); j++) {
size_t var_len = type_len(bcinfo->rt_bc_vars[i][j]);
*O(p_dynamic_Output_).ptr_[pos] = convert_buffer_to_var(bcinfo->rt_bc_vars[i][j], offset, (uint8_t*)bcinfo->bc_sabuf_.data_wds);
offset += var_len;
pos++;
}
}
}

// memset(&bcinfo->bc_sabuf_, 0, sizeof(bcinfo->bc_sabuf_)); // 清空上次数据
}

/**********************************
在此函数中编写自定义积分函数
***********************************/
int32_t Block_Port_1553B_BC::integral(int32_t msg, double t, double* state, double* derivative)
{
return 0;
}

/**********************************
在此函数中释放内部变量资源
内部变量:bcinfo_
***********************************/
void Block_Port_1553B_BC::destroyInternalVariable()
{
// 是否调用了初始化函数,默认为false(控制引擎会出现直接调用destroy的情况,而成员变量si_未初始化被使用会导致崩溃)
if (!binit_) {
return;
}
CAV1553B_BC_INFO* bcinfo = static_cast<CAV1553B_BC_INFO*>(bcinfo_);

auto iter = bcinfo->init_info_1553b_->find({ bcinfo->dev_num_, bcinfo->channel_num_ });
if (iter == bcinfo->init_info_1553b_->end() || !iter->second) {
CORE_BC_Stop(bcinfo->dev_num_, bcinfo->channel_num_);
}

delete bcinfo;
}

3. 测试

测试场景包含BC->RT, RT->BC, RT->RT,下面是我们产品一个BC对应的设置界面。

这里给BC添加了3条消息,分别是bc->rt, rt->bc, rt->rt。它们是一个数组,一一对应,只有msgType字段少一个是因为rt->rt这1条消息有2个rt,还有需要注意rtType字段的收/发是针对rt来的。

最后,时间匆忙,文章整理得比较粗糙,不过上面的两个示例程序是现场正式环境验证通过了的,封装它们是踩了无数的坑过来的。关于1553B有任何疑问欢迎留言交流~~