这是官方标准程序,还可以使用。
单片机源程序如下:
- /*! ----------------------------------------------------------------------------
- * @file main.c
- * @brief Double-sided two-way ranging (DS TWR) initiator example code
- *
- * This is a simple code example which acts as the initiator in a DS TWR distance measurement exchange. This application sends a "poll"
- * frame (recording the TX time-stamp of the poll), and then waits for a "response" message expected from the "DS TWR responder" example
- * code (companion to this application). When the response is received its RX time-stamp is recorded and we send a "final" message to
- * complete the exchange. The final message contains all the time-stamps recorded by this application, including the calculated/predicted TX
- * time-stamp for the final message itself. The companion "DS TWR responder" example application works out the time-of-flight over-the-air
- * and, thus, the estimated distance between the two devices.
- *
- * @attention
- *
- * Copyright 2015 (c) Decawave Ltd, Dublin, Ireland.
- *
- * All rights reserved.
- *
- * @author Decawave
- */
- #include
- #include
- #include "deca_device_api.h"
- #include "deca_regs.h"
- #include "deca_sleep.h"
- #include "lcd.h"
- #include "port.h"
- /* Example application name and version to display on LCD screen. */
- #define APP_NAME "DS TWR INIT v1.1"
- /* Inter-ranging delay period, in milliseconds. */
- #define RNG_DELAY_MS 100
- /* Default communication configuration. We use here EVK1000's default mode (mode 3). */
- static dwt_config_t config = {
- 2, /* Channel number. */
- DWT_PRF_64M, /* Pulse repetition frequency. */
- DWT_PLEN_1024, /* Preamble length. */
- DWT_PAC32, /* Preamble acquisition chunk size. Used in RX only. */
- 9, /* TX preamble code. Used in TX only. */
- 9, /* RX preamble code. Used in RX only. */
- 1, /* Use non-standard SFD (Boolean) */
- DWT_BR_110K, /* Data rate. */
- DWT_PHRMODE_STD, /* PHY header mode. */
- (1025 + 64 - 32) /* SFD timeout (preamble length + 1 + SFD length - PAC size). Used in RX only. */
- };
- /* Default antenna delay values for 64 MHz PRF. See NOTE 1 below. */
- #define TX_ANT_DLY 0
- #define RX_ANT_DLY 32899
- static uint8 rx_poll_msg[] = {0x00, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0x21, 0, 0};
- static uint8 tx_resp_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'V', 'E', 'W', 'A', 0x10, 0x02, 0, 0, 0, 0};
- static uint8 rx_final_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- /* Frames used in the ranging process. See NOTE 2 below. */
- static uint8 tx_poll_msg[] = {0x00, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0x21, 0, 0};
- static uint8 rx_resp_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'V', 'E', 'W', 'A', 0x10, 0x02, 0, 0, 0, 0};
- static uint8 tx_final_msg[] = {0x41, 0x88, 0, 0xCA, 0xDE, 'W', 'A', 'V', 'E', 0x23, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
- /* Length of the common part of the message (up to and including the function code, see NOTE 2 below). */
- typedef signed long long int64;
- typedef unsigned long long uint64;
- static uint64 poll_rx_ts;
- static uint64 resp_tx_ts;
- static uint64 final_rx_ts;
- static double tof;
- static double distance,dist,dist2;
- #define ALL_MSG_COMMON_LEN 10
- /* Indexes to access some of the fields in the frames defined above. */
- #define ALL_MSG_SN_IDX 2
- #define FINAL_MSG_POLL_TX_TS_IDX 10
- #define FINAL_MSG_RESP_RX_TS_IDX 14
- #define FINAL_MSG_FINAL_TX_TS_IDX 18
- #define FINAL_MSG_TS_LEN 4
- /* Frame sequence number, incremented after each transmission. */
- static uint32 frame_seq_nb = 0;
- /* Buffer to store received response message.
- * Its size is adjusted to longest frame that this example code is supposed to handle. */
- #define RX_BUF_LEN 20
- #define RX_BUF_LEN2 24
- static uint8 rx_buffer[RX_BUF_LEN+4];
- /* Hold copy of status register state here for reference, so reader can examine it at a breakpoint. */
- static uint32 status_reg = 0;
- /* UWB microsecond (uus) to device time unit (dtu, around 15.65 ps) conversion factor.
- * 1 uus = 512 / 499.2 祍 and 1 祍 = 499.2 * 128 dtu. */
- #define UUS_TO_DWT_TIME 65536
- /* Delay between frames, in UWB microseconds. See NOTE 4 below. */
- /* This is the delay from the end of the frame transmission to the enable of the receiver, as programmed for the DW1000's wait for response feature. */
- #define POLL_TX_TO_RESP_RX_DLY_UUS 150
- /* This is the delay from Frame RX timestamp to TX reply timestamp used for calculating/setting the DW1000's delayed TX function. This includes the
- * frame length of approximately 2.66 ms with above configuration. */
- #define RESP_RX_TO_FINAL_TX_DLY_UUS 3100
- /* Receive response timeout. See NOTE 5 below. */
- #define RESP_RX_TIMEOUT_UUS 2700
- #define POLL_RX_TO_RESP_TX_DLY_UUS 2600
- /* This is the delay from the end of the frame transmission to the enable of the receiver, as programmed for the DW1000's wait for response feature. */
- #define RESP_TX_TO_FINAL_RX_DLY_UUS 500
- /* Receive final timeout. See NOTE 5 below. */
- #define FINAL_RX_TIMEOUT_UUS 4300
- #define SPEED_OF_LIGHT 299702547
- /* Time-stamps of frames transmission/reception, expressed in device time units.
- * As they are 40-bit wide, we need to define a 64-bit int type to handle them. */
- typedef unsigned long long uint64;
- static uint64 poll_tx_ts;
- static uint64 resp_rx_ts;
- static uint64 final_tx_ts;
- /* Declaration of static functions. */
- static uint64 get_tx_timestamp_u64(void);
- static uint64 get_rx_timestamp_u64(void);
- static void final_msg_set_ts(uint8 *ts_field, uint64 ts);
- /*! ------------------------------------------------------------------------------------------------------------------
- * @fn main()
- *
- * @brief Application entry point.
- *
- * @param none
- *
- * @return none
- */
- static void final_msg_get_ts(const uint8 *ts_field, uint32 *ts)
- {
- int i;
- *ts = 0;
- for (i = 0; i < FINAL_MSG_TS_LEN; i++)
- {
- *ts += ts_field << (i * 8);
- }
- }
- void GPIO_Toggle(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
- {
- GPIO_WriteBit(GPIOx, GPIO_Pin, (BitAction)!GPIO_ReadOutputDataBit(GPIOx, GPIO_Pin));
- }
- int fputc(int ch, FILE *f)
- {
- USART_SendData(USART1, (unsigned char) ch);// USART1 ???? USART2 ?
- while (!(USART1->SR & USART_FLAG_TXE));
- return (ch);
- }
- void USART_putc(char c)
- {
- //while(!(USART2->SR & 0x00000040));
- //USART_SendData(USART2,c);
- /* e.g. write a character to the USART */
- USART_SendData(USART1, c);
- /* Loop until the end of transmission */
- while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) ;
- }
- void USART_puts(uint8_t *s,uint8_t len)
- {
- int i;
- for(i=0; i
- {
- USART_putc(s);
- }
- }
- int ld[100];
- int LP(int tmp,uint8_t channel)
- {
- int data;
- data = 0.7*ld[channel]+0.3*tmp;
- ld[channel]=data;
- return data;
- }
- uint16_t Checksum_u16(uint8_t* pdata, uint32_t len)
- {
- uint16_t sum = 0;
- uint32_t i;
- for(i=0; i
- sum += pdata;
- sum = ~sum;
- return sum;
- }
- void LED_blink(void)
- {
- uint8_t ii;
- for (ii=0;ii<10;ii++)
- {
- GPIO_Toggle(GPIOA,LED_PIN);
- deca_sleep(100);
- }
- }
- extern volatile unsigned long time32_reset;
- extern uint8_t Work_Mode;
- uint32 frame_len;
- uint8_t send[9];
- char dist_str[16] = {0};
- int32_t dis;
- double dID;
- uint8_t TAG_ID,ANCHOR_ID, jumptime=0;
- uint32_t rec_dist,hex_dist;
- uint16_t check;
- int main(void)
- {
- /* Start with board specific hardware init. */
- peripherals_init();//初始化外设
- /* Display application name on LCD. */
- // lcd_display_str(APP_NAME);
- /* 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();//重启DW1000 /* Target specific drive of RSTn line into DW1000 low for a period. */
- spi_set_rate_low();//降低SPI频率
- dwt_initialise(DWT_LOADUCODE);//初始化DW1000
- spi_set_rate_high();//回复SPI频率
- /* Configure DW1000. See NOTE 6 below. */
- dwt_configure(&config);//配置DW1000
- /* Apply default antenna delay value. See NOTE 1 below. */
- dwt_setrxantennadelay(RX_ANT_DLY); //设置接收天线延迟
- dwt_settxantennadelay(TX_ANT_DLY); //设置发射天线延迟
- /* Set expected response's delay and timeout. See NOTE 4 and 5 below.
- * As this example only handles one incoming frame with always the same delay and timeout, those values can be set here once for all. */
- dwt_setrxaftertxdelay(POLL_TX_TO_RESP_RX_DLY_UUS);//设置发送后开启接收,并设定延迟时间
- dwt_setrxtimeout(RESP_RX_TIMEOUT_UUS); //设置接收超时时间
- send[0]=0x6D; //串口数据
- send[1]=0xD6; //串口数据
- tx_poll_msg[6] = ANCHOR_ID; //UWB POLL 包数据
- rx_resp_msg[6] = ANCHOR_ID; //UWB RESPONSE 包数据
- tx_final_msg[6] = ANCHOR_ID;//UWB Fianl 包数据
- rx_poll_msg[6] = ANCHOR_ID;
- tx_resp_msg[6] = ANCHOR_ID;
- rx_final_msg[6] = ANCHOR_ID;
- tx_poll_msg[5] = TAG_ID;//UWB POLL 包数据
- rx_resp_msg[5] = TAG_ID;//UWB RESPONSE 包数据
- tx_final_msg[5] = TAG_ID;//UWB Fianl 包数据
- /* Loop forever initiating ranging exchanges. */
- LED_blink();
- if(!Work_Mode) //选择发送模式(TAG标签)还是接收模式(ANCHOR基站)
- {
- while (1) //发送模式(TAG标签)
- {
- /* Write frame data to DW1000 and prepare transmission. See NOTE 7 below. */
- tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
- dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);//将Poll包数据传给DW1000,将在开启发送时传出去
- dwt_writetxfctrl(sizeof(tx_poll_msg), 0);//设置超宽带发送数据长度
- /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
- * set by dwt_setrxaftertxdelay() has elapsed. */
- dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);//开启发送,发送完成后等待一段时间开启接收,等待时间在dwt_setrxaftertxdelay中设置
- /* We assume that the transmission is achieved correctly, 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_ERR)))//不断查询芯片状态直到成功接收或者发生错误
- { };
- /* Increment frame sequence number after transmission of the poll message (modulo 256). */
- frame_seq_nb++;
- if (status_reg & SYS_STATUS_RXFCG)//如果成功接收
- {
- uint32 frame_len;
- /* 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. */
- frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK; //获得接收到的数据长度
- if (frame_len <= RX_BUF_LEN)
- {
- dwt_readrxdata(rx_buffer, frame_len, 0); //读取接收数据
- }
- /* Check that the frame is the expected response from the companion "DS TWR responder" example.
- * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
- rx_buffer[ALL_MSG_SN_IDX] = 0;
- if (memcmp(rx_buffer, rx_resp_msg, ALL_MSG_COMMON_LEN) == 0)//判断接收到的数据是否是response数据
- {
- uint32 final_tx_time;
- /* Retrieve poll transmission and response reception timestamp. */
- poll_tx_ts = get_tx_timestamp_u64(); //获得POLL发送时间T1
- resp_rx_ts = get_rx_timestamp_u64(); //获得RESPONSE接收时间T4
- /* Compute final message transmission time. See NOTE 9 below. */
- final_tx_time = (resp_rx_ts + (RESP_RX_TO_FINAL_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;//计算final包发送时间,T5=T4+Treply2
- dwt_setdelayedtrxtime(final_tx_time);//设置final包发送时间T5
- /* Final TX timestamp is the transmission time we programmed plus the TX antenna delay. */
- final_tx_ts = (((uint64)(final_tx_time & 0xFFFFFFFE)) << 8) + TX_ANT_DLY;//final包实际发送时间是计算时间加上发送天线delay
- /* Write all timestamps in the final message. See NOTE 10 below. */
- final_msg_set_ts(&tx_final_msg[FINAL_MSG_POLL_TX_TS_IDX], poll_tx_ts);//将T1,T4,T5写入发送数据
- final_msg_set_ts(&tx_final_msg[FINAL_MSG_RESP_RX_TS_IDX], resp_rx_ts);
- final_msg_set_ts(&tx_final_msg[FINAL_MSG_FINAL_TX_TS_IDX], final_tx_ts);
- /* Write and send final message. See NOTE 7 below. */
- tx_final_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
- dwt_writetxdata(sizeof(tx_final_msg), tx_final_msg, 0);//将发送数据写入DW1000
- dwt_writetxfctrl(sizeof(tx_final_msg), 0);//设定发送数据长度
- dwt_starttx(DWT_START_TX_DELAYED);//设定为延迟发送
- /* Poll DW1000 until TX frame sent event set. See NOTE 8 below. */
- while (!(dwt_read32bitreg(SYS_STATUS_ID) & SYS_STATUS_TXFRS))//不断查询芯片状态直到发送完成
- { };
- /* Clear TXFRS event. */
- dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);//清楚标志位
- /* Increment frame sequence number after transmission of the final message (modulo 256). */
- frame_seq_nb++;
- time32_reset = 0;
- GPIO_Toggle(GPIOA,LED_PIN);//LED闪烁
- jumptime = 0;
- }else{
- jumptime =5;//如果通讯失败,将间隔时间增加5ms,避开因为多标签同时发送引起的冲突。
- }
- }
- else
- {
- /* Clear RX error events in the DW1000 status register. */
- dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_ALL_RX_ERR);
- jumptime =5;
- }
- /* Execute a delay between ranging exchanges. */
- deca_sleep(RNG_DELAY_MS+jumptime);//休眠固定时间
- }
- }else{
- while (1)//接收模式(ANCHOR基站)
- {
- /* Clear reception timeout to start next ranging process. */
- dwt_setrxtimeout(0);//设定接收超时时间,0位没有超时时间
- /* Activate reception immediately. */
- dwt_rxenable(0);//打开接收
- /* Poll for reception of a frame or error/timeout. See NOTE 7 below. */
- 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);//清楚标志位
- /* A frame has been received, read it into the local buffer. */
- frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;//获得接收数据长度
- if (frame_len <= RX_BUFFER_LEN)
- {
- dwt_readrxdata(rx_buffer, frame_len, 0);//读取接收数据
- }
- /* Check that the frame is a poll sent by "DS TWR initiator" example.
- * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
- rx_buffer[ALL_MSG_SN_IDX] = 0;
- TAG_ID = rx_buffer[5];
- rx_poll_msg[5] = TAG_ID;//为多标签通讯服务,防止一次通讯中接收到不同ID标签的数据
- tx_resp_msg[5] = TAG_ID;
- rx_final_msg[5] = TAG_ID;
- if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0)//判断是否是poll包数据
- {
- uint32 resp_tx_time;
- /* Retrieve poll reception timestamp. */
- poll_rx_ts = get_rx_timestamp_u64();//获得Poll包接收时间T2
- /* Set send time for response. See NOTE 8 below. */
- resp_tx_time = (poll_rx_ts + (POLL_RX_TO_RESP_TX_DLY_UUS * UUS_TO_DWT_TIME)) >> 8;//计算Response发送时间T3。
- dwt_setdelayedtrxtime(resp_tx_time);//设置Response发送时间T3
- /* Set expected delay and timeout for final message reception. */
- dwt_setrxaftertxdelay(RESP_TX_TO_FINAL_RX_DLY_UUS);//设置发送完成后开启接收延迟时间
- dwt_setrxtimeout(FINAL_RX_TIMEOUT_UUS);//接收超时时间
- /* Write and send the response message. See NOTE 9 below.*/
- // memcpy(&tx_resp_msg[11],&dis,4);
- tx_resp_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
- dwt_writetxdata(sizeof(tx_resp_msg), tx_resp_msg, 0);//写入发送数据
- dwt_writetxfctrl(sizeof(tx_resp_msg), 0);//设定发送长度
- dwt_starttx(DWT_START_TX_DELAYED | DWT_RESPONSE_EXPECTED);//延迟发送,等待接收
- /* We assume that the transmission is achieved correctly, now poll for reception of expected "final" frame or error/timeout.
- * See NOTE 7 below. */
- while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))///不断查询芯片状态直到接收成功或者出现错误
- { };
- /* Increment frame sequence number after transmission of the response message (modulo 256). */
- frame_seq_nb++;
- 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. */
- frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFLEN_MASK;//数据长度
- if (frame_len <= RX_BUF_LEN2)
- {
- dwt_readrxdata(rx_buffer, frame_len, 0);//读取接收数据
- }
- /* Check that the frame is a final message sent by "DS TWR initiator" example.
- * As the sequence number field of the frame is not used in this example, it can be zeroed to ease the validation of the frame. */
- rx_buffer[ALL_MSG_SN_IDX] = 0;
- if (memcmp(rx_buffer, rx_final_msg, ALL_MSG_COMMON_LEN) == 0)//判断是否为Fianl包
- {
- uint32 poll_tx_ts, resp_rx_ts, final_tx_ts;
- uint32 poll_rx_ts_32, resp_tx_ts_32, final_rx_ts_32;
- double Ra, Rb, Da, Db;
- int64 tof_dtu;
- /* Retrieve response transmission and final reception timestamps. */
- resp_tx_ts = get_tx_timestamp_u64();//获得response发送时间T3
- final_rx_ts = get_rx_timestamp_u64();//获得final接收时间T6
- /* Get timestamps embedded in the final message. */
- final_msg_get_ts(&rx_buffer[FINAL_MSG_POLL_TX_TS_IDX], &poll_tx_ts);//从接收数据中读取T1,T4,T5
- final_msg_get_ts(&rx_buffer[FINAL_MSG_RESP_RX_TS_IDX], &resp_rx_ts);
- final_msg_get_ts(&rx_buffer[FINAL_MSG_FINAL_TX_TS_IDX], &final_tx_ts);
- /* Compute time of flight. 32-bit subtractions give correct answers even if clock has wrapped. See NOTE 10 below. */
- poll_rx_ts_32 = (uint32)poll_rx_ts;//使用32位数据计算
- resp_tx_ts_32 = (uint32)resp_tx_ts;
- final_rx_ts_32 = (uint32)final_rx_ts;
- Ra = (double)(resp_rx_ts - poll_tx_ts);//Tround1 = T4 - T1
- Rb = (double)(final_rx_ts_32 - resp_tx_ts_32);//Tround2 = T6 - T3
- Da = (double)(final_tx_ts - resp_rx_ts);//Treply2 = T5 - T4
- Db = (double)(resp_tx_ts_32 - poll_rx_ts_32);//Treply1 = T3 - T2
- tof_dtu = (int64)((Ra * Rb - Da * Db) / (Ra + Rb + Da + Db));//计算公式
- tof = tof_dtu * DWT_TIME_UNITS;
- distance = tof * SPEED_OF_LIGHT;//距离=光速*飞行时间
- dist2 = distance - dwt_getrangebias(config.chan,(float)distance, config.prf);//距离减去矫正系数
- dis = dist2*100;//dis 为单位为cm的距离
- dist = LP(dis,TAG_ID);//LP 为低通滤波器,让数据更稳定
- time32_reset = 0;
- GPIO_Toggle(GPIOA,LED_PIN);
- if (GPIO_ReadInputDataBit(GPIOA,SW2) != RESET) //通过拨码开关判断数据输出格式
- ……………………
- …………限于本文篇幅 余下代码请从电子发烧友下载附件…………
所有资料51hei提供下载:
1基站多标签V3.5.zip
|