历史上的今天
返回首页

历史上的今天

今天是:2025年07月28日(星期一)

正在发生

2021年07月28日 | DW1000开发笔记(五)DW1000使用轮询方式接收数据

2021-07-28 来源:eefocus

0、准备工作

之前的STM32L4小熊派开发板用于发送数据,这里我们使用一个STM32G070RB的板子连接DW1000官方评估板,作为数据接收端,硬件连接方式和STM32CubeMX工程配置生成请参考第二篇文章。


这里DW1000评估板和STM32G0开发板的连接情况如下表:

DW1000评估板引脚名STM32G0引脚
RSTPB3(输出)(评估板没有,预留出来这个引脚)
WAKEUPPB2(输出)
IRQPB3(EXTI输入)
SPI_MISOPC2(SPI2_MISO)
SPI_MOSIPC3(SPI2_MOSI)
SPI_SCKPB13(SPI2_SCK)
SPI_CSnPB12(SPI2_NSS)

实物如下图:

接下来参考第二篇文章,使用STM32CubeMX配置SPI2、USART1、以及额外的两个GPIO,并测试是否可以正确读取DeviceID。


测试无误后,参考第三篇文章,将之前移植的HAL库通用驱动复制过来,复制过来之后,如图将驱动添加到MDK工程中,将头文件路径添加到MDK中:

接着需要在dw1000.h中配置控制引脚号,并根据板子实际的时钟主频来修改SPI配置高速率和低速率的函数,这里STM32G0T0RB的主频为64Mhz,SPI低速率最大3Mhz,所以低速率分频系数应该为32分频,SPI高速率最大20Mhz,所以高速率分频系数为4,综上所述,改为如下配置:


#ifndef _DW1000_H_

#define _DW1000_H_


#include "stm32g0xx_hal.h"


/*

CS <-------------  PB12

RST <------------- PB4

WAKEUP <---------- PB2

*/

#define DW1000_CS_PORT GPIOB

#define DW1000_CS_PIN GPIO_PIN_12

#define DW1000_RST_PORT GPIOB

#define DW1000_RST_PIN GPIO_PIN_4

#define DW1000_WAKEUP_PORT     GPIOB

#define DW10000_WAKEUP_PIN     GPIO_PIN_2


/*

IRQ --------------> PB3

*/

#define DW1000_IRQn_TYPE EXTI2_3_IRQn

#define DW1000_IRQ_PORT     GPIOB

#define DW1000_IRQ_PIN GPIO_PIN_3


/*

SPI Interface <---> SPI2

SPI_CS <----------> PB12

SPI_CLK <---------> PB13

SPI_MISO <--------> PC2

SPI_MOSI <--------> PC3

*/

extern SPI_HandleTypeDef hspi2;

#define DW1000_SPI_Handle hspi2


/*

    SPI rate = HCLK / SPI_BAUDRATEPRESCALE

    SPI low rate must less than 3Mhz

    SPI High rate must less than 20Mhz

*/

#define SPI_LOW_RATE    SPI_BAUDRATEPRESCALER_32

#define SPI_HIGH_RATE   SPI_BAUDRATEPRESCALER_4


void reset_DW1000(void);

void spi_set_rate_low(void);

void spi_set_rate_high(void);


#endif /* _DW1000_H_ */


之后参考第三篇文章,测试使用驱动初始化DW1000,测试结果如下:

一、移植官方示例

1. 复制官方示例文件

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

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

将其添加到MDK工程中:

2. 修改官方示例文件

① 修改替换头文件:

② 修改函数名,修改打印和延时函数:

添加打印信息:

/* hex dump */

printf("Recv Frame, frame_len is %d, frame data:rn", frame_len);

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

{

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

}

printf("rn");



修改完成。


3. 调用示例代码

修改main.c,移除我们之前自己添加的所有测试代码。


接着先引入外部定义:


/* USER CODE BEGIN PFP */

extern int example_application_entry(void);

/* USER CODE END PFP */


然后在main函数中调用:


/* USER CODE BEGIN 2 */

printf("DW1000 UWB ic port on STM32G0 board By Mculover666rn");


example_application_entry();

 

/* USER CODE END 2 */


需要注意:


① 此函数需要在GPIO、USART、SPI外设初始化完成之后调用;

② 此函数中已经包含while(1)循环,所以此函数之后的代码无效。


4. 移植结果

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


此时在等待接收数据,将第四节中完成的数据发送板上电,即可接收到发送板发送的数据:

示例程序移植成功。


二、示例程序分析

1. DW1000初始化API

和第四篇文章相同。


2. DW1000配置API(重点)

和第四篇文章相同。


3. DW1000使用轮询方式接收数据流程

3.1. 轮询接收流程

3.2. 接收使能API

该API的定义在deca_device_api.h中,实现在deca_device.c中,其原型如下:

int dwt_rxenable(int mode);


该函数使能DW1000接收数据。

入参只有一个,表示接收数据模式,意义如下表:

意义
0立即使能接收
1设置延迟接收
3
4

这些值都有对应的宏定义:

#define DWT_START_RX_IMMEDIATE  0

#define DWT_START_RX_DELAYED    1    // Set up delayed RX, if "late" error triggers, then the RX will be enabled immediately

#define DWT_IDLE_ON_DLY_ERR     2    // If delayed RX failed due to "late" error then if this

                                     // flag is set the RX will not be re-enabled immediately, and device will be in IDLE when function exits

#define DWT_NO_SYNC_PTRS        4    // Do not try to sync IC side and Host side buffer pointers when enabling RX. This is used to perform manual RX

                                     // re-enabling when receiving a frame in double buffer mode.


返回值也有两个:

返回值意义
DWT_SUCCESS使能成功
DWT_ERROR使能错误(如果延迟时间已过,则延迟接收失败)

3.3. 查询中断标志寄存器

while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))  { };


dwt_read32bitreg用来读取DW1000中一个32位的寄存器,SYS_STATUS_ID表示系统状态寄存器(System event Status Register)的ID:


#define SYS_STATUS_ID           0x0F            /* System event Status Register */


SYS_STATUS_RXFCG表示该寄存器中的RXFCG位,该位在接收到一帧数据成功后会被设置为1:


#define SYS_STATUS_RXFCG        0x00004000UL    /* Receiver FCS Good */


SYS_STATUS_RXFCE表示该寄存器中的RXFCE,该位在接收一帧数据错误后会被设置为1:


#define SYS_STATUS_RXFCE        0x00008000UL    /* Receiver FCS Error */


查询到这两位被设置之后,意味着接收到数据,但成功还是失败未知,进一步进行判断,使用完毕后,向对应的位写1,清空该位:


if (status_reg & SYS_STATUS_RXFCG) {

//接收成功

/* Clear good RX frame event in the DW1000 status register. */

    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);

} else {

//接收失败


/* Clear RX error events in the DW1000 status register. */

    dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);

}


3.4. 读取接收的帧长度

判断到接收成功后,读取接收帧信息寄存器( RX_FINFO 寄存器),获取帧的信息:


这两个数据域的作用如下:

这里读取的时候有三种读取模式:


只读取帧长度

只读取帧长度扩展

同时读取帧长度和帧长度扩展

#define RX_FINFO_RXFLEN_MASK    0x0000007FUL    /* Receive Frame Length (0 to 127) */

#define RX_FINFO_RXFLE_MASK     0x00000380UL    /* Receive Frame Length Extension (0 to 7)<<7 */

#define RX_FINFO_RXFL_MASK_1023 0x000003FFUL    /* Receive Frame Length Extension (0 to 1023) */


3.5. 读取接收的帧内容API

该API的定义在deca_device_api.h中,实现在deca_device.c中,其原型如下:



/*! ------------------------------------------------------------------------------------------------------------------

 * @fn dwt_readrxdata()

 *

 * @brief This is used to read the data from the RX buffer, from an offset location give by offset parameter

 *

 * input parameters

 * @param buffer - the buffer into which the data will be read

 * @param length - the length of data to read (in bytes)

 * @param rxBufferOffset - the offset in the rx buffer from which to read the data

 *

 * output parameters

 *

 * no return value

 */

void dwt_readrxdata(uint8 *buffer, uint16 length, uint16 rxBufferOffset);


该函数从DW1000接收缓冲区中读取接收的帧的内容。


入参有三个,意义如下表:

意义
buffer用于存储读取的内容
length读取的数据的长度(一般为上一步获取到的帧长度)
rxBufferOffset读取开始时在接收缓冲区中的偏移量

至此,DW1000接收示例代码移植、学习完成。

推荐阅读

史海拾趣

Hendon Semiconductors公司的发展小趣事

Hendon Semiconductors以其强大的定制化集成电路设计能力而闻名。公司拥有一支经验丰富的设计团队,能够为客户提供从概念到量产的一站式解决方案。这种定制化服务不仅满足了客户对特殊功能和高性能的需求,也帮助Hendon Semiconductors在竞争激烈的市场中脱颖而出。通过不断积累成功案例和技术经验,Hendon Semiconductors逐渐在定制化集成电路设计领域建立了良好的口碑。

GWM Associates公司的发展小趣事
选择具有低噪声系数和高增益的放大器器件,如低噪声运算放大器(LNA)。
华润微(CRMICRO)公司的发展小趣事

华润微的前身可以追溯到1983年成立的香港华科电子公司。这家公司在电子行业中默默耕耘,逐渐积累了技术实力和市场份额。1999年,公司开始涉足6英寸晶圆代工业务,标志着其向半导体制造领域的进军。经过数年的发展和积累,华润微于2002年收购了中国华晶电子集团公司,进一步扩大了其业务范围和市场份额。此后,华润微不断壮大,逐步成为电子行业的佼佼者。

Adaptive Networks Inc公司的发展小趣事

尽管面临市场终端景气度低迷等挑战,华润微依然保持稳健的发展态势。公司积极应对市场变化,通过优化产品结构、加大研发投入等措施,不断提升自身竞争力。同时,华润微也看到了新能源业务等领域的巨大潜力,将其作为未来发展的重要方向。通过不断的技术创新和市场拓展,华润微有望在电子行业中实现更加辉煌的成就。

Advanced Analog公司的发展小趣事

创新是Advanced Analog公司发展的核心动力。公司始终坚持自主研发和技术创新,不断推出新的产品和技术。这些新产品不仅满足了市场的多样化需求,也进一步巩固了公司在电源管理IC领域的领先地位。同时,Advanced Analog还积极关注行业发展趋势和未来技术走向,为公司的长远发展做好战略布局。

EXXELIA Group公司的发展小趣事

创新是Advanced Analog公司发展的核心动力。公司始终坚持自主研发和技术创新,不断推出新的产品和技术。这些新产品不仅满足了市场的多样化需求,也进一步巩固了公司在电源管理IC领域的领先地位。同时,Advanced Analog还积极关注行业发展趋势和未来技术走向,为公司的长远发展做好战略布局。

问答坊 | AI 解惑

大赛有好的测速方案

各位GG,MM大家测速都用什么方案啊,有意的交流下,呵呵…… 流传有很多小车题目,觉得可行吗 本人认为爬坡的可能性很大 有意的交流下哈………

查看全部问答>

基于FPGA技术的存储器设计及其应用

引言   复杂可编程逻辑器件——FPGA技术在近几年的电子设计中应用越来越广泛。FPGA具有的硬件逻辑可编程性、大容量、高速、内嵌存储阵列等特点使其特别适合于高速数据采集、复杂控制逻辑、精确时序逻辑等场合的应用。而应用FPGA中的存储功能目前 ...…

查看全部问答>

在WinCE6.0操作系统上,用户如何注册自已的动态库

在WinCE6.0操作系统上,用户如何注册自已的动态库(像XP系统上一样regsvr32.exe \\xxx\\XXX.dll )…

查看全部问答>

闲话wince,散分!

~~~~~~~~~~~~~~~~~~再过两天就刚好接触wince九个月了~~~~~~~~~~~~~~感觉挺晕的。 现在来提几个问题,欢迎大家来讨论。 一、你所在公司的城市,wince研发人员数量,驱动多少?硬件多少?应用多少? 二、你们使用什么开发开发工具开发应用?使用什 ...…

查看全部问答>

EVC 开发 设计提示声音

我现在设计串口数据采集程序,希望每次数据采集完后能发出想MESSAGEBOX弹出的提示声音,请教各位该如何设计?…

查看全部问答>

Hi

大家好!我是新注册的会员,希望常跟大家交流,多多学习!…

查看全部问答>

MSP430F2274 ADC10模块_ADC10介绍

模块实现了一个10位SAR核、采样选择控制、参考电压发生器和数据传输控制器。 数据传输控制器DTC可以将ADC采样结果存储在内存的任何位置。 ADC10特点: l         高于20万次/秒的转换速率; l &n ...…

查看全部问答>

求助啊

最近搞这个LPCXpresso这个软件,发现要自己添加头文件的,麻烦啊,不知哪位有关于LPC1343的一些头文件库,可否共享一下,谢谢…

查看全部问答>

【讨论】msp430f149的评估板怎么做的阿?向大侠请教

做这个评估板除了max3221,aat3221-3.3  还需要什么器件?…

查看全部问答>

大家有没有人用过欧式96接口啊。。。??

网上只有图片,没有介绍,没法画板子啊。。…

查看全部问答>