NRF52832學(xué)習(xí)筆記(33)——低功耗實現(xiàn)

一折柠、功耗模式

nRF52 上只有兩種電源模式:SYSTEM_ONSYSTEM_OFF

1.1 SYSTEM_ON低功耗模式

SYSTEM_ON:此狀態(tài)有持續(xù)延遲和低功率子模式辩块。當(dāng)系統(tǒng)空閑進入 System On 模式時昏鹃,默認(rèn)情況下將處于低功耗子模式返弹,通常最低功耗為 1.9uA (nRF52832) 或 1.5uA(nRF52840)稀余,包括 LFCLK 和 RTC及舍。這是連接事件之間的正常狀態(tài)。CPU 在計時器、外圍設(shè)備或pin中斷時重新啟動汇四。

1.1.1 進入SYSTEM_ON模式

當(dāng) CPU 和外圍設(shè)備處于空閑狀態(tài)時接奈,芯片進入默認(rèn)的低功耗子模式。

在主函數(shù)最后面都會出現(xiàn)一個 for 循環(huán)通孽,這個循環(huán)不停的重復(fù)運行其中的 idle_state_handle() 函數(shù)序宦。

int main(void)
{
    ···
    ···
    for(;;)
    {
        idle_state_handle();
    }
}

打開 idle_state_handle() 函數(shù),該函數(shù)是處理空閑狀態(tài)的函數(shù)背苦。通過 if 語句互捌,判斷調(diào)試緩沖區(qū)沒有更多日志的時候,就進入 nrf_pwr_mgmt_run() 函數(shù)行剂,這個函數(shù)就會進入到低功耗模式秕噪,直到下一個事件發(fā)生。

static void idle_state_handle(void)
{
    if(NRF_LOG_PROCESS() == false)  // 如果調(diào)試緩沖區(qū)沒有更多日志
    {
        nrf_pwr_mgmt_run();
    }
}

打開 nrf_pwr_mgmt_run() 函數(shù)厚宰,BLE 狀態(tài)下腌巾,如果 CPU 處于空閑狀態(tài)就會進入 sd_app_evt_wait() 函數(shù),這個函數(shù)是進入低功耗的關(guān)鍵铲觉,是協(xié)議棧提供的一個等待事件函數(shù)澈蝙。

void nrf_pwr_mgmt_run(void)
{
    PWR_MGMT_FPU_SLEEP_PREPARE();  // 清除FDU異常,避免FDU中斷被掛起
    PWR_MGMT_SLEEP_LOCK_ACQUIRE();  // 鎖定臨界區(qū)
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER();  // 用戶監(jiān)視段進入备燃,監(jiān)聽進入低功耗的時間
    PWR_MGMT_DEBUG_PIN_SET();  // 置位仿真引腳

    // Wait for an event.
#ifdef SOFTDEVICE_PRESENT  // 帶協(xié)議棧狀態(tài)下
    if (nrf_sdh_is_enabled())  // 如果協(xié)議棧被使能
    {
        ret_code_t ret_code = sd_app_evt_wait();  //調(diào)用協(xié)議棧等待函數(shù)
        ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED));
        UNUSED_VARIABLE(ret_code);
    }
    else
#endif // SOFTDEVICE_PRESENT  // 否則碉克,不帶協(xié)議棧狀態(tài)
    {
        // Wait for an event.
        __WFE();
        // Clear the internal event register.
        __SEV();
        __WFE();
    }

    PWR_MGMT_DEBUG_PIN_CLEAR();  // 清除仿真引腳
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT();  // 用戶監(jiān)視段退出
    PWR_MGMT_SLEEP_LOCK_RELEASE();  // 鎖定臨界區(qū)釋放
}

1.1.2 退出SYSTEM_ON模式

通過藍牙的事件觸發(fā)芯片脫離低功耗模式,進入運行狀態(tài)并齐。

1.2 SYSTEM_OFF睡眠模式

SYSTEM_OFF:是深省電模式漏麦,工作電流為 300nA (nRF52832) 或 400nA (nRF52840),在該模式下况褪,系統(tǒng)的內(nèi)核和所有在運行的任務(wù)都會停止撕贞,也就是說時鐘也停止,相當(dāng)于關(guān)機狀態(tài)测垛∧笈颍可以直接控制 POWER 相關(guān)寄存器使系統(tǒng)進入 System OFF 模式(NRF_POWER->SYSTEMOFF = 1; ),也可以通過API函數(shù)(sleep_mode_enter() 或 nrf_pwr_mgmt_run() 此函數(shù)執(zhí)行 __WFE() 指令進入睡眠前清除所有事件)食侮,可以參考 SDK 中的 nrf_pwr_mgt 例子屯碴,系統(tǒng)進入 System OFF 模式會保留 GPIO 之前的狀態(tài)瓶蝴,包括 GPIO 的輸入/輸出晓猛、I2C 總線翩伪、SPI 總線等,所以在進入 System OFF 模式前應(yīng)該將 GPIO 都釋放掉眉尸,使用 nrf_gpio_cfg_default(pin)釋放 GPIO域蜗,同時巨双,如果有 I2C 或 SPI 等總線外設(shè)也需要釋放掉;可以通過復(fù)位霉祸、GPIO 中斷或 NFC 信號(增加100nA)進行喚醒 筑累。從 System OFF 模式中喚醒程序會發(fā)生復(fù)位,參考 832 product spec 文檔

1.2.1 進入SYSTEM_OFF模式

在進入 System Off 模式之前丝蹭,用戶必須確保所有正在進行的 EasyDMA 通信已完成慢宗。進入深度睡眠之前一定要將使用 EasyDMA 的外設(shè)停掉。

BLE 程序代碼里通過兩種方式進入半夷,一個是廣播超時后會進入無效廣播婆廊,再進入睡眠迅细;另外就是通過按鍵按下調(diào)用睡眠模式進入函數(shù)進行進入巫橄。

  • 無效廣播后進入到睡眠模式
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    uint32_t err_code;

    switch(ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
            err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
            sleep_mode_enter();  // 進入睡眠模式
            break;
        default:
            break;
    }
}
  • 按鍵按下觸發(fā) BSP_EVENT_SLEEP 事件進入睡眠模式
static void bsp_event_handler(bsp_event_t event)
{
    ret_code_t err_code;
    switch(event)
    {
        case BSP_EVENT_SLEEP:
            sleep_mode_enter();  // 進入睡眠模式
            break;
        ···
        ···
    }
}

打開 sleep_mode_enter() 函數(shù),觀察到函數(shù)內(nèi)部主要實現(xiàn)配置休眠指示燈茵典、配置喚醒按鍵湘换,進入 System Off 睡眠模式三個功能。進入 System Off 模式的關(guān)鍵在于調(diào)用協(xié)議棧 API 函數(shù) sd_power_system_off()统阿,這個函數(shù)可以在協(xié)議棧下起到寄存器操作 NRF_POWER->SYSTEMOFF=1 一樣的效果彩倚。調(diào)用了這個函數(shù)后,系統(tǒng)將進入到睡眠模式扶平。

static void sleep_mode_enter(void)
{
    // 設(shè)置指示燈
    uint32_t err_code = bsp_indication_set(BSP_INDICATE_IDLE);
    APP_ERROR_CHECK(err_code);

    // 配置喚醒按鍵
    err_code = bsp_btn_ble_sleep_mode_prepare();
    APP_ERROR_CHECK(err_code);

    // 進入系統(tǒng)關(guān)閉模式(此功能不會返回帆离,喚醒將導(dǎo)致系統(tǒng)重置)
    err_code = sd_power_system_off();
    APP_ERROR_CHECK(err_code);
}

1.2.2 退出SYSTEM_OFF模式

在 System Off 模式下,可以通過以下信號之一喚醒設(shè)備:

  1. DETECT 信號结澄,可由 GPIO 外設(shè)產(chǎn)生哥谷。
  2. ANADETECT 信號,可由 LPCOMP 外設(shè)模塊產(chǎn)生麻献。
  3. SENSE 信號们妥,可由 NFC 模塊產(chǎn)生 "wake-on-field"方式產(chǎn)生。
  4. 復(fù)位重啟

在 BLE 程序中勉吻,提供了其中一種按鍵喚醒方式监婶,喚醒按鍵在 sleep_mode_enter() 函數(shù)的 bsp_btn_ble_sleep_mode_prepare() 中進行配置。

uint32_t bsp_btn_ble_sleep_mode_prepare(void)
{
    uint32_t err_code;
    // 配置喚醒按鍵
    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);
    // 配置喚醒和剔除綁定信息按鍵
    err_code = bsp_wakeup_button_enable(BTN_ID_WAKEUP_BOND_DELETE);
    RETURN_ON_ERROR_NOT_NOT_SUPPORTED(err_code);

    return NRF_SUCCESS;
}

二齿桃、硬件上降低功耗

不同的內(nèi)部穩(wěn)壓器選擇惑惶,會造成不同的電路消耗《套荩可以通過選擇不同的硬件電路配置带污,來選取下面兩種內(nèi)部穩(wěn)壓器:

  • 內(nèi)部 LDO 穩(wěn)壓器
  • 內(nèi)部 DC/DC 穩(wěn)壓器

LDO 是系統(tǒng)默認(rèn)的穩(wěn)壓器,而 DC/DC 穩(wěn)壓器可用作 LDO 穩(wěn)壓器的替代產(chǎn)品踩娘。與使用 LDO 穩(wěn)壓器相比刮刑,使用 DC/DC 穩(wěn)壓器具有更低的電流消耗喉祭,但 DC/DC 穩(wěn)壓器需要連接外部 LC 濾波器:



其中關(guān)于 DC/DC 穩(wěn)壓器所連接的 外部 LC 濾波器電路上的電感和電容參數(shù),請參看芯片手冊 53 節(jié) Reference circuitry 所提供的參考電路雷绢。



由于默認(rèn)選擇的是內(nèi)部 LDO 穩(wěn)壓器泛烙,因此如果需要切換到使用內(nèi)部 DC/DC 穩(wěn)壓器,還需要在軟件上進行配置翘紊。
  • 首先需要在主函數(shù) main.c 中蔽氨,初始化 softDevice 協(xié)議棧前,執(zhí)行 NRF_POWER->DCDCEN=1帆疟○木浚或者在初始化softDevice 協(xié)議棧后,執(zhí)行 sd_power_dcdc_mode_set(1)踪宠。
  • sdk_config.h 配置文件中勾選 NRFX_POWER_ENABLED 使能選項自赔,同時把選項下的 DC/DC 使能選項 NRFX_POWER_CONFIG_DEFAULT_DCDCEN 進行勾選。

    在選取電源電壓為 3.0 V 柳琢,廣播間隔為 500ms绍妨,發(fā)射功率為 0dbm 的情況下,選擇 DC/DC 穩(wěn)壓方式的總平均功耗電流為 20uA柬脸,而選擇 LDO 穩(wěn)壓方式的總平均電流在 32uA 左右他去。因此,選擇 DC/DC 穩(wěn)壓方式可以大幅度的降低功耗倒堕。

三灾测、軟件上降低功耗

3.1 廣播狀態(tài)下功耗優(yōu)化

3.1.1 發(fā)射功率

設(shè)置發(fā)射功率具有 9 個發(fā)射等級。系統(tǒng)默認(rèn)的發(fā)射功率是 0dbm垦巴,發(fā)射功率越大媳搪,發(fā)射距離就越遠(yuǎn),相應(yīng)的電流消耗就越大魂那。

3.1.2 廣播間隔時間

廣播間隔就是廣播包發(fā)出的頻率蛾号,廣播間隔越長,功耗越低涯雅。

3.1.3 廣播負(fù)載

藍牙的廣播包普通包長度在 31 字節(jié)鲜结,掃描響應(yīng)包也有 31 字節(jié)。如果藍牙 5.0 下的第二廣播包長度更長活逆,越長的廣播負(fù)載精刷,會造成越大的電流消耗。

3.2 連接狀態(tài)下功耗優(yōu)化

3.2.1 連接間隔和從機潛伏周期

連接間隔是保證主從機維持連接蔗候,相互發(fā)空包的時間間隔怒允。連接間隔可以在 GAP 初始化中進行設(shè)置。當(dāng)設(shè)置的連接間隔越長锈遥,設(shè)備的功耗越低纫事。因此勘畔,可以在維持連接狀態(tài)下,保證數(shù)據(jù)正常通信的基礎(chǔ)下丽惶,設(shè)置盡可能長的連接間隔炫七。

從機潛伏周期和連接間隔是同時進行配置的,從機潛伏周期允許藍牙設(shè)備一定次數(shù)的周期不對藍牙主機數(shù)據(jù)進行回復(fù)钾唬。在這個周期次數(shù)范圍內(nèi)万哪,藍牙主機即使沒有收到藍牙從機設(shè)備的回復(fù)確認(rèn)信息包,也會認(rèn)為設(shè)備正常抡秆。這種方式也可以降低藍牙設(shè)備的功耗奕巍。

3.2.2 發(fā)射和接收的數(shù)據(jù)量

藍牙數(shù)據(jù)發(fā)送和接收的數(shù)據(jù)量大小,直觀的影響到了功耗儒士。數(shù)據(jù)吞吐量越大的止,功耗越高。

3.3 系統(tǒng)及外設(shè)功耗優(yōu)化

3.3.1 協(xié)議棧時鐘選擇

協(xié)議棧時鐘可以選擇外部低速時鐘和內(nèi)部低速時鐘乍桂。選取外部低速時鐘具有更低的功耗冲杀,使能外部 32kHz 晶振效床,通扯米茫可以節(jié)省 1-2% 的電能。默認(rèn)使用外部低速晶振剩檀。在 main.c 文件憋沿,ble_stack_init() 函數(shù)中 nrf_sdh_enable_request() 找到

    nrf_clock_lf_cfg_t const clock_lf_cfg =
    {
        .source       = NRF_SDH_CLOCK_LF_SRC,
        .rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
        .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        .accuracy     = NRF_SDH_CLOCK_LF_ACCURACY
    };

.source 配置脈沖時鐘源 NRF_SDH_CLOCK_LF_SRC,默認(rèn)值為 1沪猴,即外部晶振辐啄。

// <0=> NRF_CLOCK_LF_SRC_RC     // 內(nèi)部時鐘源
// <1=> NRF_CLOCK_LF_SRC_XTAL  // 外部晶振源
// <2=> NRF_CLOCK_LF_SRC_SYNTH  // 合成時鐘源

#ifndef NRF_SDH_CLOCK_LF_SRC
#define NRF_SDH_CLOCK_LF_SRC 1
#endif

3.3.2 關(guān)閉日志打印

  • main.c 文件,main() 函數(shù)中注釋掉 log_init()运嗜。
  • 在 sdk_config.h 文件中關(guān)閉 UART 日志記錄壶辜,選擇支持 RTT。除非jlink調(diào)試器已連接担租,否則 RTT 不會使用電流砸民。



3.3.3 UART/UARTE

首先 UART 模塊本身只需要 55uA 的工作電流,同時會自動打開高頻時鐘電路奋救,也需要消耗 250uA 左右電流岭参。如果使能了 UARTE 的 EasyDMA,那么 DMA 還需要消耗額外的 2mA 電流尝艘。這樣 UARTE 工作消耗的電流會很高演侯。因此在 UART 沒有數(shù)據(jù)傳輸?shù)臅r候建議將 UART 關(guān)掉,以節(jié)省功耗背亥。

  • 注:為了達到低功耗和實時性雙重目的秒际,在設(shè)計 UART 通信的時候悬赏,我們經(jīng)常會額外再加 2 個 GPIO 口用來通知對方 UART 要傳送數(shù)據(jù)了。
  • 關(guān)閉 UART 的 API 為:nrf_drv_uart_uninit() 或者 app_uart_close()娄徊。

3.3.4 SPI/TWI

在不使用的時候建議采用 uninit 函數(shù)進行關(guān)閉舷嗡,這部分的外設(shè)也消耗電流。需要使用的時候進行 init 初始化開啟嵌莉。

  • SPI 開啟和關(guān)閉:nrf_drv_spi_initnrf_drv_spi_uninit
  • TWI 開啟和關(guān)閉:nrf_drv_twi_enablenrf_drv_twi_disable

3.3.5 SAADC

在不使用的時候建議采用 uninit 函數(shù)進行關(guān)閉进萄,需要使用的時候進行 init 初始化開啟。

3.3.6 GPIOE

GPIOE 事件模式下具有兩鐘模式:高精度模式(hi_accuracy 為 true)和低精度模式(hi_accuracy 為 false)。高精度模式 IN event 中斷比低精度模式 Port event 中斷消耗更多的電流 10~20uA椎扬。如果只是檢測 IO 口電平惫搏,建議使用低精度模式,也就是所有的輸入信號都使用一個中斷申請蚕涤,庫函數(shù)調(diào)用配置:
GPIOTE_CONFIG_IN_SENSE_HITOLO(false);

3.3.7 Timer

Timer0/1/2/3/4筐赔。Timer 的工作電流大概為 5~50uA 左右(nRF51功耗會更高),對低功耗應(yīng)用來說揖铜,已經(jīng)非常大了茴丰。如果你的定時精度要求不高,而且是毫秒的倍數(shù)天吓,那么強烈建議你使用 RTC 來實現(xiàn)定時功能贿肩。協(xié)議棧下為 app_timer 軟件定時器,app_timer 的功耗只有 0.2uA 左右龄寞。

3.3.8 FPU

由于 nRF52x 系列處理器不同于 nRF51 系列汰规,其內(nèi)核為 ARM Cortex M4 處理器。ARM Cortex M4 處理器 帶 FPU 浮點運算單元物邑。每當(dāng)程序要執(zhí)行浮點運算的時候溜哮,內(nèi)核就會自動把 FPU 打開i。FPU 將消耗 7mA 以上的電流拂封,此種情況下茬射,進入 idle 模式之前必須手動關(guān)閉 FPU,手動關(guān)閉 FPU 代碼如下所示:

/* Clear FPSCR register and clear pending FPU interrupts. This code is base on

         * nRF5x_release_notes.txt in documentation folder. It is necessary part of code when

         * application using power saving mode and after handling FPU errors in polling mode.

*/

__set_FPSCR(__get_FPSCR() & ~(FPU_EXCEPTION_MASK));

(void) __get_FPSCR();

NVIC_ClearPendingIRQ(FPU_IRQn);

在新版本 SDK 中 idle_state_handle()已經(jīng)加了處理


四冒签、電量消耗預(yù)估

https://devzone.nordicsemi.com/power/


? 由 Leung 寫于 2020 年 10 月 14 日

? 參考:青風(fēng)電子社區(qū)
    板子功耗高的原因有哪些
    nRF52 Power優(yōu)化降低70%以上耗電量

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末在抛,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子萧恕,更是在濱河造成了極大的恐慌刚梭,老刑警劉巖肠阱,帶你破解...
    沈念sama閱讀 211,948評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異朴读,居然都是意外死亡屹徘,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,371評論 3 385
  • 文/潘曉璐 我一進店門衅金,熙熙樓的掌柜王于貴愁眉苦臉地迎上來噪伊,“玉大人,你說我怎么就攤上這事氮唯〖担” “怎么了?”我有些...
    開封第一講書人閱讀 157,490評論 0 348
  • 文/不壞的土叔 我叫張陵惩琉,是天一觀的道長豆励。 經(jīng)常有香客問我,道長瞒渠,這世上最難降的妖魔是什么良蒸? 我笑而不...
    開封第一講書人閱讀 56,521評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮伍玖,結(jié)果婚禮上嫩痰,老公的妹妹穿的比我還像新娘。我一直安慰自己私沮,他們只是感情好始赎,可當(dāng)我...
    茶點故事閱讀 65,627評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著仔燕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪魔招。 梳的紋絲不亂的頭發(fā)上晰搀,一...
    開封第一講書人閱讀 49,842評論 1 290
  • 那天,我揣著相機與錄音办斑,去河邊找鬼外恕。 笑死,一個胖子當(dāng)著我的面吹牛乡翅,可吹牛的內(nèi)容都是我干的鳞疲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,997評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼蠕蚜,長吁一口氣:“原來是場噩夢啊……” “哼尚洽!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起靶累,我...
    開封第一講書人閱讀 37,741評論 0 268
  • 序言:老撾萬榮一對情侶失蹤腺毫,失蹤者是張志新(化名)和其女友劉穎癣疟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潮酒,經(jīng)...
    沈念sama閱讀 44,203評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡睛挚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,534評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了急黎。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扎狱。...
    茶點故事閱讀 38,673評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖勃教,靈堂內(nèi)的尸體忽然破棺而出委乌,到底是詐尸還是另有隱情,我是刑警寧澤荣回,帶...
    沈念sama閱讀 34,339評論 4 330
  • 正文 年R本政府宣布遭贸,位于F島的核電站,受9級特大地震影響心软,放射性物質(zhì)發(fā)生泄漏壕吹。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,955評論 3 313
  • 文/蒙蒙 一删铃、第九天 我趴在偏房一處隱蔽的房頂上張望耳贬。 院中可真熱鬧,春花似錦猎唁、人聲如沸咒劲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,770評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽腐魂。三九已至,卻和暖如春逐纬,著一層夾襖步出監(jiān)牢的瞬間蛔屹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,000評論 1 266
  • 我被黑心中介騙來泰國打工豁生, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留兔毒,地道東北人。 一個月前我還...
    沈念sama閱讀 46,394評論 2 360
  • 正文 我出身青樓甸箱,卻偏偏與公主長得像育叁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子芍殖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,562評論 2 349