接觸nrf52832晶片已經有一段時間了,記錄我踩過的坑。這些坑大多都補回來了,願後來的開發者沒有坑~
先來點開胃小菜
一、環境問題
- 安裝離線包遇到的錯誤——svdconv exited with an error
原因可能是軟體包含中文路徑或者keil版本過低,修改安裝路徑或者升級一下keil。
- Jlink下載提示No Cortex-M SW Device Found錯誤
最簡單的就是在keil的除錯設定裡面選擇Jlink,然後scan一下
不行就重插jlink再試一下。如果還是不行,不著急,還可以試試一下這個方法
開啟jlink的RTT Viewer(或者在keil裡面debug的Jlink選擇cmd進入),然後選著預設使用的藍芽晶片按下回車,之後去keil下載就沒有這些錯誤。
- Keil5除錯警告——This target device does not support all the defined breakpos!Please reduce the number of breakpoints and start again.
原因裝置斷點太多,超過5個就會產生這個警告。清除所有斷點,再選擇自己想要設定斷點的位置。
- keil5閃退問題
可能的兩個原因,Jlink的接觸不良,拔了再接起來可能就沒有了,最好的解決辦法是買正版的Jlink,還可以把工程移動到其他資料夾也可能可以解決。
還有就是版本相容性問題,可以試著把Keil登錄檔中的Recent Projects的全部內容清楚。
如果還不行,便把keil5程式改成相容性win7。
再不行,打擾了
這些用到keil5的都有可能會遇到,不要慌都可以解決 來點主菜吧,大家也等久了~
二、程式問題
- 【編譯錯誤】 ".\_build\nrf52832_xxaa.axf: Error: L6218E: Undefined symbol app_uart_init (referred from main.o)."
版本驅動不相容,新增就得版本驅動即可解決。舊版驅動:\modules\nrfx\drivers,新版驅動:\integration\nrfx\legacy.
- 【編譯錯誤】 "._build\rtc_tick.axf: Error: L6200E: Symbol SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler multiply defined (by nrf_drv_spi.o and nrf_drv_twi.o)."
TWI0和SPI0使用使用相同地址,把其中一個換到1(SPI1/TWI1)或者使用模擬IIC。
- 【編譯錯誤】 ”,. build\nrf5232 xxaa,.axf: Eror:16915E:Library zeports error: _use no sewihosting was requested, bnt asemihosting frutc was linked inNot enough information to list load addresses in the image map.“
我的解決辦法是把printf改成NRF_LOG_INFO列印輸出。網上的解決辦法是Keil的設定裡面勾選use MicroLIB。
- RTT列印浮點數,NRF_LOG_INFO無法列印浮點數
1) 新增串列埠列印;
2) 新增浮點數列印函式——NRF_LOG_FLOAT.
/**
* @brief Macro to be used in a formatted string to a pass float number to the log.
*
* Use this macro in a formatted string instead of the %f specifier together with
* @ref NRF_LOG_FLOAT macro.
* Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f)))
*/
#define NRF_LOG_FLOAT_MARKER "%s%d.%02d"
/**
* @brief Macro for dissecting a float number into two numbers (integer and residuum).
*/
#define NRF_LOG_FLOAT(val) (uint32_t)(((val) < 0 && (val) > -1.0) ? "-" : ""), \
(int32_t)(val), \
(int32_t)((((val) > 0) ? (val) - (int32_t)(val) \
: (int32_t)(val) - (val))*100)
- IIC讀寫卡住問題
卡在iic讀寫的時候,很大可能是它的裝置地址沒有寫對,有些庫會偏移器件地址,有些不會。試一下把iic器件的地址偏移。
- 自定義藍芽名字過長,廣播顯示不全
原因:nrf52832預設使用藍芽4.x的廣播,它的廣播包資料只有32byte資料,當廣播已經包含足夠多的資料的時候,廣播每次過長就會顯示部分名稱,即便你選擇"BLE_ADVDATA_FULL_NAME"也一樣。解決辦法是使用藍芽5.0,它的容量就會增加到254byte,具體新增程式碼如下:
/**
* @brief Function for initializing the Advertising functionality.
*/
void advertising_init(void)
{
uint32_t err_code;
ble_advertising_init_t adv_data;
ble_advdata_service_data_t service_data; //定義藍芽服務資料到廣播包中
int8_t tx_power_level = TX_POWER_LEVEL; //設定發射功率
memset(&adv_data, 0, sizeof(adv_data));
adv_data.advdata.name_type = BLE_ADVDATA_FULL_NAME;
adv_data.advdata.include_appearance = true;
adv_data.advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
adv_data.advdata.p_tx_power_level = &tx_power_level;
adv_data.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
adv_data.advdata.uuids_complete.p_uuids = m_adv_uuids;
uint8_t my_adv_manuf_data[6] = {0};
memcpy(my_adv_manuf_data, passwords, 6);
ble_advdata_manuf_data_t manuf_specific_data; //定義製造商資料結構體變數
manuf_specific_data.company_identifier = 0x0059; //0x0059是Nordic的製造商ID
manuf_specific_data.data.p_data = my_adv_manuf_data; //指向自定義資料
manuf_specific_data.data.size = sizeof(my_adv_manuf_data); //自定義資料的大小
adv_data.advdata.p_manuf_specific_data = &manuf_specific_data; //定義自定義資料到廣播包中
adv_data.config.ble_adv_fast_enabled = true;
adv_data.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
adv_data.config.ble_adv_fast_timeout = APP_ADV_DURATION;
adv_data.evt_handler = on_adv_evt;
//**********************新增藍芽5.0**************************//
adv_data.config.ble_adv_primary_phy = BLE_GAP_PHY_1MBPS;
adv_data.config.ble_adv_secondary_phy = BLE_GAP_PHY_2MBPS;
adv_data.config.ble_adv_extended_enabled = true;
//***********************************************************//
err_code = ble_advertising_init(&m_advertising, &adv_data);
APP_ERROR_CHECK(err_code);
ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}
注意:只能新增advdata的資料,srdata的資料在開啟5.0之後新增會出錯。
- 按鍵長短按設定的時候每次都進入短按事件
註釋掉bsp_init()裡面的迴圈
// uint32_t num;
// for (num = 0; ((num < BUTTONS_NUMBER) && (err_code == NRF_SUCCESS)); num++)
// {
// err_code = bsp_event_to_button_action_assign(num, BSP_BUTTON_ACTION_PUSH, BSP_EVENT_DEFAULT);
// }
- 【程式錯誤】 <error> nrf_sdh_ble: sd_ble_enable() returned NRF_ERROR_NO_MEM.
錯誤截圖:
將0x20002AE8和0xD518放入Keil5的RAM設定
產生NRF_ERROR_NO_MEM的原因,除了RAM沒有配置對,還與NRF_SDH_BLE_VS_UUID_COUNT和NRF_SDH_BLE_GATTS_ATTR_TAB_SIZE,試著SIZE的值,然後改RAM可能就可以解決。
- 【自定義服務】—— 初始化值不顯示、顯示不全問題
看看有沒有設定變數把值存進去,再進行復制;設定長度可變,如下
add_char_params.is_var_len = true; //長度可變
- 【自定義服務】新增128bitUUID到特性
在新增特性前面,新增一個sd_ble_uuid_vs_add()函式,把自定義特性的128UUID放進去,然後再新增特性。
示例程式碼:
/**
@brief Register the application callback function. Call this function only once
@param pLwsProfile -[out] LWS Initialize the service structure
@param pAppCallback -[in] Callback to the application
@return NRF_SUCCESS - Success; other values-failure
*/
uint32_t ble_lws_init(LwsProfile_t *pLwsProfile, const LwsProfileCallback_t *pAppCallback)
{
uint32_t errCode;
ble_uuid_t bleUuid;
ble_add_char_params_t addCharParams;
// Initialize the service structure
pLwsProfile->lWsProfileCharWriteHandler = pAppCallback->lWsProfileCharWriteHandler;
/*--------------------- service ---------------------*/
ble_uuid128_t baseUuid = {LWSPROFILE_UUID_BASE};
// Add base UUID
errCode = sd_ble_uuid_vs_add(&baseUuid, &pLwsProfile->uuidType);
VERIFY_SUCCESS(errCode);
//Add main service UUID
bleUuid.type = pLwsProfile->uuidType;
bleUuid.uuid = LWSPROFILE_UUID_SERVICE;
errCode = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
&bleUuid,
&pLwsProfile->serviceHandle);
VERIFY_SUCCESS(errCode);
/*--------------------- characteristic 1--Update request---------------------*/
ble_uuid128_t nus_base_uuid_char1 = LWSPROFILE_UUID_NEW_CHAR1;
errCode = sd_ble_uuid_vs_add(&nus_base_uuid_char1, &pLwsProfile->uuidType); // add uuid base to SD, get uuid type back to app
VERIFY_SUCCESS(errCode);
memset(&addCharParams, 0, sizeof(addCharParams));
addCharParams.uuid = LWSPROFILE_UUID_CHAR1;
addCharParams.uuid_type = pLwsProfile->uuidType;
addCharParams.init_len = 0;
addCharParams.max_len = LWSPROFILE_CHAR1_LEN; // Characteristic length
addCharParams.is_var_len = true; //可變資料長度
addCharParams.char_props.indicate = 1; // Declarable
addCharParams.cccd_write_access = SEC_MITM;
errCode = characteristic_add(pLwsProfile->serviceHandle, &addCharParams, &pLwsProfile->char1Handle);
return errCode;
}
- 在DFU後,FDS內容丟失
FDS供使用者使用的有一個範圍的ID,FILE ID(0x0000 - 0xBFFF),RECORD KEY(0x0001 - 0xBFFF),在這個範圍內使用一般沒什麼問題,而我直接使用0xfff1的ID,就有這個問題。FILE ID 從0xC000 到 0xFFFF 的值保留供Peer Manager模組使用,並且只能在不包含 Peer Manager 的應用程式中使用;RECORD KEY 從0xFFFF 是被系統使用的,從 0xC000 到 0xFFFE 的值保留供Peer Manager模組使用,並且只能在不包含 Peer Manager 的應用程式中使用。
- sd_ble_gatts_value_set()產生的錯誤NRF_ERROR_DATA_SIZE
原因:使用資料長度超過特徵最大長度
解決辦法:將所使用到的特徵的最大長度加長
-
nrf_crypto_init初始化失敗
RTT列印資訊:
sm_init()初始化產生的錯誤,可能是RNG重複初始化,可以在sm_init()裡面加一個重複判斷,或者把原先的RNG初始化關閉。
三、硬體問題
- DFU升級程式一直卡在bootloader
本來以為是配置問題,然後看了一天的配置,發現一點問題都沒有 再去看升級命令、步驟,也沒有發現什麼問題。也試過改settings的版本號,也不行。最後在官方文件發現,程式在啟動時先進入協議棧,再由協議棧進入bootloader,然後bootloader去檢測是否進入app。如果bootloader的按鍵進入DFU引腳一直被拉高,就會導致程式一直無法啟動。解決辦法,把bootloader的按鍵檢測引腳更換到其他引腳位置。
原本是25號引腳,被我改到了27號,程式可以正常進入,DFU也是正常的。
四、解決思路
以前遇到nrf52832問題的時候,直接就百度,如果關鍵詞不對會花費很多時間。現在的話,先去開啟DEBUG列印,看看錯誤的位置,再去看函式定義的錯誤返回值是什麼原因引起的,要麼直接改,要麼根據這個函式和返回錯誤百度或者去官方社群搜尋。都找不到就去看NORDIC線上文件的指導步驟。之後想到的再更新,nrf52832該有的坑我都踩了
五、參考連結
關於stm32報錯Library reports error: __use_no_semihosting was requested的三種解決方案