目录
引言
今天终于又有点时间了,来测试一下星闪的数据传输速度。前面的博文已经分析了星闪的传输示例sle_uuid_client和sle_uuid_server,如果对星闪程序还不了解,可以先看看【星闪开发连载】SLE_UUID_Server和SLE_UUID_Client程序分析_sle广播功能-CSDN博客。
程序工作原理
我用来测试速度的程序也来自官方的例子sle_speed_client和sle_speed_server。这两个例子和sle_uuid_client和sle_uuid_server,也是服务器端开启广播,客户端找到服务器之后服务器端就开始数据传输,然后客户端统计传输速度并打印在日志中。
客户端
客户端接收数据的核心代码是这样的。
cpp
static void sle_uart_notification_cb(uint8_t client_id, uint16_t conn_id, ssapc_handle_value_t *data,
errcode_t status)
{
unused(client_id);
unused(conn_id);
unused(status);
g_recv_pkt_num++;
if (g_recv_pkt_num == 1) {
g_count_before_get_us = uapi_tcxo_get_us();
} else if (g_recv_pkt_num == RECV_PKT_CNT) {
g_count_after_get_us = uapi_tcxo_get_us();
printf("g_count_after_get_us = %llu, g_count_before_get_us = %llu, data_len = %d\r\n",
g_count_after_get_us, g_count_before_get_us, data->data_len);
float time = (float)(g_count_after_get_us - g_count_before_get_us) / 1000000.0; /* 1s = 1000000.0us */
printf("time = %d.%d s\r\n", GetFloatInt(time), GetFloatDec(time));
uint16_t len = data->data_len;
float speed = len * RECV_PKT_CNT * 8 / time; /* 1B = 8bits */
printf("speed = %d.%d bps\r\n", GetFloatInt(speed), GetFloatDec(speed));
g_recv_pkt_num = 0;
}
}
这段代码是一个回调函数,用于处理通过UART(通用异步接收/发送)接口接收到的数据。它记录了接收到的数据包数量,并在接收到一定数量的数据包后计算数据传输速率。下面是对代码的逐行解释:
-
static void sle_uart_notification_cb(...)
这是一个静态函数,作为UART通知的回调函数。它接收四个参数:client_id
(客户端ID),conn_id
(连接ID),data
(指向包含接收数据的结构体的指针),以及status
(接收操作的状态码)。 -
unused(client_id); unused(conn_id); unused(status);
这三行代码是为了避免编译器警告而添加的。它们表明函数的参数client_id
、conn_id
和status
在这个函数中没有被使用。 -
g_recv_pkt_num++;
这行代码将全局变量g_recv_pkt_num
(接收到的数据包数量)增加1。 -
if (g_recv_pkt_num == 1) { ... }
如果这是接收到的第一个数据包,那么执行大括号内的代码。 -
g_count_before_get_us = uapi_tcxo_get_us();
获取当前时间(以微秒为单位),并将其存储在g_count_before_get_us
变量中。这通常用于测量时间间隔。 -
else if (g_recv_pkt_num == RECV_PKT_CNT) { ... }
如果接收到的数据包数量等于预设的RECV_PKT_CNT
,则执行大括号内的代码。 -
g_count_after_get_us = uapi_tcxo_get_us();
再次获取当前时间,并存储在g_count_after_get_us
变量中。 -
printf(...)
打印出接收到的数据包的结束时间、开始时间以及数据长度。 -
float time = (float)(g_count_after_get_us - g_count_before_get_us) / 1000000.0;
计算从接收第一个数据包到接收最后一个数据包所花费的总时间,并将其转换为秒。 -
printf("time = %d.%d s\r\n", GetFloatInt(time), GetFloatDec(time));
打印出花费的总时间,其中GetFloatInt
和GetFloatDec
函数分别获取浮点数的整数部分和小数部分。 -
uint16_t len = data->data_len;
获取接收到的数据长度。 -
float speed = len * RECV_PKT_CNT * 8 / time;
计算数据传输速率。这里假设1字节等于8位。 -
printf("speed = %d.%d bps\r\n", GetFloatInt(speed), GetFloatDec(speed));
打印出数据传输速率。 -
g_recv_pkt_num = 0;
将接收到的数据包数量重置为0,为下一轮数据包的接收做准备。
这个回调函数的主要作用是在接收到一定数量的数据包后,计算并打印出数据的传输速率。它通过记录接收数据包的开始和结束时间,以及每个数据包的长度,来计算总的传输时间和速率。
服务器端
服务器端的发送程序是这样的。
cpp
void send_data_thread_function(void)
{
sle_set_data_len(g_sle_conn_hdl, DEFAULT_SLE_SPEED_DATA_LEN);
sle_set_phy_t phy_parm = {
.tx_format = SLE_RADIO_FRAME_2,
.rx_format = SLE_RADIO_FRAME_2,
.tx_phy = SLE_PHY_4M,
.rx_phy = SLE_PHY_4M,
.tx_pilot_density = SLE_PHY_PILOT_DENSITY_16_TO_1,
.rx_pilot_density = SLE_PHY_PILOT_DENSITY_16_TO_1,
.g_feedback = 0,
.t_feedback = 0,
};
sle_set_phy_param(g_sle_conn_hdl, &phy_parm);
sle_set_mcs(g_sle_conn_hdl, DEFAULT_SLE_SPEED_MCS);
int i = 0;
count_before_get_us = uapi_tcxo_get_us();
for (int j = 0; j < SEND_PKT_TIMES; j++) {
while (i < SEND_PKT_NUMS) {
if (sle_flow_ctrl_flag() > 0) {
i++;
data[0] = (i >> 8) & 0xFF; /* offset 8bits */
data[1] = i & 0xFF;
sle_uuid_server_send_report_by_handle_id(data, PKT_DATA_LEN, g_sle_conn_hdl);
}
}
i = 0;
}
count_after_get_us = uapi_tcxo_get_us();
printf("count_us = %llu\r\n", count_after_get_us - count_before_get_us);
printf("[uuid server]send data thread end.\n");
}
这段程序是一个用于发送数据的线程函数,它使用了星闪低功耗无线通信协议。下面是对程序中每个部分的解释:
-
sle_set_data_len(g_sle_conn_hdl, DEFAULT_SLE_SPEED_DATA_LEN);
这行代码设置了连接句柄g_sle_conn_hdl
的数据长度为DEFAULT_SLE_SPEED_DATA_LEN
。这通常用于配置通信的数据包大小。 -
sle_set_phy_t phy_parm = {...};
这是一个结构体变量phy_parm
,用于存储物理层参数。它设置了发送和接收的格式、物理层速率、导频密度等参数。这些参数通常用于配置无线通信的物理层特性。 -
sle_set_phy_param(g_sle_conn_hdl, &phy_parm);
这行代码将之前设置的物理层参数应用到连接句柄g_sle_conn_hdl
上。 -
sle_set_mcs(g_sle_conn_hdl, DEFAULT_SLE_SPEED_MCS);
这行代码设置了调制编码方案(Modulation and Coding Scheme,MCS),这影响数据传输的速率和可靠性。 -
int i = 0;
定义了一个整型变量i
并初始化为0。 -
count_before_get_us = uapi_tcxo_get_us();
这行代码获取当前时间(以微秒为单位),并将其存储在count_before_get_us
变量中。这通常用于测量时间间隔。 -
for (int j = 0; j < SEND_PKT_TIMES; j++) { ... }
这是一个循环,它将执行SEND_PKT_TIMES
次。每次循环都代表一次发送数据的尝试。 -
while (i < SEND_PKT_NUMS) { ... }
这是一个嵌套循环,它将执行SEND_PKT_NUMS
次。每次循环都代表一次数据包的发送。 -
if (sle_flow_ctrl_flag() > 0) { ... }
这行代码检查流量控制标志,如果返回值大于0,则表示可以发送数据。 -
data[0] = (i >> 8) & 0xFF; data[1] = i & 0xFF;
这两行代码将变量i
的值拆分成两个字节,并存储在数组data
中。这是为了将i
的值作为数据包的内容发送。 -
sle_uuid_server_send_report_by_handle_id(data, PKT_DATA_LEN, g_sle_conn_hdl);
这行代码通过连接句柄g_sle_conn_hdl
发送数据。data
是要发送的数据,PKT_DATA_LEN
是数据包的长度。 -
count_after_get_us = uapi_tcxo_get_us();
这行代码再次获取当前时间,并存储在count_after_get_us
变量中。 -
printf("count_us = %llu\r\n", count_after_get_us - count_before_get_us);
这行代码打印出发送数据所花费的总时间(微秒)。 -
printf("[uuid server]send data thread end.\n");
这行代码表示数据发送线程的结束。
整个函数的作用是在指定的连接句柄上,按照预设的物理层参数和MCS,发送一定次数和数量的数据包,并且测量发送这些数据包所花费的时间。这个函数可能是用于测试无线通信模块的性能。
测试记录
编译和烧录程序的步骤在前面已经说过了,这里不再重复。
近距离测试
首先,我们把两块开发板连接在同一台电脑下进行测试。
下面是客户端的部分日志:
g_count_after_get_us = 33124582, g_count_before_get_us = 31869704, data_len = 236
time = 1.25 s
speed = 1504528.64 bps
g_count_after_get_us = 34384594, g_count_before_get_us = 33129673, data_len = 236
time = 1.25 s
speed = 1504477.28 bps
g_count_after_get_us = 35639581, g_count_before_get_us = 34389689, data_len = 236
time = 1.24 s
speed = 1510530.56 bps
g_count_after_get_us = 36894586, g_count_before_get_us = 35644678, data_len = 236
time = 1.24 s
speed = 1510511.20 bps
g_count_after_get_us = 38147077, g_count_before_get_us = 36899683, data_len = 236
time = 1.24 s
speed = 1513555.52 bps
g_count_after_get_us = 39402104, g_count_before_get_us = 38152184, data_len = 236
time = 1.24 s
speed = 1510496.64 bps
g_count_after_get_us = 40664586, g_count_before_get_us = 39407199, data_len = 236
time = 1.25 s
speed = 1501526.56 bps
APP|[SYS INFO] mem: used:91156, free:272752; log: drop/all[0/0], at_recv 0.
g_count_after_get_us = 41923357, g_count_before_get_us = 40669697, data_len = 236
time = 1.25 s
speed = 1505990.56 bps
g_count_after_get_us = 43184591, g_count_before_get_us = 41928443, data_len = 236
time = 1.25 s
speed = 1503007.68 bps
g_count_after_get_us = 44444590, g_count_before_get_us = 43189683, data_len = 236
time = 1.25 s
speed = 1504494.8 bps
[Disconnected]
addr:11:**:**:**:55:66, handle:00
[ssap client] conn state changed conn_id:0, addr:11***5566
[ssap client] conn state changed disc_reason:0x7
APP|[SYS INFO] mem: used:89440, free:274468; log: drop/all[0/0], at_recv 0.
下面是服务器的部分日志。
cpp
[uuid server] init ok
[Connected]
addr:13:**:**:**:00:51, handle:00
[ACore] sle adv cbk in, event:7 status:0
[uuid server] connect state changed conn_id:0x00, conn_state:0x1, pair_state:0x1, disc_reason:0x0
[uuid server] connect state changed addr:13:**:**:**:00:51
sle announce terminal id:01
[Connected param update] addr:13:**:**:**:00:51, handle:00
[ssap server] updat state changed conn_id:0, interval = 0a
[uuid server] pair complete conn_id:00, status:0
[uuid server] pair complete addr:13:**:**:**:00:51
[uuid server] ssaps write request cbk server_id:0, conn_id:0, mtu_size:200, status:0
[uuid server] ssaps write request cbk server_id:1, conn_id:0, handle:1, status:0
[uuid server] ssaps read request cbk server_id:1, conn_id:0, handle:1, status:0
kthread success
update ssap send report handle: pre handle:ffff, current:0
[ssap server] sle_sample_update_req_cbk interval_min:f6, interval_max:6a01
xo update temp:4,diff:0,xo:0x3083c
APP|[SYS INFO] mem: used:100592, free:263188; log: drop/all[0/0], at_recv 0.
[Disconnected]
addr:13:**:**:**:00:51, handle:00
[uuid server] connect state changed conn_id:0x00, conn_state:0x2, pair_state:0x3, disc_reason:0x7
[uuid server] connect state changed addr:13:**:**:**:00:51
count_us = 15872547
[uuid server]send data thread end.
测试速度大概是1.5Mbps,由于距离很近,没有啥干扰,所以没有丢包是正常的。
相邻两个房间之间的测试
然后我把服务器端放置到隔壁房间的中间。然后重启客户端和服务器,再进行测试。下面是客户端的结果。
cpp
[ssap client] sle_sample_update_req_cbk interval_min = f6, interval_max = 6a01
g_count_after_get_us = 3615572, g_count_before_get_us = 1641760, data_len = 236
time = 1.97 s
speed = 956524.72 bps
xo update temp:4,diff:0,xo:0x3083c
g_count_after_get_us = 4986811, g_count_before_get_us = 3620621, data_len = 236
time = 1.36 s
speed = 1381945.44 bps
g_count_after_get_us = 6351833, g_count_before_get_us = 4991867, data_len = 236
time = 1.35 s
speed = 1388270.8 bps
g_count_after_get_us = 7703058, g_count_before_get_us = 6356906, data_len = 236
time = 1.34 s
speed = 1402516.32 bps
g_count_after_get_us = 9060587, g_count_before_get_us = 7708153, data_len = 236
time = 1.35 s
speed = 1396001.44 bps
g_count_after_get_us = 10429349, g_count_before_get_us = 9065620, data_len = 236
time = 1.36 s
speed = 1384439.20 bps
APP|[SYS INFO] mem: used:91512, free:272396; log: drop/all[0/0], at_recv 0.
g_count_after_get_us = 11794330, g_count_before_get_us = 10434390, data_len = 236
time = 1.35 s
speed = 1388296.48 bps
g_count_after_get_us = 13180628, g_count_before_get_us = 11799443, data_len = 236
time = 1.38 s
speed = 1366942.8 bps
g_count_after_get_us = 14543058, g_count_before_get_us = 13185648, data_len = 236
time = 1.35 s
speed = 1390884.16 bps
g_count_after_get_us = 15901871, g_count_before_get_us = 14548139, data_len = 236
time = 1.35 s
speed = 1394663.4 bps
g_count_after_get_us = 17280618, g_count_before_get_us = 15906895, data_len = 236
time = 1.37 s
speed = 1374367.20 bps
g_count_after_get_us = 18668061, g_count_before_get_us = 17285703, data_len = 236
time = 1.38 s
speed = 1365782.24 bps
g_count_after_get_us = 20076818, g_count_before_get_us = 18673155, data_len = 236
time = 1.40 s
speed = 1345052.16 bps
APP|[SYS INFO] mem: used:91060, free:272848; log: drop/all[0/0], at_recv 0.
g_count_after_get_us = 21476804, g_count_before_get_us = 20081897, data_len = 236
time = 1.39 s
speed = 1353495.20 bps
[Disconnected]
测试速率有了比较明显的下降,大概在1.34~1.39Mbps 之间。
相隔一个房间的两个房间之间的测试
我把服务器移动到相隔一个房间的另一个房间进行测试。测试位置在房间中尽可能靠近客户端的地方,测试结果如下。
cpp
[Connected]
addr:11:**:**:**:55:66, handle:00
[ssap client] conn state changed conn_id:0, addr:11***5566
[ssap client] conn state changed disc_reason:0x0
[ssap client] sle_sample_update_req_cbk interval_min = 0a, interval_max = 0a
[Connected param update] addr:11:**:**:**:55:66, handle:00
[ssap client] updat state changed conn_id:0, interval = 0a
[ssap client] pair complete conn_id:0, addr:11***5566
ssapc exchange info, conn_id:0, err_code:0
[ssap client] pair complete client id:0 status:0
[ssap client] exchange mtu, mtu size: 512, version: 1.
discovery character cbk complete in
[ssap client] find structure cbk client: 0 conn_id:0 status: 0
[ssap client] find structure start_hdl:[0x01], end_hdl:[0x02], uuid len:2
[ssap client] structure uuid:[0xcd][0xab]
[ssap client] find structure cmp cbk client id:0 status:0 type:1 uuid len:0
[ssap client] find structure cmp cbk structure uuid[0]:[0x00]
[ssap client] find structure cmp cbk structure uuid[1]:[0x00]
[ssap client] find structure cmp cbk structure uuid[2]:[0x00]
[ssap client] find structure cmp cbk structure uuid[3]:[0x00]
[ssap client] find structure cmp cbk structure uuid[4]:[0x00]
[ssap client] find structure cmp cbk structure uuid[5]:[0x00]
[ssap client] find structure cmp cbk structure uuid[6]:[0x00]
[ssap client] find structure cmp cbk structure uuid[7]:[0x00]
[ssap client] find structure cmp cbk structure uuid[8]:[0x00]
[ssap client] find structure cmp cbk structure uuid[9]:[0x00]
[ssap client] find structure cmp cbk structure uuid[10]:[0x00]
[ssap client] find structure cmp cbk structure uuid[11]:[0x00]
[ssap client] find structure cmp cbk structure uuid[12]:[0x00]
[ssap client] find structure cmp cbk structure uuid[13]:[0x00]
[ssap client] find structure cmp cbk structure uuid[14]:[0x00]
[ssap client] find structure cmp cbk structure uuid[15]:[0x00]
ssapc write rsp handle:1
[sle write_req_complete_cbk]conn_id:0, err_code:0
[ssap client] write cfm cbk, client id: 0 status:0.
ssapc read rsp handle:0, data len:4
[ssap client] read cfm cbk client id: 0 conn id: 0 status: 0
[ssap client] read cfm cbk handle: 0, type: 10 , len: 4
[ssap client] read cfm cbk[0] 0x11
[ssap client] read cfm cbk[1] 0x22
[ssap client] read cfm cbk[2] 0x33
[ssap client] read cfm cbk[3] 0x44
[ssap client] sle_sample_update_req_cbk interval_min = f6, interval_max = 6a01
g_count_after_get_us = 100214318, g_count_before_get_us = 96838781, data_len = 236
time = 3.37 s
speed = 559318.44 bps
APP|[SYS INFO] mem: used:91352, free:272556; log: drop/all[0/0], at_recv 0.
g_count_after_get_us = 103493092, g_count_before_get_us = 100223210, data_len = 236
time = 3.26 s
speed = 577390.88 bps
g_count_after_get_us = 106793080, g_count_before_get_us = 103498373, data_len = 236
time = 3.29 s
speed = 573040.32 bps
g_count_after_get_us = 109516827, g_count_before_get_us = 106798253, data_len = 236
time = 2.71 s
speed = 694481.76 bps
APP|[SYS INFO] mem: used:90952, free:272956; log: drop/all[0/0], at_recv 0.
[Disconnected]
可以看到速率已经降到570kbps了。两个墙的衰减是非常明显的。
我又把服务器移动到尽可能远离客户端的位置,这时客户端只能收到微弱的广播信号,已经基本无法连接上服务器了。
cpp
sle enable
[adv_report] event_type: 0x03, addr_type: 0x0000, addr: 11:**:**:**:55:66
[adv_report] data length: 6, data: 0x02 0x01 0x01 0x02 0x02 0x00
xo update temp:4,diff:0,xo:0x3083c
APP|[SYS INFO] mem: used:89608, free:274300; log: drop/all[0/0], at_recv 0.
[Disconnected]
addr:11:**:**:**:55:66, handle:00
[ssap client] conn state changed conn_id:0, addr:11***5566
[ssap client] conn state changed disc_reason:0x0
xo update temp:3,diff:0,xo:0x3083c
结语
我测试的结果看,星闪的测试结果符合预期。