本文將基於Nordic nRF5
SDK開發我們的第一個BLE應用程序——Blinky(類似跑馬燈小程序),哪怕你之前沒有任何BLE開發經驗,也不用擔心,只要跟著文中所述步驟,你就可以一步步搭建自己的第一個BLE應用程序。通過這個Blinky程序的搭建,你將體會到BLE的一些基本概念,對BLE將會有一個非常直觀的認識,為後續自己的BLE應用程序開發打下一個堅實的基礎。
如果你已經有一些BLE應用開發經驗,只是對Nordic產品開發不熟,那麼建議你可以直接去閱讀下一篇文章:手把手教你開發BLE數據透傳應用程序
下文所述的代碼工程我已經將其上傳到百度雲盤中,有需要的同學可以到如下鏈接下載:
2) 開發環境搭建。簡述如下(詳細說明請參考「Nordic nRF51/nRF52開發環境搭建」):
1) 確認自己的芯片型號或者開發板。如果採用Nordic官方開發板的話,芯片型號和開發板編號對應關係如下:
2) 將開發板與PC機通過USB線相連,同時打開開發板電源(將左下角的撥位開關打到「ON」位置),打開桌面版nRF Connect,選擇啟動「Programmer」應用,由於驅動之前已經安裝好了,設備可以立即識別成功。執行「Erase all」操作,以擦除芯片原始內容。
3) 打開SDK中的Blinky程序。對於blinky程序,如果是52832開發板,請打開:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\ble_app_blinky\pca10040\s132\arm5_no_packs;如果是51822開發板,請打開:nRF5_SDK_12.3.0_d7731ad\examples\ble_peripheral\experimental_ble_app_blinky\pca10028\s130\arm5_no_packs
後續將以52832開發板為例來闡述,51822與之類似就不再闡述了。
註:Nordic SDK例程目錄結構為:SDK版本/ examples /協議角色/例子名稱/開發板型號/協議棧型號/工具鏈類型/具體工程,比如下面例子:
Nordic每一個例子都支持5種工具鏈:Keil5/Keil4/IAR/GCC/SES,如下所示:
4) 編譯上面的blinky程序。如果你已經按照之前的說明配置好了開發環境,那麼這裡編譯是不會報任何錯的。(如果你遇到了編譯錯誤,請重新按照前面說明去搭建你的開發環境,不要懷疑SDK例子代碼有問題哦)
5) 程序下載。程序下載包括2步:先下載softdevice,再下載應用。Softdevice是Nordic藍牙協議棧的名稱,整個開發過程中只需下載一次。應用就是我們這裡的blinky程序。
7) 連接設備。點擊「CONNECT」,手機將與設備建立連接,並開始服務發現過程,連接成功後,LED1熄滅,LED2點亮,最後將得到如下界面。
由上圖可見,Blinky程序包含三個service:Generic Access(GAP),Generic Attribute(GATT),以及Nordic LED Button Service,GAP和GATT都是標準的藍牙service,Nordic LED Button Service是Blinky程序自定義的service,它又具體包括兩個characteristic:Button和LED。
8) 測試Blinky程序。點擊右上角的「Enable CCCDs」以使能notification,如下:
按下開發板上的Button1按鍵,你會發現nRF connect中的Button characteristic Value會實時顯示按鍵狀態:pressed或者released。
點擊nRF connect中的LED characteristic右邊的向上箭頭,選擇「ON」並「SEND」,你會發現開發板的LED3將點亮;選擇「OFF」並「SEND」,LED3又將熄滅。
我們只需將這裡的Nordic_Blinky換成My_Blinky,即
就可以實現我們的目標了。重新編譯下載blinky程序,在nRF connect中,你將看到:
你再全文搜索一下「DEVICE_NAME」,你會發現廣播名字其實是通過如下API來完成修改的:
註:Keil的搜索功能非常好用,很多問題都可以通過它來解決
因此為了將廣播間隔改為200ms,只需將APP_ADV_INTERVAL改成200/0.625 = 320,即
重新編譯下載blinky程序,在nRF connect中,你將發現廣播間隔已改為200ms了:
可以看出,我們是通過ble_lbs_on_button_change來更新Button characteristic的值的,ble_lbs_on_button_change具體函數實現如下所示:
我們可以仿照Button1的做法,來添加Button2的代碼。首先初始化app_button模塊,讓button2按下事件可以被button_event_handler捕獲,如下:
然後在button_event_handler調用ble_button2_send(uint16_t conn_handle,
ble_lbs_t * p_lbs, uint8_t val),以更新Button characteristic的值,代碼如下所示:
ble_button2_send(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t val)實現代碼如下所示:
重新編譯下載blinky程序,連接設備,使能cccd,按下Button2,你會看到Button characteristic的值變為5:
這個實現起來比較簡單,我們只需在led_write_handler中添加bsp_board_led_invert(BSP_BOARD_LED_3),整體代碼如下所示:
重新編譯下載blinky程序,連接設備,你會發現第一次發送「ON」,LED4點亮,第二次發送「ON」,LED4又將熄滅。
通過全文搜索「led_write_handler」,你會發現這個函數是被ble_lbs.c中的on_write調用,而on_write又被ble_lbs_on_ble_evt調用,而ble_lbs_on_ble_evt就是我們的BLE事件回調函數,每當softdevice收到LED characteristic的寫操作時,都會調用它,這就是通過nRF connect操作設備的過程和原理。
上述代碼工程我已經將其上傳到百度雲盤中,有需要的同學可以到如下鏈接下載:
下載「tutorial_ble_app_blinky_SDK15_3_0.rar」,然後解壓縮到SDK15.3.0如下目錄下:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\
即可成功編譯。
nRF Blinky操作界面如下所示:
如果你已經有一些BLE應用開發經驗,只是對Nordic產品開發不熟,那麼建議你可以直接去閱讀下一篇文章:手把手教你開發BLE數據透傳應用程序
下文所述的代碼工程我已經將其上傳到百度雲盤中,有需要的同學可以到如下鏈接下載:
1. 開發準備
1) nRF52或者nRF51開發板1塊。請參考「Nordic nRF51/nRF52開發流程說明」,購買相應開發板(DK)。2) 開發環境搭建。簡述如下(詳細說明請參考「Nordic nRF51/nRF52開發環境搭建」):
- 安裝Keil5 MDK
- 安裝SDK。SDK下載鏈接:https://www.nordicsemi.com/Software-and-Tools/Software/nRF5-SDK/Download#infotabs。如果你開發的是nRF52系列,請選擇最新版SDK(當前是SDK15.3.0);如果你開發的是nRF51系列,請下載nRF5 SDK12.3.0(nRF51最高SDK版本只能到12.3.0,後續SDK就不再支持nRF51了)
- 安裝ARM CMSIS4.5.0,下載鏈接:https://github.com/ARM-software/CMSIS/releases/download/v4.5.0/ARM.CMSIS.4.5.0.pack。
- 安裝Keil5 Device Family Pack,下載鏈接:https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-MDK/Download#infotabs,請選擇「Pack,3-clause BSD license」
- 安裝nRF5 Command Line Tools,下載鏈接(Windows版):https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF5-Command-Line-Tools/Download#infotabs。
- 安裝安卓版或者iOS版nRF connect。iOS版nRF connect請到蘋果app store下載,搜索「nRF」即可以找到。安卓版nRF connect可以到Nordic Github官網上下載,下載鏈接為:https://github.com/NordicSemiconductor/Android-nRF-Connect/releases
- 安裝PC版nRF connect或者nRFgo studio。PC版nRF connect下載鏈接(Windows版):https://www.nordicsemi.com/Software-and-Tools/Development-Tools/nRF-Connect-for-desktop/Download#infotabs。
2. 運行Blinky程序
請按照如下步驟運行SDK自帶的Blinky程序1) 確認自己的芯片型號或者開發板。如果採用Nordic官方開發板的話,芯片型號和開發板編號對應關係如下:
- nRF52832和nRF52810對應開發板編號為PCA10040。雖然52832和52810共用同一塊開發板,但是他們在SDK中的項目編號是不一樣的,52832對應PCA10040目錄,52810對應PCA10040e目錄,由於52810和52832 PIN to PIN兼容,軟件也是完全兼容的,因此SDK很多項目只有PCA10040的目錄,而沒有PCA10040e目錄,此時需要你自己來建立PCA10040e對應的目錄和工程,具體說明可參考:https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Fnrf52810_user_guide.html。
- nRF52840和nRF52811對應開發板編號為PCA10056。雖然52840和52811共用同一塊開發板,但是他們在SDK中的項目編號是不一樣的,52840對應PCA10056目錄,52811對應PCA10056e目錄,由於52811和52840 PIN to PIN兼容,軟件也是完全兼容的,因此SDK很多項目只有PCA10056的目錄,而沒有PCA10056e目錄,此時需要你自己來建立PCA10056e對應的目錄和工程,具體說明可參考:https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.3.0%2Fnrf52811_user_guide.html&cp=5_1_5_1。
- nRF52840 dongle編號為PCA10059
- nRF51系列對應開發板編號為PCA10028
2) 將開發板與PC機通過USB線相連,同時打開開發板電源(將左下角的撥位開關打到「ON」位置),打開桌面版nRF Connect,選擇啟動「Programmer」應用,由於驅動之前已經安裝好了,設備可以立即識別成功。執行「Erase all」操作,以擦除芯片原始內容。
3) 打開SDK中的Blinky程序。對於blinky程序,如果是52832開發板,請打開:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\ble_app_blinky\pca10040\s132\arm5_no_packs;如果是51822開發板,請打開:nRF5_SDK_12.3.0_d7731ad\examples\ble_peripheral\experimental_ble_app_blinky\pca10028\s130\arm5_no_packs
後續將以52832開發板為例來闡述,51822與之類似就不再闡述了。
註:Nordic SDK例程目錄結構為:SDK版本/ examples /協議角色/例子名稱/開發板型號/協議棧型號/工具鏈類型/具體工程,比如下面例子:
Nordic每一個例子都支持5種工具鏈:Keil5/Keil4/IAR/GCC/SES,如下所示:
4) 編譯上面的blinky程序。如果你已經按照之前的說明配置好了開發環境,那麼這裡編譯是不會報任何錯的。(如果你遇到了編譯錯誤,請重新按照前面說明去搭建你的開發環境,不要懷疑SDK例子代碼有問題哦)
5) 程序下載。程序下載包括2步:先下載softdevice,再下載應用。Softdevice是Nordic藍牙協議棧的名稱,整個開發過程中只需下載一次。應用就是我們這裡的blinky程序。
- 藍牙協議棧下載(整個開發週期只下載一次)。在Keil 『select target'下拉列表中,默認選擇的是Keil工程對應的Target,即『nrf52832_xxaa'。但我們還可以選擇另一個target 『flash_s132_nrf52_6.1.1_softdevice',即softdevice對應的target,然後點擊「下載download」(不需要編譯哦!),此時會把softdevice下載到開發板中。
- 應用下載。重新選擇Target:『nrf52832_xxaa',點擊「下載Download」,此時會把Blinky程序下載到開發板中。此時開發板的LED1常亮,表示程序運行正常。
7) 連接設備。點擊「CONNECT」,手機將與設備建立連接,並開始服務發現過程,連接成功後,LED1熄滅,LED2點亮,最後將得到如下界面。
由上圖可見,Blinky程序包含三個service:Generic Access(GAP),Generic Attribute(GATT),以及Nordic LED Button Service,GAP和GATT都是標準的藍牙service,Nordic LED Button Service是Blinky程序自定義的service,它又具體包括兩個characteristic:Button和LED。
8) 測試Blinky程序。點擊右上角的「Enable CCCDs」以使能notification,如下:
按下開發板上的Button1按鍵,你會發現nRF connect中的Button characteristic Value會實時顯示按鍵狀態:pressed或者released。
點擊nRF connect中的LED characteristic右邊的向上箭頭,選擇「ON」並「SEND」,你會發現開發板的LED3將點亮;選擇「OFF」並「SEND」,LED3又將熄滅。
3. 修改Blinky程序
3.1 修改廣播名稱
如前所述,Blinky程序默認的廣播名字是:Nordic_Blinky,我們現在將其修改為「My_Blinky」,怎麼做呢?我們在Keil中全文搜索「Nordic_Blinky」,發現有如下宏定義:#define DEVICE_NAME "Nordic_Blinky"
#define DEVICE_NAME "My_Blinky"
你再全文搜索一下「DEVICE_NAME」,你會發現廣播名字其實是通過如下API來完成修改的:
err_code = sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *)DEVICE_NAME, strlen(DEVICE_NAME));
3.2 修改廣播間隔
如nRF connect界面所示,blinky程序的廣播間隔大概為40ms左右,現在為了節省功耗,我們將其改為200ms,通過搜索,我們可以看到如下宏定義:#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms; this value corresponds to 40 ms). */
#define APP_ADV_INTERVAL 320
3.3 修改Button characteristic行為 (設備發數據給手機)
現在的Blinky程序,只有按下開發板的Button1時,nRF connect的Button characteristic 值才會更新。我們現在新增一個功能:當按下開發板的Button 2時,讓Button characteristic value更新為5(註: nRF connect把1當成按鍵按下,把0當成按鍵釋放,為了更直觀,我們沒有選擇0或者1,而是隨便選擇一個值:5)。我們先找到Button1按下的回調函數,如下所示:case LEDBUTTON_BUTTON: NRF_LOG_INFO("Send button state change."); err_code = ble_lbs_on_button_change(m_conn_handle, &m_lbs, button_action); if (err_code != NRF_SUCCESS && err_code != BLE_ERROR_INVALID_CONN_HANDLE && err_code != NRF_ERROR_INVALID_STATE && err_code != BLE_ERROR_GATTS_SYS_ATTR_MISSING) { APP_ERROR_CHECK(err_code); } break;
uint32_t ble_lbs_on_button_change(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t button_state) { ble_gatts_hvx_params_t params; uint16_t len = sizeof(button_state); memset(¶ms, 0, sizeof(params)); params.type = BLE_GATT_HVX_NOTIFICATION; params.handle = p_lbs->button_char_handles.value_handle; params.p_data = &button_state; params.p_len = &len; return sd_ble_gatts_hvx(conn_handle, ¶ms); }
static app_button_cfg_t buttons[] = { {LEDBUTTON_BUTTON, false, BUTTON_PULL, button_event_handler}, {BSP_BUTTON_1, false, BUTTON_PULL, button_event_handler} };
case BSP_BUTTON_1: NRF_LOG_INFO("Button2 pressed."); ble_button2_send(m_conn_handle, &m_lbs, 5); break;
uint32_t ble_button2_send(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t val) { ble_gatts_hvx_params_t params; uint16_t len = sizeof(val); memset(¶ms, 0, sizeof(params)); params.type = BLE_GATT_HVX_NOTIFICATION; params.handle = p_lbs->button_char_handles.value_handle; //Button characteristic value handle params.p_data = &val; params.p_len = &len; return sd_ble_gatts_hvx(conn_handle, ¶ms); }
3.4 修改LED characteristic行為(手機發數據給設備)
由於nRF connect把LED characteristic的值寫死了,只能發送「ON」或者「OFF」,前面也測試過,發送「ON」之後,LED3將點亮,其實這裡的「ON」,就是數值1。我們現在增加一個新的功能:在收到「ON」命令後,把LED4 toggle一下。這個實現起來比較簡單,我們只需在led_write_handler中添加bsp_board_led_invert(BSP_BOARD_LED_3),整體代碼如下所示:
static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t led_state) { if (led_state) { bsp_board_led_on(LEDBUTTON_LED); NRF_LOG_INFO("Received LED ON!"); bsp_board_led_invert(BSP_BOARD_LED_3); } else { bsp_board_led_off(LEDBUTTON_LED); NRF_LOG_INFO("Received LED OFF!"); } }
通過全文搜索「led_write_handler」,你會發現這個函數是被ble_lbs.c中的on_write調用,而on_write又被ble_lbs_on_ble_evt調用,而ble_lbs_on_ble_evt就是我們的BLE事件回調函數,每當softdevice收到LED characteristic的寫操作時,都會調用它,這就是通過nRF connect操作設備的過程和原理。
上述代碼工程我已經將其上傳到百度雲盤中,有需要的同學可以到如下鏈接下載:
下載「tutorial_ble_app_blinky_SDK15_3_0.rar」,然後解壓縮到SDK15.3.0如下目錄下:nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\
即可成功編譯。
4. 開發手機端Blinky程序
Nordic同時提供手機端的Blinky程序,該程序源代碼完全向用戶開放,以幫助用戶快速開發自己的第一個Android或者iOS BLE應用程序。用戶可以先到app store下載iOS版nRF blinky,或者到Github下載Android版nRF blinky(下載鏈接:https://github.com/NordicSemiconductor/Android-nRF-Blinky/releases)。手機版的nRF Blinky跟前面介紹的Blinky固件是配合工作的,通過手機版nRF Blinky可以對前面的blinky固件進行操作。nRF Blinky app圖標如下所示:nRF Blinky操作界面如下所示:
- nRF Blinky Android版源代碼及開發說明請參考:https://github.com/NordicSemiconductor/Android-nRF-Blinky
- nRF Blinky iOS版源代碼及開發說明請參考:https://github.com/NordicSemiconductor/iOS-nRF-Blinky
沒有留言:
張貼留言