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

发布者:ZenMaster123最新更新时间:2021-07-30 来源: eefocus关键字:发送数据  STM32F103ZET6 手机看文章 扫描二维码
随时随地手机看文章

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

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


1. 复制官方示例文件

将官方驱动库中example下的第三个示例 a 移植过来:

复制到之前移植的STM32CubeMX生成的工程文件中,并重命名文件为tx_wait_resp_example.c:

将其添加到MDK工程中:

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

2. 修改官方示例文件

① 修改替换头文件:

② 修改函数名

③ 修改打印和延时函数

添加调试打印信息:

printf("send okrn");


printf("send data:rn[");

/* hex dump */

for (int i = 0; i < sizeof(tx_msg); i++)

{

    printf("%02x ", tx_msg[i]);

}

printf("]rn");


printf("recv okrn");


printf("recv resp data:rn[");

/* hex dump */

for (int i = 0; i < frame_len; i++)

{

    printf("%02x ", rx_buffer[i]);

}

printf("]rn");



修改延时函数:

修改完成。


3. 调用示例代码

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


4. 移植结果

编译、下载程序,在串口助手中查看打印日志:

可以看到DW1000一直在循环发送,但没有收到应答。


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

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


1. 复制官方示例文件

将官方驱动库中example下的第三个示例 b 移植过来:

复制到之前移植的STM32CubeMX生成的工程文件中,并重命名文件为rx_send_resp_example.c:

将其添加到MDK工程中:

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

2. 修改官方示例文件

① 修改替换头文件:

② 修改函数名

③ 修改打印函数:

再添加一些额外的调试信息:

printf("recv okrn");

/* hex dump */

printf("recv data:rn[");

for (int i = 0; i < frame_len; i++)

{

    printf("%02x ", rx_buffer[i]);

}

printf("]rn");


printf("send resp okrn");


/* hex dump */

printf("send data:rn[");

for (int i = 0; i < sizeof(tx_msg); i++)

{

    printf("%02x ", tx_msg[i]);

}

printf("]rn");


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


3. 调用示例代码

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


4. 移植结果

编译、下载程序,在串口助手中查看打印日志:

可以看到这一侧没有问题 ,接收到数据之后并发送响应数据回去。

此时再看等待响应的一侧:

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


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

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

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

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

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

void dwt_setrxaftertxdelay(uint32 rxDelayTime);


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

这个时间值的大小宽度为20bit,也就是最大为 2 20 − 1 = 1048575 2^{20}-1=1048575 220−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 us 1UWBms=512/499.2Mhzus=1.0256us。


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


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

void dwt_setrxtimeout(uint16 time);


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


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


如果设置为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);


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)))

{ };


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


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

1. 问题分析

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


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


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

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

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


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


2. 问题定位

2.1. 定位是否为情况1

将从发送完成开始,到自动打开接收模式的延时时间设置为最低,也就是0,根据API手册,设置为0之后也要花费6.7us,这时最短时间:

再次编译、下载,查看串口日志:

依然接收超时,证明问题不在这儿,将该值改回原来的60(UWB ms)。


2.2. 定位是否为情况2

将接收数据超时时间设置为最长,也就是0,表示禁止接收超时:

编译、下载,查看串口日志:

接收响应数据成功,定位出问题所在,就是默认的接收超时时间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;


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

/* get start timestamp */

rx_start_time = HAL_GetTick();


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

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

/* get end timestamp */

rx_end_time = HAL_GetTick();


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

/* log rx spend time */

rx_spend_time = rx_end_time - rx_start_time;

printf("rx spend time is %d msrn", rx_spend_time);


编译,运行,查看实际响应数据接收花费的时间:

可以看到,数据实际接收的时间为12ms左右,所以要设置为12000(UWB ms),一个UWB ms几乎可以按1us来算,为了保险起见,设置为15000:

再次编译、下载,查看串口助手结果:

可以看到,发送之后成功接收到响应数据。

关键字:发送数据  STM32F103ZET6 引用地址:DW1000开发笔记(六)DW1000发送数据并等待另一个DW1000回应

上一篇:STM32 USB Mass Storage 例程调试笔记
下一篇:【STM32Cube_07】使用USART发送和接收数据(中断模式)

推荐阅读最新更新时间:2024-11-07 15:46

51单片机 串口发送数据(只是发送
51单片机 串口发送数据(只是发送)用于调试。 #include reg51.h #define uchar unsigned char #define uint unsigned int #define XTAL 11059200 // CUP 晶振频率 #define baudrate 9600 // 通信波特率 /************************************************* 函数:uart_init 功能:初始化串口 出口:void 入口:void *************************************************/ void uart
[单片机]
HAL库教程5:串口数据发送
使用CubeMX配置串口1 配置引脚   我的板子上使用插针引出了串口1,串口1连接PA8与PA9。 配置串口通信参数   使能串口1,并配置为同步模式,波特率为115200,模式8N1。 使能串口中断 查看生成的代码   引脚与中断的初始化在stm32f4xx_hal_msp.c   而通信用到的参数,如波特率校验方式等初始化在main.c。   同样是串口初始化的代码,为什么要分开写?   可能是分层思想,换板子的话,只用修改引脚与中断的函数,用户函数不用修改。比如用户关心波特率,不用关心引脚。 按键控制串口发送代码编写   通过串口打印按键的信息。 //main.c int main(vo
[单片机]
HAL库教程5:串口<font color='red'>数据</font><font color='red'>发送</font>
实现STM32的串口数据发送和printf函数重定向
在调试电机驱动程序的时候,是不能随便利用中断来进行一些寄存器或数据的查看的,不然你在运行的时候突然来一下,如果占空比大的话那可能直接就把MOS管给烧了,所以我们很多情况下只能使用USART(串口)来进行程序的调试和数据的监控了。 对于STM32来说,由于很多内容都是有库来实现的,那就省了很多时间,直接看个例子就可以写了,大致有4步步骤: 1 1、RCC始终初始化,对端口和USARTX使能时钟 2 2、初始化端口功能,RX设置为输入悬空,TX设置为复用功能的推挽输出,注意GPIO_SPEED要设置下,我没设置弄了半天都没输出 3 3、设置USARTX寄存器,波特率、数据位、校验位、停止位等 4 4、看需要是否开中断,我这里
[单片机]
51单片机:电脑向串口发送数据并控制LED灯
电脑向串口发送数据后,控制LED灯,并返回发送的数据 程序如下 #include regx52.h #include intrins.h unsigned int num; //建立全局变量 void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 8; j = 1; k = 243; do { do { while (--k); } while (--j); } while (--i); } void UartInit(void) //480
[单片机]
51单片机:电脑向串口<font color='red'>发送</font><font color='red'>数据</font>并控制LED灯
基于STM32f103zet6之使用FSMC驱动TFT
在完成IO驱动彩屏的试验后,就准备着手使用FSMC来驱动彩屏,先了解一下预备知识 一、所谓的FSMC机制 简单介绍FSMC在这篇博文里面很清楚,推荐一下http://blog.csdn.net/king_bingge/article/details/8718566 然后还有就是这篇学习笔记,也还行http://www.cnblogs.com/hduxyc/archive/2011/05/17/2048099.html 个人觉得有了这两篇博文再加上我们的参考手册足够搞定FSMC驱动彩屏了 二、FSMC之我见 开始只是谈到别人对FSMC的理解,注意这里只讨论FSMC控制TFT,也就是在FSMC的NORPSRAM
[单片机]
基于<font color='red'>STM32f103zet6</font>之使用FSMC驱动TFT
AVR 单片机UART以查询、中断方式发送数据
/**************************************************************************************************************** * AVR 单片机UART以查询、中断方式发送数据 * 说明:测试环境 硬件M16、开发平台IAR for AVR V5.11B ****************************************************************************************************************/ //------------
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved