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);  //立即发送并等待回应
			
//		     延时发送
	      //   TX_resp_times = get_rx_timestamp_u64();  //获取接收的时间戳					
			// TX_set_delay_times = (TX_resp_times + (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;  //计算延时发送时间点
     //  dwt_setdelayedtrxtime(TX_set_delay_times); //设置延时发送时间点						
		 //  TX_final_times = (((uint64_t)(TX_set_delay_times&0xfffffffe))<<8) + TX_ANT_DLY;  //获取发送端最后一次发送的时间戳
//	        dwt_readsystime((uint8_t *)&now_systime);  //获取系统当前时间点
//		   Txtime = (now_systime + (2000 * UUS_TO_DWT_TIME)) >> 8;   //计算发送时间点
//		   dwt_setdelayedtrxtime(Txtime);  //设置延迟发送时间点
		TX_final_times = (((uint64_t)Txtime + TX_ANT_DLY;  //获取发送端最后一次发送的时间戳                
//          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)。

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

UWB文章整理如下:

UWB-DW1000初始化、发送和接收详解(一):https://blog.csdn.net/weixin_46107106/article/details/128221089?spm=1001.2014.3001.5501
UWB-DW1000的天线延迟补偿和发射功率调节(二):https://blog.csdn.net/weixin_46107106/article/details/128715094?spm=1001.2014.3001.5502
DW1000的温度补偿及基站,标签天线延迟校准(三):https://blog.csdn.net/weixin_46107106/article/details/128806871?spm=1001.2014.3001.5502
UWB测距 方法,双向双边测距法(DS-TWR)(四):https://blog.csdn.net/weixin_46107106/article/details/129200945?spm=1001.2014.3001.5502
UWB-DW1000的TWR测距及代码(五):https://blog.csdn.net/weixin_46107106/article/details/129204267?spm=1001.2014.3001.5502
UWB定位 - 三球定位及算出的两个交点取舍(六):https://blog.csdn.net/weixin_46107106/article/details/130645080?spm=1001.2014.3001.5502
UWB定位的误差原因及摆放和布局(七):https://blog.csdn.net/weixin_46107106/article/details/130807768?spm=1001.2014.3001.5502
由把dwm1000模块从STM32单片机移植到N32单片机(国民技术)问题整理(八):https://blog.csdn.net/weixin_46107106/article/details/138178919?spm=1001.2014.3001.5502
UWB - DW1000的延时发送和延时接收(九):https://blog.csdn.net/weixin_46107106/article/details/144590332
TDOA-无线时钟同步及晶振偏差校准(十):https://blog.csdn.net/weixin_46107106/article/details/145174675

辣鸡网站怎么把资源都涨价到35了,改回来 谷歌机翻+个人修正的user manul,感兴趣可以看看 目录 Initializing the driver 6 2 DW1000的概述 13 2.1简介 13 2.2连接到DW1000 13 2.2.1 SPI接口 13 .2.1.1 SPI工作模式 13 2.2.2中断 16 2.2.3通用I / O 17 2.2.4 SYNC引脚 17 2.3 DW1000操作状态 17 2.3.1状态图 17 2.3.2主要运行状态概述 17 2.4上电复位(POR) 19 2.5上电时的默认配置 21 2.5.3默认发射机配置T 22 2.5.4默认接收器配置 22 2.5.5应该修改的默认配置 23 3消息传输 26 3.1基本传输 26 3.2传输时间戳 27 3.3延迟传输 28 3.4扩展长度数据帧 29 3.5高速传输 30 3.5.1 TX缓冲区偏移索引 30 3.5.2发送接收TX缓冲区时写入 31 4讯息接收 33 4.1基本接收 33 4.1.1前导码检测 33 4.1.2前导码累积 34 4.1.3 SFD检测 35 4.1.4 PHR解调 35 4.1.5数据解调 35 4.1.6 RX消息时间戳 36 4.2延迟接收 36 4.3双接收缓冲器 37 4.3.1启用双缓冲操作 37 4.3.2控制正在访问哪个缓冲区 37 4.3.3双缓冲的操作 38 4.3.4使用双缓冲时的TRXOFF 40 4.3.5超限 40 4.4低功耗侦听 41 4.4.1配置低功率监听 42 4.5低功耗SNIFF模式 42 4.5低功耗SNIFF模式 43 4.5.1 SNIFF模式 43 4.5.2低占空比SNIFF模式 44 4.7.1估算第条路径的信号功率 45 4.7.2估算接收信号功率 46 5 Media Access Control (MAC) hardware features 47 5.1循环冗余校验 47 5.2帧过滤 47 5.2.1帧过滤规则 48 5.2.2帧过滤注意事项 49 5.3自动确认 49 5.3.2自动接收器重新启用 51 5.3.3自动ACK周转时间 51 5.3.4帧挂起位Frame Pending bit 51 5.3.5主机通知 51 5.4发送并自动等待响应 52 6 DW1000的其他功能 52 6.1外部同步 52 6.1.1次性时基复位(OSTR)模式 52 6.1.2单发发送同步(OSTS)模式 53 6.1.3接收同步(OSRS)模式 53 6.2外部功率放大 55 6.3使用片上OTP存储器 55 6.3.1 OTP存储器映射 55 6.3.2将值编程到OTP存储器中 57 6.3.3从OTP内存中读取个值 58 6.4测量IC温度电压 58 10附录1:IEEE 802.15.4 UWB物理层 59 10.1框架结构概述 59 10.2数据调制方案 59 10.3同步头调制方案 60 10.4 PHY头 61 10.5 UWB信道前导码 62 10.6标准的其他细节 62 11附录2:IEEE 802.15.4 MAC层 62 11.1般MAC消息格式 63 11.2 MAC报头中的帧控制字段 63 11.2.1帧类型字段Frame type field 64 11.2.2启用安全性字段Security enabled Field 64 11.2.3帧未决字段Frame pending field 64 11.2.4确认请求字段Acknowledgement request field 65 11.2.5 PAN ID压缩字段PAN ID compression field 65 11.2.6目标寻址模式字段Destination addressing mode field 65 11.2.7帧版本字段Frame version field 66 11.2.8源寻址模式字段Source addressing mode field 66 11.3序号字段The Sequence Number field 66 11.4 DW1000中的MAC级处理 66
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

吾与春风皆过客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值