UWB-DW1000初始化、发送和接收详解(一)

DWM1000简介

DWM1000板子上的DW1000芯片,是基于CMOS的、低功耗的无线收发集成电路,遵循IEEE 802.15.4-2011协议中的UWB标准芯片。DWM1000不需要用户去设计电路,因为模块上包含天线,无线通讯模块及相关电路。
标准的IEEE 802.15.4-2011 UWB帧可承载127字节的有效载荷。不过DW1000支持非标准操作模式,帧长可达到1023个字节的数据。该操作模式通过寄存器文件 :0x04 - 系统配置的PHR_MODE选择位启用。

DW1000初始化

  peripherals_init();
    printf("hello dwm1000!\r\n");
   // dwt_dumpregisters();
    /* Reset and initialise DW1000.
     * For initialisation, DW1000 clocks must be temporarily set to crystal speed. After initialisation SPI rate can be increased for optimum
     * performance. */
    reset_DW1000(); /* Target specific drive of RSTn line into DW1000 low for a period. */

    spi_set_rate_low();
    if(dwt_initialise(DWT_LOADUCODE) == -1)
    {
        printf("dwm1000 init fail!\r\n");
        OLED_ShowString(0,0,"INIT FAIL");
        while (1)
        {
            STM_EVAL_LEDOn(LED1);
            deca_sleep(100);
            STM_EVAL_LEDOff(LED1);
            deca_sleep(100);
        }
    }
    spi_set_rate_high();

    /* Configure DW1000. See NOTE 6 below. */
    dwt_configure(&config);
    dwt_setleds(1);
    /* Apply default antenna delay value. See NOTE 1 below. */
    dwt_setrxantennadelay(RX_ANT_DLY);
    dwt_settxantennadelay(TX_ANT_DLY);
    OLED_ShowString(0,0,"INIT PASS");

    printf("init pass!\r\n");

初始化成功,显示屏显示 INIT PASS,串口助手打印 init pass。则DW1000可以正常使用。初始化失败 ,显示屏显示 INIT FAIL,串口助手打印 init fail .则说明DW1000初始化失败,不能正常使用,需要重新初始化。

DW1000上电复位时是RSTn脚的高低电平是有特殊变化的,如果不按照该变化来,很大可能导致DW1000不能正常使用。


模块启动时,当设备开始供电的时候,RSTn 被内部的集成电路拉到低电平,RSTn 会一直保持低电平,直到模块上的晶振启动,并且当晶振的输出可以被所有模块上的设备使用时,RSTn 转为高电平。

当系统启动时,RSTn 可以被用来作为输出去的外部电路。模块上的一个外部的电路可以最少用10ns去重置DW1000模块。RSTn是一个异步输入。当引脚被转为高电平时,DW1000开始初始化。注意RSTn不可以被外部电路驱动。

void reset_DW1000(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    // Enable GPIO used for DW1000 reset
    GPIO_InitStructure.GPIO_Pin = DW1000_RSTn;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DW1000_RSTn_GPIO, &GPIO_InitStructure);
    //drive the RSTn pin low
    GPIO_WriteBit(GPIOB, DW1000_RSTn, 0);
    deca_sleep(100);
    GPIO_WriteBit(GPIOB, DW1000_RSTn, 1);

    deca_sleep(100);
    //put the pin back to tri-state ... as input
    GPIO_InitStructure.GPIO_Pin = DW1000_RSTn;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(DW1000_RSTn_GPIO, &GPIO_InitStructure);
}

/*******函数名:int dwt_initialise(uint16 config) ****************/
/*******函数功能:DW1000初始化************************************/
/****参数:DWT_LOADUCODE(0x01):从ROM加载LDE码,启用准确的RX时间戳*/
/**********DWT_LOADNONE(0x0):不从OTP内存加载任何值****************/
/***返回值:成功返回 DWT_SUCCESS(0),失败返回 DWT_ERROR(-1)********/
int dwt_initialise(uint16 config)
{
	uint8 plllockdetect = EC_CTRL_PLLLCK;
	uint16 otp_addr = 0;
	uint32 ldo_tune = 0;

    dw1000local.dblbuffon = 0; // Double buffer mode off by default
    dw1000local.prfIndex = 0; // 16MHz
    dw1000local.cdata.aatset = 0; // Auto ACK bit not set
    dw1000local.wait4resp = 0;
    dw1000local.sleep_mode = 0;

    dw1000local.dwt_txcallback = NULL ;
    dw1000local.dwt_rxcallback = NULL ;

    // Read and validate device ID return -1 if not recognised
    dw1000local.deviceID =  dwt_readdevid() ;
    if (DWT_DEVICE_ID != dw1000local.deviceID) // MP IC ONLY (i.e. DW1000) FOR THIS CODE
    {
    	GPIO_ResetBits(GPIOA,GPIO_Pin_1);
		GPIO_ResetBits(GPIOA,GPIO_Pin_2);
        return DWT_ERROR ;
    }

    _dwt_enableclocks(FORCE_SYS_XTI); // NOTE: set system clock to XTI - this is necessary to make
                                       // -sure the values read by _dwt_otpread are reliable

	// Configure the CPLL lock detect
	dwt_writetodevice(EXT_SYNC_ID, EC_CTRL_OFFSET, 1, &plllockdetect);

	// Read OTP revision number
	otp_addr = _dwt_otpread(XTRIM_ADDRESS) & 0xffff;        // Read 32 bit value, XTAL trim val is in low octet-0 (5 bits)
	dw1000local.otprev = (otp_addr >> 8) & 0xff;			// OTP revision is next byte

    // Load LDO tune from OTP and kick it if there is a value actually programmed.
    ldo_tune = _dwt_otpread(LDOTUNE_ADDRESS);
	if((ldo_tune & 0xFF) != 0)
	{
		uint8 ldok = OTP_SF_LDO_KICK;
		// Kick LDO tune
		dwt_writetodevice(OTP_IF_ID, OTP_SF, 1, &ldok); // Set load LDE kick bit
		dw1000local.sleep_mode |= AON_WCFG_ONW_LLDO; // LDO tune must be kicked at wake-up
	}

    // Load Part and Lot ID from OTP
    dw1000local.partID = _dwt_otpread(PARTID_ADDRESS);
    dw1000local.lotID = _dwt_otpread(LOTID_ADDRESS);

    // XTAL trim value is set in OTP for DW1000 module and EVK/TREK boards but that might not be the case in a custom design
    dw1000local.xtrim = otp_addr & 0x1F;
    if (!dw1000local.xtrim) // A value of 0 means that the crystal has not been trimmed
    {
        dw1000local.xtrim = FS_XTALT_MIDRANGE ; // Set to mid-range if no calibration value inside
    }
    // Configure XTAL trim
    dwt_xtaltrim(dw1000local.xtrim);

    // Load leading edge detect code
    if(config & DWT_LOADUCODE)
	{
        _dwt_loaducodefromrom();
        dw1000local.sleep_mode |= AON_WCFG_ONW_LLDE; // microcode must be loaded at wake-up
	}
	else // Should disable the LDERUN enable bit in 0x36, 0x4
	{
		uint16 rega = dwt_read16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1) ;
		rega &= 0xFDFF ; // Clear LDERUN bit
		dwt_write16bitoffsetreg(PMSC_ID, PMSC_CTRL1_OFFSET+1, rega) ;
	}

    _dwt_enableclocks(ENABLE_ALL_SEQ); // Enable clocks for sequencing

    // Read system register / store local copy
    dw1000local.sysCFGreg = dwt_read32bitreg(SYS_CFG_ID) ; // Read sysconfig register

    return DWT_SUCCESS ;

} // end dwt_initialise()
注意DW1000初始化这个函数需要在dwt_configure之前运行,而且SPI频率必须小于 3MHz ,所以该使用该函数之前需要把SPI 时钟降下来先,它也可以从OTP内存中读取并应用LDO调优和晶体修剪值。
dwt_readdevid() 函数读取的是 0x00-设备标准符。对于生产的DW1000,设备ID 被设置为 0xDECA0130 。
int dwt_configure(dwt_config_t *config)
{
    uint8 nsSfd_result  = 0;
    uint8 useDWnsSFD = 0;
    uint8 chan = config->chan ;
    uint32 regval ;
    uint16 reg16 = lde_replicaCoeff[config->rxCode];
    uint8 prfIndex = dw1000local.prfIndex = config->prf - DWT_PRF_16M;
    uint8 bw = ((chan == 4) || (chan == 7)) ? 1 : 0 ; // Select wide or narrow band

    dw1000local.chan = config->chan ;

#ifdef DWT_API_ERROR_CHECK
    if (config->dataRate > DWT_BR_6M8)
    {
    	return DWT_ERROR ;
    }// validate datarate parameter
    if ((config->prf > DWT_PRF_64M) || (config->prf < DWT_PRF_16M))
    {
    	return DWT_ERROR ;      // validate Pulse Repetition Frequency
    }
    if (config->rxPAC > DWT_PAC64)
    {
    	return DWT_ERROR ;      // validate PAC size
    }
    if ((chan < 1) || (chan > 7) || (6 == chan))
    {
    	return DWT_ERROR ; // validate channel number parameter
    }

    // validate TX and TX pre-amble codes selections
    if (config->prf == DWT_PRF_64M)
    {
        // at 64M PRF, codes should be 9 to 27 only
        // config->txCode
        // config->rxCode
    }
    else
    {
        // at 16M PRF, codes should be 0 to 8 only
    }
    switch (config->txPreambLength)
    {
    case DWT_PLEN_4096 :
    case DWT_PLEN_2048 :
    case DWT_PLEN_1536 :
    case DWT_PLEN_1024 :
    case DWT_PLEN_512  :
    case DWT_PLEN_256  :
    case DWT_PLEN_128  :
    case DWT_PLEN_64   : break ; // all okay
    default            : return DWT_ERROR ; // not a good preamble length parameter
    }

    if(config->phrMode > DWT_PHRMODE_EXT)
    {
        return DWT_ERROR ;
    }
#endif

    // For 110 kbps we need a special setup
    if(DWT_BR_110K == config->dataRate)
    {
        dw1000local.sysCFGreg |= SYS_CFG_RXM110K ;
        reg16 >>= 3; // lde_replicaCoeff must be divided by 8
    }
    else
    {
        dw1000local.sysCFGreg &= (~SYS_CFG_RXM110K) ;
    }

    dw1000local.longFrames = config->phrMode ;

    dw1000local.sysCFGreg |= (SYS_CFG_PHR_MODE_11 & (config->phrMode << 16)) ;

    dwt_write32bitreg(SYS_CFG_ID,dw1000local.sysCFGreg) ;
    // Set the lde_replicaCoeff
    dwt_write16bitoffsetreg(LDE_IF_ID, LDE_REPC_OFFSET, reg16) ;

    _dwt_configlde(prfIndex);

    // Configure PLL2/RF PLL block CFG (for a given channel)
    dwt_writetodevice(FS_CTRL_ID, FS_PLLCFG_OFFSET, 5, &pll2_config[chan_idx[chan]][0]);

    // Configure RF RX blocks (for specified channel/bandwidth)
    dwt_writetodevice(RF_CONF_ID, RF_RXCTRLH_OFFSET, 1, &rx_config[bw]);

    // Configure RF TX blocks (for specified channel and PRF)
    // Configure RF TX control
    dwt_write32bitoffsetreg(RF_CONF_ID, RF_TXCTRL_OFFSET, tx_config[chan_idx[chan]]);

    // Configure the baseband parameters (for specified PRF, bit rate, PAC, and SFD settings)
    // DTUNE0
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE0b_OFFSET, sftsh[config->dataRate][config->nsSFD]);

    // DTUNE1
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1a_OFFSET, dtune1[prfIndex]);

    if(config->dataRate == DWT_BR_110K)
    {
        dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x64);
    }
    else
    {
        if(config->txPreambLength == DWT_PLEN_64)
        {
            uint8 temp = 0x10;
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x10);
            dwt_writetodevice(DRX_CONF_ID, 0x26, 1, &temp);
        }
        else
        {
            uint8 temp = 0x28;
            dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_TUNE1b_OFFSET, 0x20);
            dwt_writetodevice(DRX_CONF_ID, 0x26, 1, &temp);
        }
    }

    // DTUNE2
    dwt_write32bitoffsetreg(DRX_CONF_ID, DRX_TUNE2_OFFSET, digital_bb_config[prfIndex][config->rxPAC]);

    // DTUNE3 (SFD timeout)
    // Don't allow 0 - SFD timeout will always be enabled
    if(config->sfdTO == 0)
    {
        config->sfdTO = DWT_SFDTOC_DEF;
    }
    dwt_write16bitoffsetreg(DRX_CONF_ID, DRX_SFDTOC_OFFSET, config->sfdTO);

    // Configure AGC parameters
    dwt_write32bitoffsetreg( AGC_CFG_STS_ID, 0xC, agc_config.lo32);
    dwt_write16bitoffsetreg( AGC_CFG_STS_ID, 0x4, agc_config.target[prfIndex]);

    // Set (non-standard) user SFD for improved performance,
    if(config->nsSFD)
    {
         // Write non standard (DW) SFD length
         dwt_writetodevice(USR_SFD_ID,0x00,1,&dwnsSFDlen[config->dataRate]);
         nsSfd_result = 3 ;
         useDWnsSFD = 1 ;
    }
    regval =  (CHAN_CTRL_TX_CHAN_MASK & (chan << CHAN_CTRL_TX_CHAN_SHIFT)) | // Transmit Channel
              (CHAN_CTRL_RX_CHAN_MASK & (chan << CHAN_CTRL_RX_CHAN_SHIFT)) | // Receive Channel
              (CHAN_CTRL_RXFPRF_MASK & (config->prf << CHAN_CTRL_RXFPRF_SHIFT)) | // RX PRF
              ((CHAN_CTRL_TNSSFD|CHAN_CTRL_RNSSFD) & (nsSfd_result << CHAN_CTRL_TNSSFD_SHIFT)) | // nsSFD enable RX&TX
              (CHAN_CTRL_DWSFD & (useDWnsSFD << CHAN_CTRL_DWSFD_SHIFT)) | // Use DW nsSFD
              (CHAN_CTRL_TX_PCOD_MASK & (config->txCode << CHAN_CTRL_TX_PCOD_SHIFT)) | // TX Preamble Code
              (CHAN_CTRL_RX_PCOD_MASK & (config->rxCode << CHAN_CTRL_RX_PCOD_SHIFT)) ; // RX Preamble Code

    dwt_write32bitreg(CHAN_CTRL_ID,regval) ;

    // Set up TX Preamble Size and TX PRF
    // Set up TX Ranging Bit and Data Rate
    dw1000local.txFCTRL = (config->txPreambLength | config->prf) << 16;
    dw1000local.txFCTRL |= (config->dataRate << TX_FCTRL_TXBR_SHFT) | TX_FCTRL_TR; // Always set ranging bit !!!
    dwt_write32bitoffsetreg(TX_FCTRL_ID,0,dw1000local.txFCTRL) ;

    return DWT_SUCCESS ;

} // end dwt_configure()
int dwt_configure(dwt_config_t *config)是 DW1000 配置函数。配置通道,PRF等。参数为结构体。
typedef struct
{
    uint8 chan ;           //!< channel number {1, 2, 3, 4, 5, 7 }
    uint8 prf ;            //!< Pulse Repetition Frequency {DWT_PRF_16M or DWT_PRF_64M}
    uint8 txPreambLength ; //!< DWT_PLEN_64..DWT_PLEN_4096
    uint8 rxPAC ;          //!< Acquisition Chunk Size (Relates to RX preamble length)
    uint8 txCode ;         //!< TX preamble code
    uint8 rxCode ;         //!< RX preamble code
    uint8 nsSFD ;          //!< Boolean should we use non-standard SFD for better performance
    uint8 dataRate ;       //!< Data Rate {DWT_BR_110K, DWT_BR_850K or DWT_BR_6M8}
    uint8 phrMode ;        //!< PHR mode {0x0 - standard DWT_PHRMODE_STD, 0x3 - extended frames DWT_PHRMODE_EXT}
    uint16 sfdTO ;         //!< SFD timeout value (in symbols)
}__attribute__ ((packed))  dwt_config_t ;

初始化完成以及配置完成,还需要进行天线延迟校准,这个以后的文章会细说,这里先跳过。然后可以进行无线通信。以下是设备先发送然后在接收自己发过去的被对面接收以后转发回来的代码,本人亲测传输正常。

       static uint8_t TX_Buff[13] ={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20}; //发送buff
       static uint8_t RX_Buff[100] ={0};   //接收buff
        
        dwt_setrxaftertxdelay(0);   //设置发送后打开接收的延迟时间
		dwt_setrxtimeout(37000);    //设置接收超时时间
		dwt_setrxmode(0,0,0);       //设置接收模式
		
		 
		 while(1)
	{
		   dwt_writetxdata(sizeof(TX_Buff), TX_Buff, 0);  
           dwt_writetxfctrl(sizeof(TX_Buff), 0);
           dwt_starttx(DWT_START_TX_IMMEDIATE|DWT_RESPONSE_EXPECTED);  //立即发送并等待回应
			
//			           
//	        dwt_readsystime((uint8_t *)&now_systime);  //获取系统当前时间点
//		   Txtime = (now_systime + (2000 * UUS_TO_DWT_TIME)) >> 8;   //计算发送时间点
//		   dwt_setdelayedtrxtime(Txtime);  //设置延迟发送时间点
			                
//          dwt_starttx(DWT_START_TX_DELAYED); //延迟发送
	           		
			      
			  while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS)) //等待发送完成
               { };
								
		     dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG | SYS_STATUS_TXFRS); //清除发送和接收
								
             while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
                  { };  //等待接收完成或者接收错误
										
			  if (status_reg & SYS_STATUS_RXFCG) //接收完成
			  {
					/* Clear good RX frame event and TX frame sent in the DW1000 status register. */
					dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG | SYS_STATUS_TXFRS);
					/* A frame has been received, read it into the local buffer. */
					len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;
					printf("len=%d\r\n",len);
				    if (len <= sizeof(RX_Buff))
					{
					  dwt_readrxdata(RX_Buff, len, 0);
					}
                    for(i=0;i<len;i++)
					{
				      printf("RX_buff[%d]=%x\r\n",i,RX_Buff[i]);
					}
			   }
		    else    //接收失败
				{
			    	/* Clear RX error events in the DW1000 status register. */
				   dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
				   printf("Receive_ERROR !\r\n");
			       for(i=0;i<20;i++)
				  {
				    printf("RX_buff[%d]=%x\r\n",i,RX_Buff[i]);
				    RX_Buff[i] =0;
				  }
				//GPIO_SetBits(GPIOA,GPIO_Pin_1);
		    	}
							 

}
void dwt_setrxaftertxdelay(uint32 rxDelayTime) 该函数是 设置发送后打开接收的延迟时间,时间单元是 UWB, 单位是微微秒(uus)。1 uus = 512 / 499.2MHz ≈ 1.0256 us。参数为0时,则发送完成后立即转为接收模式。在这里插入图片描述
void dwt_setrxtimeout(uint16 time) 该参数是设置接收超时时间,时间单位也是 1uus ≈ 1.0256 us。dwt这些一系列的DW1000的API 函数,时间单位都是 1uus 后面不在强调。当接收时间超过设定时间,则不在进行接收,建议使用时,确定超时时间设置够用,否则会导致数据接收错误 ,参数为0时则禁用接收超时,一直处于接收状态。
void dwt_setrxmode(int mode, uint8 rxON, uint8 rxOFF) 该函数是设置接收模式,0-正常模式,1-SNIFF 模式,SNIFF 模式是指在低功耗模式下进行收,即收一会,关一会,如此循环,后两个参数是设置SNIFF模式下,收和关的时间。可以理解为占空比。默认为正常模式,所以不需要配置。
int dwt_writetxdata(uint16 txFrameLength, uint8 *txFrameBytes, uint16 txBufferOffset) 该函数是将数据写入 DW1000发送缓冲区,第一个参数为 发送的数据帧总长度,包括数据后面的两个字节的校验值。所以参数长度为你发送数据的长度+2。第二个参数为发送数据buff的指针(即首地址),第三个参数是传数据的偏移量,为0则从首字节开始发。

特别注意,如果数据长度这个参数你没有留数据校验这两个字节的空间,则这两个校验字节会把你所传的数据的最后两个字节覆盖了,导致数据传输错误。

int dwt_writetxfctrl(uint16 txFrameLength, uint16 txBufferOffset) 该函数在传输帧之前配置发送帧控制寄存器,参数是长度和偏移量
int dwt_starttx(uint8 mode) 该函数在上两个函数配置之后,启动传输,并且配置传输模式,0-立即发送,无需回复,1-延时发送。无需回应,2-立即发送,转接收等回应(转发送的时间由dwt_setrxaftertxdelay设置),3-延时发送,转接收等待回应。
如果设置为延时发送,则每次延时发送之前,需要配置发送的时间,否则无法正常发送。
void dwt_readsystime(uint8 * timestamp) 该函数用来读取系统当前时间,参数为一个指向五字节缓冲区的指针,如果传数组地址,则下面需要转换两次后才能使用,所以可以传一个 64bit 的变量的地址。即dwt_readsystime((uint8_t *)&now_systime);
Txtime = (now_systime + (2000 * UUS_TO_DWT_TIME)) >> 8; 该功能是把读取的当前时间加上延时传输时间,则就是计算发送时间点。
void dwt_setdelayedtrxtime(uint32 starttime) 该函数是配置延时传输时间和延时接收时间,dwt_setdelayedtrxtime(Txtime);即配置好延时发送时间点,最后使用dwt_starttx(1不转接收或3转接收)即可。

以下是开始为接收,接收完成后,把接收到的数据发送回去,本人亲测,传输正常

static uint8_t Check_Buff[13] ={0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x20,0xfa,0x8d};  //后两个为校验
static uint8_t RX_Buff[100] ={0}; //接收buff
while(1)
{
	 dwt_setrxtimeout(0);  //设置接收超时
	 dwt_setrxmode(0,0,0);   //设置接收模式
     dwt_rxenable(0);     //开始接收
	 while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
           { };  //等待接收完成或错误
				
	 if (status_reg & SYS_STATUS_RXFCG)  //接收完成
       {
            /* Clear good RX frame event in the DW1000 status register. */
            dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG | SYS_STATUS_TXFRS);  //清除发送和接收

            /* A frame has been received, read it into the local buffer. */
            len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;   //读取接收长度包括校验
            if (len <= sizeof(RX_Buff))
              {
               dwt_readrxdata(RX_Buff, len, 0);   //将接收的数据放入RX_Buff中
               }
						
			if(memcmp(RX_Buff,Check_Buff,len)==0)  //判断接收的是否和发送过来的数据一模一样
			 {
			   for(i=0;i<len;i++)
				{
					printf("RX_buff[%d]=%x\r\n",i,RX_Buff[i]);
				}
				dwt_writetxdata(len, RX_Buff, 0); 
                dwt_writetxfctrl(len, 0);
      
                dwt_starttx(DWT_START_TX_IMMEDIATE); //传输接收数据给发送方
		     }				
	 }
	 else  //接收错误
     {
           /* Clear RX error events in the DW1000 status register. */
           dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR); //清除错误标准
	  	   printf("Receive_ERROR !\r\n");
		   for(i=0;i<20;i++)
		   {
			 printf("RX_buff[%d]=%x\r\n",i,RX_Buff[i]);
			 RX_Buff[i] =0;
			}
     }
}
		
int dwt_rxenable(int delayed) 该函数是延时一段时间打开接收,参数为延时时间,为0则立即打开接收。
uint32 dwt_read32bitoffsetreg(int regFileID,int regOffset) 该函数是用来读取32位的DW1000设备寄存器的值,第一个参数为要读取的寄存器的ID,第二个参数为开始读取的偏移量。返回值:成功返回读取的值,失败返回 DWT_ERROR(-1)。
int dwt_write32bitoffsetreg(int regFileID,int regOffset,uint32 regval) 该函数是用来写入32位的DW1000设备寄存器的值,第一个参数为要写入的寄存器的ID,第二个参数为开始写入的偏移量,第三个参数为写入寄存器的值。返回值:成功返回 DWT_SUCCESS(0),失败返回DWT_ERROR(-1)。

发送后转接收自己发送出去的数据,结果如下

  • 13
    点赞
  • 84
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
UWB DW1000 DTU(Ultra-Wideband DW1000 Data Terminal Unit)使用时间戳来进行测距过程。在这个过程中,设备A和设备B之间通过发送接收不同的消息来计算距离。 设备A首先发送一个消息P给设备B,并在发送时记录时间戳。设备B收到消息P后,发送一个应答消息R给设备A,并在发送时记录时间戳。设备A收到消息R后,发送一个确认消息F给设备B,并在发送时记录时间戳。设备B收到消息F后,记录接收时间戳。 设备A将所有的时间戳发送给设备B。设备B根据自己的时间戳和设备A发送的时间戳,使用DS-TWR算法计算出两者之间的距离。然后,设备B将计算出的距离打包发送给设备A。 需要注意的是,时间戳是五个字节的,但为了方便传输,只使用了四个字节,并且舍弃了最高字节。如果前面的时间戳比后面的时间戳大,说明已经过了一个周期,后者需要加上一个周期后再进行计算。由于一个测距过程只需要几毫秒完成,而跑满32位计数需要67.216毫秒,因此不用担心溢出的问题。 此外,在UWB DW1000中,所有的消息都以两个字节的校验和结束,这个校验和是由DW1000自动设置的。在消息中,字节10到13是用来传输消息的时间戳的。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [UWB-DW1000的TWR测距及代码(五)](https://blog.csdn.net/weixin_46107106/article/details/129204267)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [UWB DW1000 TWR测距定位功能实现](https://blog.csdn.net/CSDN_XIAXIA/article/details/128185923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值