DW1000开发笔记(六)DW1000发送数据并等待另一个DW1000回应

本文详细记录了基于STM32的DW1000模块发送数据并等待另一DW1000响应的开发过程,包括移植官方示例代码、分析发送接收超时问题以及解决措施。通过调整发送后的等待时间及接收超时时间,最终实现了数据的正确交互。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、移植发送数据并等待响应的代码

本文中使用基于STM32F103ZET6开发板+DW1000评估板作为发送数据并等待回应端

1. 复制官方示例文件

将官方驱动库中example下的第三个示例 a 移植过来:
img
复制到之前移植的STM32CubeMX生成的工程文件中,并重命名文件为tx_wait_resp_example.c:
img

将其添加到MDK工程中:
img

将之前移植的发送demo取消工程构建(防止冲突):
img

2. 修改官方示例文件

① 修改替换头文件:
img

② 修改函数名
img

③ 修改打印和延时函数:
img
添加调试打印信息:

printf("send ok\r\n");

printf("send data:\r\n[");
/* hex dump */
for (int i = 0; i < sizeof(tx_msg); i++)
{
    printf("%02x ", tx_msg[i]);
}
printf("]\r\n");
123456789

img

printf("recv ok\r\n");

printf("recv resp data:\r\n[");
/* hex dump */
for (int i = 0; i < frame_len; i++)
{
    printf("%02x ", rx_buffer[i]);
}
printf("]\r\n");
123456789

img
修改延时函数:
img
修改完成。

3. 调用示例代码

main.c保持原来第三节中的测试代码不变。

4. 移植结果

编译、下载程序,在串口助手中查看打印日志:
img
可以看到DW1000一直在循环发送,但没有收到应答

三、移植接收数据并发送响应的代码

本文中使用基于STM32L431RCT6开发板+DW1000 E53扩展板作为接收数据并发送响应的一侧设备。

1. 复制官方示例文件

将官方驱动库中example下的第三个示例 b 移植过来:
img
复制到之前移植的STM32CubeMX生成的工程文件中,并重命名文件为rx_send_resp_example.c:
img
将其添加到MDK工程中:
img
将之前移植的接收demo取消工程构建(防止冲突):
img

2. 修改官方示例文件

① 修改替换头文件:
img

② 修改函数名
img
③ 修改打印函数:
img
再添加一些额外的调试信息:

printf("recv ok\r\n");
/* hex dump */
printf("recv data:\r\n[");
for (int i = 0; i < frame_len; i++)
{
    printf("%02x ", rx_buffer[i]);
}
printf("]\r\n");
12345678

img

printf("send resp ok\r\n");

/* hex dump */
printf("send data:\r\n[");
for (int i = 0; i < sizeof(tx_msg); i++)
{
    printf("%02x ", tx_msg[i]);
}
printf("]\r\n");
123456789

在这里插入图片描述
修改完成。

3. 调用示例代码

main.c保持原来第四节中的测试代码不变。

4. 移植结果

编译、下载程序,在串口助手中查看打印日志:
img
可以看到这一侧没有问题 ,接收到数据之后并发送响应数据回去。

此时再看等待响应的一侧:
img
发送成功但是接收数据超时,移植失败。接下来我们对照API手册,研究一下本实验中的API,之后再对此问题进行定位、分析、解决。

四、发送之后等待接收响应API分析

1. 发送并等待响应的流程

img

2. 发送并等待响应流程中需要设置的延时时间

在发生并等待响应端,延时时间有两个,设置API分别如下。

第一个是从发送完成开始,到自动打开接收模式的延时时间。使用下面的API进行设置:

void dwt_setrxaftertxdelay(uint32 rxDelayTime);
1

它的入参只有一个,表示设置的时间大小。

这个时间值的大小宽度为20bit,也就是最大为2 20 − 1 = 1048575 2^{20}-1=1048575220−1=1048575。这个时间值的单位是UWB ms,该单位与正常的时间关系为1 U W B m s = 512 / 499.2 M h z u s = 1.0256 u s 1 UWB ms = 512/499.2Mhz us = 1.0256 us1UWBms=512/499.2Mhzus=1.0256u**s

这个值最小可以设置为0,设置为0的时候,则DW1000会在发送完成后立即打开接收模式,这个操作大概需要花费6.2us的时间。而且如果设置的值小于7us,则花费的时间依然会是6.2us。

第二个是设置接收数据超时时间,即接收端在RX启用命令之后保持开着多久,其API原型如下:

void dwt_setrxtimeout(uint16 time);
1

该函数的入参也有一个,是一个16位的值(最大65535),单位依然是UWB ms,也就是1.0256us。

如果设置最大,则大约是1.0256 ∗ 65535 / 1000 = 65 m s 1.025665535/1000=65ms1.0256∗65535/1000=65m**s*。

如果设置为0,则表示禁止该超时检测功能。

该函数没有返回值,但需要注意,该功能设置的是DW1000内部硬件定时器,如果发生超时,则直接置位SY_STAT_RFTO事件标志

3. 发送数据并等待回应

写入数据到发送缓冲区和控制发送寄存器的操作和之前普通发送相同,无需赘述。

在启动发送的时候,除了设置立即发送模式(DWT_START_TX_IMMEDIATE),还要设置等待响应模式(DWT_RESPONSE_EXPECTED),如下:

/* Start transmission, indicating that a response is expected so that reception is enabled immediately after the frame is sent. */
dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);
12

4. 轮询是否接收到响应数据

如果设置了接收超时时间,还应该在轮询的时间检测是否超时(SYS_STATUS_ALL_RX_TO),如下:

/* We assume that the transmission is achieved normally, now poll for reception of a frame or error/timeout. See NOTE 8 below. */
while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_TO | SYS_STATUS_ALL_RX_ERR)))
{ };
123

其余的是成功接收到数据之后的操作,与普通数据接收没有区别。

五、接收超时问题分析(重点)

1. 问题分析

在第二块板没有上电时,第一块板在发送等待接收回应超时,因为响应数据并没有发送,所以这是正常的。

但在第二块板上电后,第二块板的日志显示确实发送响应数据成功,所以问题就出在第一块板的接收上面

根据上一节对API的分析,接收并等待回应API有两个超时值,可能会出现以下两种情况:

① 从发送完成开始,到自动打开接收模式的延时时间(dwt_setrxaftertxdelay)设置太长,还没有来得及打开接收,对方(第二块板)已发送完毕;

② 接收数据超时时间(dwt_setrxtimeout)设置太短,对方还没来得及发送,本机已经接收超时。

接下来我们分别验证这两种情况,定位问题所在。

2. 问题定位

2.1. 定位是否为情况1

将从发送完成开始,到自动打开接收模式的延时时间设置为最低,也就是0,根据API手册,设置为0之后也要花费6.7us,这时最短时间:
img
再次编译、下载,查看串口日志:
img
依然接收超时,证明问题不在这儿,将该值改回原来的60(UWB ms)

2.2. 定位是否为情况2

将接收数据超时时间设置为最长,也就是0,表示禁止接收超时:
img
编译、下载,查看串口日志:
img
接收响应数据成功,定位出问题所在,就是默认的接收超时时间5000(UWB ms)设置太短了,对方还未来的及发送回应数据,本机已接收超时

那么,接收超时时间到底该设置为多少呢?接下来我们使用STM32 Systick生成的时间戳来测量一下。

3. 测量接收时间

接收数据超时时间是接收端在RX启用命令之后保持开着多久,但是RX又是在发送完成之后自动开启的,所以我们从发送之后开始测量,到接收数据结束。

测量工具利用STM32 Systick,在HAL库中默认为1ms一次。

添加以下测试代码:

uint32_t rx_start_time = 0, rx_end_time = 0;
uint32_t rx_spend_time = 0;
12

img
在发送完成之后设置的延时使能时间大约是60us,相对与ms级别来说差了一个量级,可以忽略不计,所以在发送完成之后记录接收开始时间戳:

/* get start timestamp */
rx_start_time = HAL_GetTick();
12

img
注意:一定要在发送完成之后立即获取开始时间戳。

然后在接收到数据之后立即获取结束时间戳:

/* get end timestamp */
rx_end_time = HAL_GetTick();
12

img
最后在本次数据发送和接收完成之后,打印计算出的响应数据接收花费时间:

/* log rx spend time */
rx_spend_time = rx_end_time - rx_start_time;
printf("rx spend time is %d ms\r\n", rx_spend_time);
123

img
编译,运行,查看实际响应数据接收花费的时间:
img
可以看到,数据实际接收的时间为12ms左右,所以要设置为12000(UWB ms),一个UWB ms几乎可以按1us来算,为了保险起见,设置为15000:
img
再次编译、下载,查看串口助手结果:
img
可以看到,发送之后成功接收到响应数据。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值