esp32系列休眠主要分为轻度休眠和深度休眠。
轻度休眠主要特征是休眠时间内运行内存和大部分外设不关闭,设备从程序的那里调用接口进入轻度休眠,唤醒后就从那里接着运行,设备运行前各种寄存器和外设值得以保留。
深度休眠则只会保留RTC时钟、ULP等少部分外设通电,设备唤醒后程序重新从入口开始运行。
两者对应的功耗也是有所差别。只在默认设置下,esp32系列轻度休眠待机电流为mA级,深度休眠待机电流为uA级,更具体的数据需要根据具体型号和开启的外设来确定。
一、轻度休眠
在浅度睡眠模式下,数字外设、大部分 RAM 和 CPU 都是时钟门控的,并且电源电压会降低。退出浅睡眠状态后,外设和 CPU 恢复运行,并保留其内部状态
进入轻度休眠
esp_light_sleep_start()
注:可以通过配置,在轻度休眠的情况下更为细致的设置部分外设(GPIO和Flash)
二、深度休眠
在深度睡眠模式下,CPU、大部分 RAM 以及所有由 APB_CLK 提供时钟的数字外设均关闭。
芯片中唯一仍可以通电的部分是:实时时钟控制器;实时时钟外设;ULP协处理器;RTC快速存储器;RTC 慢速内存
进入深度休眠
esp_deep_sleep_start()
另外,就算是在深度休眠,也可以单独设置部分外设开启(功耗对应增加),例如GPIO:
//使能gpio30 在深度休眠时候保存高电平
#define GPIO30_PIN 30
gpio_config_t gpio30_config={
.intr_type= GPIO_INTR_DISABLE,
.mode=GPIO_MODE_OUTPUT,
.pin_bit_mask=BIT64(GPIO30_PIN),
.pull_down_en=0,
.pull_up_en=1,
};
gpio_config(&gpio30_config);
//先配置IO并给定初始值
gpio_set_level(GPIO30_PIN, 1);
//再锁定
gpio_hold_en(GPIO30_PIN);
gpio_deep_sleep_hold_en();
//进入休眠 gpio30保持拉高 ,
esp_deep_sleep_start();
三、唤醒源
只知道设备怎么进入休眠是没有实际意义的。项目中需要提前设置唤醒设备的条件,也就是唤醒源,使设备在特定情况下从休眠状态中退出。esp32-S3提供以下几种唤醒,其中部分唤醒源只有在轻度休眠才能配置使用:
1、定时器定时唤醒
时间以微秒精度指定,但实际分辨率取决于为 RTC SLOW_CLK 选择的时钟源。
开启唤醒源:
#define SlEEP_TIME 1000*1000
esp_sleep_enable_timer_wakeup(SlEEP_TIME); //设备休眠1S后唤醒
2、触摸板
开启唤醒源:
esp_sleep_enable_touchpad_wakeup()
3、外部唤醒(ext0)
RTC IO 是 RTC 外设电源域的一部分,因此如果请求此唤醒源, RTC 外设将在深度睡眠期间保持通电状态。
注意:esp32-S3一般只有前16个编号的引脚为RTC IO引脚,具有此项功能。
开启唤醒源:
#define RTC_INTR_GPIO 5 //0-15即使RTC IO 也是GPIO
esp_sleep_enable_ext0_wakeup(RTC_INTR_GPIO , 0);//5脚低电平唤醒
esp_sleep_enable_ext0_wakeup()
4、外部唤醒(ext1)
RTC 控制器包含使用多个 RTC GPIO 为一组触发唤醒的逻辑。
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_en(gpio_num);
开启唤醒源
esp_sleep_enable_ext1_wakeup()
5、ULP 协处理器唤醒
ULP 协处理器可以在芯片处于睡眠模式时运行,并且可用于轮询传感器、监视 ADC 或触摸传感器值,以及在检测到特定事件时唤醒芯片。ULP功能在5.0.1版本尚不稳定,不推荐使用。
开启唤醒源
esp_sleep_enable_ulp_wakeup()
6、GPIO 唤醒(仅限浅睡眠)
该唤醒源适用任何 IO。
开启唤醒源
gpio_wakeup_enable(30,1);//gpio30 高电平唤醒
esp_sleep_enable_gpio_wakeup()
7、UART 唤醒(仅限浅睡眠)
当 ESP32-S3 接收外部设备的 UART 输入时,通常需要在输入数据可用时唤醒芯片。UART 外设包含一项功能,允许在 RX 引脚上看到一定数量的上升沿时将芯片从浅睡眠状态唤醒。上升沿的数量可以使用uart_set_wakeup_threshold()函数设置。
开启唤醒源
esp_sleep_enable_uart_wakeup()
以上唤醒源多数可以自由搭配使用,如以下同时使能ext0唤醒和定时唤醒:
#define RTC_INTR_GPIO 5 //0-15即使RTC IO 也是GPIO
int intoSleep(void){
esp_sleep_enable_ext0_wakeup(RTC_INTR_GPIO , 0);//5脚低电平唤醒
esp_sleep_enable_timer_wakeup(1000*1000*60);//1分钟
esp_deep_sleep_start();
}
8、查看被哪个唤醒源唤醒
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void);
返回值
/**
* @brief Sleep wakeup cause
*/
typedef enum {
ESP_SLEEP_WAKEUP_UNDEFINED, //!< In case of deep sleep, reset was not caused by exit from deep sleep
ESP_SLEEP_WAKEUP_ALL, //!< Not a wakeup cause, used to disable all wakeup sources with esp_sleep_disable_wakeup_source
ESP_SLEEP_WAKEUP_EXT0, //!< Wakeup caused by external signal using RTC_IO
ESP_SLEEP_WAKEUP_EXT1, //!< Wakeup caused by external signal using RTC_CNTL
ESP_SLEEP_WAKEUP_TIMER, //!< Wakeup caused by timer
ESP_SLEEP_WAKEUP_TOUCHPAD, //!< Wakeup caused by touchpad
ESP_SLEEP_WAKEUP_ULP, //!< Wakeup caused by ULP program
ESP_SLEEP_WAKEUP_GPIO, //!< Wakeup caused by GPIO (light sleep only on ESP32, S2 and S3)
ESP_SLEEP_WAKEUP_UART, //!< Wakeup caused by UART (light sleep only)
ESP_SLEEP_WAKEUP_WIFI, //!< Wakeup caused by WIFI (light sleep only)
ESP_SLEEP_WAKEUP_COCPU, //!< Wakeup caused by COCPU int
ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG, //!< Wakeup caused by COCPU crash
ESP_SLEEP_WAKEUP_BT, //!< Wakeup caused by BT (light sleep only)
} esp_sleep_source_t;
/* Leave this type define for compatibility */
typedef esp_sleep_source_t esp_sleep_wakeup_cause_t;
注意项:
在深度睡眠和浅度睡眠模式下,无线外设将断电。在进入浅睡眠模式之前,应用程序必须使用适当的调用**(esp_bluedroid_disable()、esp_bt_controller_disable()、esp_wifi_stop())**禁用 WiFi 和 BT。
即使不调用这些函数,在深度睡眠或浅度睡眠下也不会保持 WiFi 和 BT 连接。
四、总结
esp32的休眠唤醒配置十分灵活,如何搭配使用,需要结合具体项目场景。此次分享就此结束,觉得有用,可以点点赞,这是我更新的动力。
参考
https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.4/esp32s3/api-reference/system/sleep_modes.html?highlight=sleep