系列文章 一、移植官方示例

1. 复制官方示例文件

将官方驱动库中example下的第一个示例移植过来:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_HAL
复制到之前移植的STM32CubeMX生成的工程文件中,并重命名文件为simple_tx_example.c:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_数据_02
将其添加到MDK工程中:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_DW1000_03

2. 修改官方示例文件

① 修改替换头文件:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_HAL_04
② 修改函数名,修改打印和延时函数:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_DW1000_05
添加两处打印信息:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_DW1000_06

DW1000开发笔记(四)DW1000使用轮询方式发送数据_STM32_07
修改完成。

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 BearPi board By Mculover666\r\n");

example_application_entry();
 
/* USER CODE END 2 */

需要注意:

此函数需要在GPIO、USART、SPI外设初始化完成之后调用
此函数中已经包含while(1)循环,所以此函数之后的代码无效

4. 移植结果

编译、下载程序,在串口助手中查看打印日志:
DW1000开发笔记(四)DW1000使用轮询方式发送数据_寄存器_08
示例程序移植成功。

二、示例程序分析

1. 轮询方式发送流程

DW1000开发笔记(四)DW1000使用轮询方式发送数据_STM32_09

2. 写入数据到缓冲区API

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

int dwt_writetxdata(uint16 txFrameLength, uint8 *txFrameBytes, uint16 txBufferOffset) ;

该函数将用户提供的待发送数据写入DW1000发送缓冲区

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

参数 意义
txFrameLength 发送数据帧的总大小,包括两个字节的CRC校验数据,最大1023,标准PHR模式允许最多127字节
txFrameBytes 指向用户待发送数据
txBufferOffset 指定DW1000 发送缓冲区中开始写入数据的偏移量

返回值也有两个:

返回值 意义
DWT_SUCCESS 写入成功
DWT_ERROR 写入错误

在本示例中,发送的帧是802.15.4e标准闪烁,包含12个字节:

static uint8 tx_msg[] = {0xC5, 0, 'D', 'E', 'C', 'A', 'W', 'A', 'V', 'E', 0, 0};
  • 第0个字节:帧类型(0xc5表示闪烁)
  • 第1个字节:帧序列号,随着每次的新帧递增
  • 第2-9个字节:Device ID(实际产品中应该唯一);
  • 第10-11个字节:CRC校验值,由DW1000自动设置;

3. 配置发送帧控制寄存器API

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

void dwt_writetxfctrl(uint16 txFrameLength, uint16 txBufferOffset, int ranging)

该函数用来在发送之前配置发送帧控制寄存器

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

参数 意义
txFrameLength 发送数据帧的总大小,包括两个字节的CRC校验数据,最大1023,标准PHR模式允许最多127字节
txBufferOffset 指定DW1000 发送缓冲区中开始写入数据的偏移量
ranging 如果这是一个范围帧,为1,否则为0

4. 立即开始发送数据API

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

int dwt_starttx(uint8 mode)

该函数用来立即开始一次发送

入参只有一个,意义如下表:

意义
0 立即发送,不期待回应
1 延迟发送,不期待回应
2 立即发送,期待回应(所以在发送完成之后自动打开接收器)
3 延迟发送,期待回应(所以在发送完成之后自动打开接收器)

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

// Defined constants for "mode" bitmask parameter passed into dwt_starttx() function.
#define DWT_START_TX_IMMEDIATE      0
#define DWT_START_TX_DELAYED        1
#define DWT_RESPONSE_EXPECTED       2

返回值也有两个:

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

5. 查询中断标志寄存器

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_TXFRS表示该寄存器中的TXFRS位,该位在发送完成后会被设置为1:

#define SYS_STATUS_TXFRS        0x00000080UL    /* Transmit Frame Sent: This is set when the transmitter has completed the sending of a frame */

DW1000开发笔记(四)DW1000使用轮询方式发送数据_STM32_10
查询到被设置之后,意味着发送完成,使用下面的这行代码向该位写1,则将该位清零,以便下次发送,另外,当下次发送使能后,该位会被自动清空

dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);

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