【WCH蓝牙系列芯片】-基于CH582开发板—四种低功耗模式电流测试

发布时间 2023-09-20 11:22:07作者: zyl4444

---------------------------------------------------------------------------------------------------------------------

在WCH沁恒官方提供的CH583的EVT资源包中,找到BLE文件中找到PW这个工程文件,这是一个系统睡眠模式并唤醒例程;其中GPIOA_5作为唤醒源,共4种功耗等级。
芯片提供以下 4 种主要的低功耗模式:
1、空闲模式(Idle)
所有外设保持正常供电,内核停止运行,时钟系统运转。检测到唤醒事件后,可以立即唤醒。
2、暂停模式(Halt)
在空闲模式的基础上,时钟系统停止。检测到唤醒事件后,首先时钟运转,然后唤醒内核运行。
3、睡眠模式(Sleep)
主 LDO 关闭,由超低功耗 ULP-LDO 维持 PMU、内核和基本外设供电,LSE 或 LSI 可以选择是否开启,RAM2K、RAM30K、USB 和 RF 配置可以选择是否维持供电。检测到唤醒事件后,首先主 LDO 开启,然后时钟运转,最后唤醒内核,程序继续运行,需要时可以重新设置到更高主频
4、下电模式(Shutdown)
在睡眠模式的基础上,关闭了内核和基本外设以及 USB 和 RF 配置,LSE 或 LSI 可以选择是否开启,RAM2K、RAM30K 可以选择是否维持供电。检测到唤醒事件后,PMU 将执行 GRWSM 复位,软件可根据复位标志 RB_RESET_FLAG 和可选的 RAM 中的保持数据区分于 RPOR

 

在数据手册上针对每一个模式,有具体的特征和进入条件,还有唤醒事件以及具体功耗的范围值。

 

在EVT资源包中的PW例程中只包含外部中断引脚PA5的方式唤醒睡眠,在此基础上,加入RTC中断唤醒。

    GPIOA_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);
    GPIOB_ModeCfg(GPIO_Pin_All, GPIO_ModeIN_PU);

 

在主程序中,GPOIO中都没有内部断开模式,上电后,默认状态为浮空输入状态,当引脚浮空状态非常耗电,所以在低功耗模式,要将在初始化时,需要将所有的IO口设置为模拟输入,这样可以避免有额外电流。

1、利用GPIO引脚中断唤醒和RTC定时模式作为唤醒源

#if 1
    /* 配置唤醒源为 GPIO - PA5 */
    GPIOA_ModeCfg(GPIO_Pin_5, GPIO_ModeIN_PU);  //输入模式
    GPIOA_ITModeCfg(GPIO_Pin_5, GPIO_ITMode_FallEdge); // 下降沿唤醒
    PFIC_EnableIRQ(GPIO_A_IRQn);  //使能GPIOA中断
    PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_GPIO_WAKE, Long_Delay);   //使能外设唤醒功能,配置唤醒源为 GPIO 引脚,并设置长延时。
#endif

#if 1
    /* 配置唤醒源为 RTC */
    RTC_TMRFunCfg(Period_1_S);     // RTC定时模式配置  1s的周期
    PFIC_EnableIRQ(RTC_IRQn);  //使能RTC中断
    PWR_PeriphWakeUpCfg(ENABLE, RB_SLP_RTC_WAKE, Long_Delay);   //使能外设唤醒功能,配置唤醒源为 RTC事件唤醒,并设置长延时。
#endif

 

2、四种低功耗模式

#if 0
    PRINT("IDLE mode sleep \n");  //空闲模式
    DelayMs(1);
    LowPower_Idle();   //低功耗-Idle模式,让 CPU 进入睡眠状态以降低功耗
    PRINT("wake.. \n");
    DelayMs(500);
#endif

#if 0
    PRINT("Halt mode sleep \n");  //暂停挂起模式
    DelayMs(2);
    LowPower_Halt();  //将系统置于 Halt 模式,这是一种更低功耗的模式
    HSECFG_Current(HSE_RCur_100); // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayMs(2);
    PRINT("wake.. \n");
    DelayMs(500);
#endif

#if 1
    PRINT("sleep mode sleep \n");  //睡眠模式
    DelayMs(2);
    // 注意当主频为80M时,Sleep睡眠唤醒中断不可调用flash内代码。
    LowPower_Sleep(RB_PWR_RAM30K | RB_PWR_RAM2K); //只保留30+2K SRAM 供电
    HSECFG_Current(HSE_RCur_100);                 // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    DelayMs(5);
    PRINT("wake.. \n");
    DelayMs(500);
#endif

#if 0
    PRINT("shut down mode sleep \n");  //关机下电模式
    DelayMs(2);
    LowPower_Shutdown(0); //全部断电,唤醒后复位
    /*
     此模式唤醒后会执行复位,所以下面代码不会运行,
     注意要确保系统睡下去再唤醒才是唤醒复位,否则有可能变成IDLE等级唤醒
     */
    HSECFG_Current(HSE_RCur_100); // 降为额定电流(低功耗函数中提升了HSE偏置电流)
    PRINT("wake.. \n");
    DelayMs(500);
#endif

 

3、采用外部中断PA5作为唤醒睡眠

/*********************************************************************
 * @fn      GPIOA_IRQHandler
 *
 * @brief   GPIOA中断函数
 *
 * @return  none
 */
__INTERRUPT
__HIGH_CODE
void GPIOA_IRQHandler(void)  //GPIOA中断处理函数
{
    GPIOA_ClearITFlagBit(GPIO_Pin_6 | GPIO_Pin_5);  //中断标志位清除

}

 

4、采用RTC唤醒中断方式,1秒为周期唤醒

__INTERRUPT
__HIGH_CODE
void RTC_IRQHandler(void)  //RTC中断处理函数,RTC闹钟唤醒中断
{
    uint16_t py;
    uint16_t pmon;
    uint16_t pd;
    uint16_t ph;
    uint16_t pm;
    uint16_t ps;
    RTC_GetTime(&py,&pmon,&pd,&ph,&pm,&ps); //获取当前时间
    if(RTC_GetITFlag(RTC_TMR_EVENT))  //判断是否发生了 RTC 周期定时事件的中断(1秒)
    {
        printf("%d年%d月%d日%d时%d分%d秒\r\n",py,pmon,pd,ph,pm,ps);
        RTC_ClearITFlag(RTC_TMR_EVENT);  //清除RTC中断标志  (RTC 周期定时事件)
    }
}

 

5、各个模式下测试电流状态,包换睡眠和唤醒后电流值。

CH582系统睡眠模式低功耗测
低功耗模式

空闲模式
IDLE mode

暂停模式
Halt mode

睡眠模式
sleep mode

下电模式
shut down

GPIO未唤醒状态  2.45mA  324.30uA  3.13uA   0.56uA
GPIO唤醒  9.27mA    9.00mA   9.14mA  5.45mA
RTC未唤醒状态  2.45mA   324.55uA   3.11uA   0.56uA
RTC 1秒唤醒  9.03mA   9.19mA   9.07 mA   5.42mA