DWM1000 測距原理簡單分析 之 SS-TWR代碼分析2 -- [藍點無限]


藍點DWM1000 模塊已經打樣測試完畢,有興趣的可以申請購買了,更多信息參見 藍點論壇 

 

正文:

首先將SS 原理介紹中的圖片拿過來,將圖片印在腦海里。

對於DeviceA 和 DeviceB來說,初始化代碼都一樣,而后面部分是一個while循環,一直執行測距任務。

DeviceA(ex_06a_ss_twr_init ) 部分代碼

 1 tx_poll_msg[ALL_MSG_SN_IDX] = frame_seq_nb;
 2 dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);
 3 dwt_writetxdata(sizeof(tx_poll_msg), tx_poll_msg, 0);
 4 dwt_writetxfctrl(sizeof(tx_poll_msg), 0);
 5 
 6 /* Start transmission, indicating that a response is expected so that reception is enabled automatically after the frame is sent and the delay
 7          * set by dwt_setrxaftertxdelay() has elapsed. */
 8 dwt_starttx(DWT_START_TX_IMMEDIATE | DWT_RESPONSE_EXPECTED);
 9 
10 /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
11 while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
12         { };

 

上述過程主要完成任務:發送數據以及打開接收器等待數據

DWM1000 發送數據通常只需要調用三個函數即可: dwt_writetxdata  dwt_writetxfctrl  dwt_starttx

dwt_writetxdata 指定發送什么數據,上述代碼發送的數據是  tx_poll_msg,另外兩個參數分別是發送數據長度,以及要將數據放到DWM1000 發送緩存的offset(默認設置為0即可)

dwt_writetxfctrl   發送控制參數設定,這個基本也是不需要修改,第一個參數是發送數據長度,第二個參數告訴DWM1000 從發送緩存那個offset 開始發送(也就是說,並不是放到發送緩存中的數據就會被發送出去)

dwt_starttx:啟動發送,一共參數,可以按位控制,上述代碼中第一個控制是否里面發送或者是延時發送,第二個控制是否在一定時間后打開接收器。

注意:在調試過程中,如果需要發送數據后再接收一個數據,通常需要使用DWT_RESPONSE_EXPECTED,而且要考慮POLL_TX_TO_RESP_RX_DLY_UUS,這個參數在dwt_setrxaftertxdelay中設定。

 

DWM1000 有很多事件,也有對應的標志flag,例如發送數據,對應的發送成功標志,接收數據,有對應的接收成功標志,當然也有fail的標志,具體可以參見《dw1000_user_manual.pdf》的 Register file: 0x0F – System Event Status Register。

事件flag 有很多,我們在基礎實驗中基本只會遇到上述代碼中的 SYS_STATUS_TXFRS /SYS_STATUS_RXFCG/SYS_STATUS_ALL_RX_ERR,分表表示發送成功標志、接收成功標志以及接收錯誤,其中接收錯誤標志其實代碼中是很多flag 的或,例如數據幀錯誤,timeout 等。所有flag 都是寫1 清0.

完成上述代碼分析,再看剩余兩行代碼

1 dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_TXFRS);        
2 /* We assume that the transmission is achieved correctly, poll for reception of a frame or error/timeout. See NOTE 8 below. */
3 while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
4         { };

第一行是在發送之前,將可能的發送完成標志位清除,后面的while 循環是等待flag 置起來,也就是在等待DeviceB發送來的無線數據(並不是無限期等待,等待時間timeout 上面的代碼直接設置過了)。

上述代碼分析完成了DeviceA 在A點的任務。

DeviceB 代碼分析

DeviceB的代碼在ex_06b_ss_twr_resp目錄,同樣有dwm1000初始化,這個所有dwm1000 基礎工程都一樣,剩余部分也是一個while1 大循環。現在拿出部分代碼,分析DeviceB在B點的動作。

 1         /* Activate reception immediately. */
 2         dwt_rxenable(0);
 3 
 4         /* Poll for reception of a frame or error/timeout. See NOTE 6 below. */
 5         while (!((status_reg = dwt_read32bitreg(SYS_STATUS_ID)) & (SYS_STATUS_RXFCG | SYS_STATUS_ALL_RX_ERR)))
 6         { };
 7 
 8         if (status_reg & SYS_STATUS_RXFCG)
 9         {
10             uint32 frame_len;
11 
12             /* Clear good RX frame event in the DW1000 status register. */
13             dwt_write32bitreg(SYS_STATUS_ID, SYS_STATUS_RXFCG);
14 
15             /* A frame has been received, read it into the local buffer. */
16             frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
17             if (frame_len <= RX_BUFFER_LEN)
18             {
19                 dwt_readrxdata(rx_buffer, frame_len, 0);
20             }
21 
22             /* Check that the frame is a poll sent by "SS TWR initiator" example.
23              * As the sequence number field of the frame is not relevant, it is cleared to simplify the validation of the frame. */
24             rx_buffer[ALL_MSG_SN_IDX] = 0;
25             if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0)
26             {
27                 uint32 resp_tx_time;
28 
29                 /* Retrieve poll reception timestamp. */
30                 poll_rx_ts = get_rx_timestamp_u64();

上面代碼摘自ex_06b_ss_twr_resp while 大循環部分代碼

首先是 dwt_rxenable(0), 這個作用是強制打開接收器,參數為timeout,設置為0,意思就是一直打開。 后面的while在Device 中已經看到,是等待接收數據,如果接收成功,SYS_STATUS_RXFCG 被置為1。 可以看到除了判斷SYS_STATUS_RXFCG 還判斷了SYS_STATUS_ALL_RX_ERR,這個是所有RX 可能出現ERROR 合集事件,我們期望的結果是SYS_STATUS_RXFCG ,弱實際中由於干擾接收到錯誤的信息SYS_STATUS_ALL_RX_ERR 會被置起來,也會退出while 等待,會接着執行后面的else,else的任務是清除SYS_STATUS_ALL_RX_ERR ,然后重新回到大while 循環等待接收數據。

假如接收到數據,就會執行if 判斷力的代碼,首先清除接收標志SYS_STATUS_RXFCG,然后通過兩個API讀取數據長度以及數據

1 frame_len = dwt_read32bitreg(RX_FINFO_ID) & RX_FINFO_RXFL_MASK_1023;
2  if (frame_len <= RX_BUFFER_LEN)
3  {
4      dwt_readrxdata(rx_buffer, frame_len, 0);
5 }

后面的判斷是判斷數據類型

1  if (memcmp(rx_buffer, rx_poll_msg, ALL_MSG_COMMON_LEN) == 0)

在DWM1000 基礎例子中,有很多種不同的數據,數據通常包括三部分(A+B+C),A是數據頭,B是實際用戶希望傳輸的數據,C是兩byte 校驗碼,其中A部分是Device之前相互約定,C是DWM1000 自動生成的,B根據實際應用更改。

在SS-TWR中,有兩種信息,分別是 rx_poll_msg 和 tx_resp_msg ,poll_msg是DeviceA 發送給DeviceB的,而 resp_meg 是DeviceB發送給DeviceA 的,而在DS-TWR中會有更多信息,這個完全可以自由擴展。

而代碼中通過if 判斷,判斷信息是DeviceA發送給DeviceB的poll_msg后,緊接着就讀取了自己接收數據的時刻

1  poll_rx_ts = get_rx_timestamp_u64();

注意:雖然 get_rx_timestamp_u64 不是標准dwt API,但是這個函數里面是直接調用API實現的,保持下來以后可以直接當API使用。

以上代碼就是DeviceB 在B 時刻接收數據的代碼。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM