藍點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 時刻接收數據的代碼。