ESP32定时器加低功耗demo

本文详细介绍了ESP32如何利用Deep-sleep模式实现30秒休眠,并通过RTC外设和ULP协处理器唤醒,展示了定时器、touchpad和GPIO触发唤醒的过程。深入探讨了软件定时器的配置和任务调度在低功耗应用中的实践。
摘要由CSDN通过智能技术生成

ESP32 系列芯片提供三种可配置的睡眠模式,针对这些睡眠模式,我们提供了了多种低功耗解决方案,用户可以结合具体需求选择睡眠模式并进行配置。

三种睡眠模式如下:

Modem-sleep 模式:CPU 可运行,时钟可被配置。Wi-Fi/蓝牙基带和射频关闭。

Light-sleep 模式:CPU 暂停运行,Wi-Fi/蓝牙基带和射频关闭。RTC 存储器和外设以及 ULP 协处理器运行。任何唤醒事件(MAC、主机、RTC 定时器或外部中断)都会唤醒芯片。

Deep-sleep 模式:CPU 和大部分外设都会掉电,Wi-Fi/蓝牙基带和射频关闭,只有 RTC 存储器和 RTC 外设以及 ULP 协处理器可以工作。Wi-Fi 和蓝牙连接数据存储在 RTC 中


ESP32 在内置 Deep-sleep 低功耗模式、RTC 外设和 ULP 协处理器的支持下,可以满足多种应用场景下的低功耗需求。当 ESP32 进入 Deep-sleep 模式时,所有由 APB_CLK 驱动的外设、CPU 和 RAM 将掉电;RTC_CLK 继续工作;RTC 控制器、RTC 外设、ULP 协处理器、RTC 快速内存和 RTC 慢速内存可以不掉电,具体取决于 App 中的唤醒源设置。

资源包括:

RTC 外设 – 包括片上温度传感器、ADC、RTC GPIO 和 touchpad;

ULP 协处理器 – 可在 Deep-sleep 模式下,进行简单的数据采集或作为一种唤醒源。协处理器可以访问 RTC 慢速内存和 RTC 寄存器;

RTC 快速内存 – 芯片从 Deep-sleep 模式下唤醒后不会马上执行 bootloader,而是会先执行存放在 RTC 快速内存中的 esp_wake_deep_sleep() 函数;

RTC 慢速内存 – 存放 ULP 协处理器和 wake stub 代码访问的数据。

Deep-sleep 模式下支持的唤醒源包括:

1)定时器

2)touchpad

3)Ext(0):RTC IO 中某个指定 GPIO 满足指定电平即唤醒

4)Ext(1):RTC IO 中某些指定 GPIO 同时满足指定电平即唤醒

5)ULP 协处理器

使用RTC IO 外部引脚触发唤醒例程

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"         //任务
#include "freertos/queue.h"        //消息队列头文件
#include "freertos/semphr.h"       //信号量头文件
#include "freertos/event_groups.h" //事件头文件
#include "freertos/timers.h"       //软件定时器头文件
#include "driver/gpio.h"
#include "driver/ledc.h" //LED PWM控制
#include "driver/uart.h" //串口
#include "driver/i2c.h"  //I2C
//#include "ble_ancs.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
//蓝牙头文件
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
//
#include <time.h>
#include <sys/time.h>
#include "esp_sleep.h"

#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"

#include "sdkconfig.h"

//软件定时器
static TimerHandle_t Time_1500_Handle = NULL; //软件定时器句柄
static TimerHandle_t Time_3000_Handle = NULL; //软件定时器句柄
static uint32_t Time_1500_Count = 0;          //记录软件定时器回调函数执行的次数
static uint32_t Time_3000_Count = 0;

//GPIO定义
#define BLINK_GPIO GPIO_NUM_2
#define BLINK_GPIO22 GPIO_NUM_22
#define Key_GPIO GPIO_NUM_21
#define Key2_GPIO GPIO_NUM_19

//Deep_sleep
static TaskHandle_t Deep_Sleep_Task_Handle = NULL; //深度睡眠句柄

static TaskHandle_t APPTaskCreat_Handle = NULL; //任务句柄

//GPIO初始化
void GPIO_init()
{

    gpio_reset_pin(BLINK_GPIO);
    gpio_reset_pin(BLINK_GPIO22);
    gpio_reset_pin(GPIO_NUM_23);
    gpio_reset_pin(Key_GPIO);
    gpio_reset_pin(Key2_GPIO);
    gpio_reset_pin(GPIO_NUM_12);

    /* Set the GPIO as a push/pull output */
    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
    gpio_set_direction(BLINK_GPIO22, GPIO_MODE_OUTPUT);
    gpio_set_direction(GPIO_NUM_23, GPIO_MODE_OUTPUT);
    gpio_set_direction(Key_GPIO, GPIO_MODE_INPUT);
    gpio_set_direction(Key2_GPIO, GPIO_MODE_INPUT);
    gpio_set_direction(GPIO_NUM_12, GPIO_MODE_INPUT);
    gpio_set_level(BLINK_GPIO, 0);
    gpio_set_level(BLINK_GPIO22, 0);
}

//软件定时器
void Time_1500_Callback(void *arg)
{
    TickType_t tick_num1;
    Time_1500_Count++;
    tick_num1 = xTaskGetTickCount();
    printf("Time_1500_Callback函数执行 %d 次\r\n", Time_1500_Count);
    printf("定时器数值= %d 次\r\n", tick_num1);
}
void Time_3000_Callback(void *arg)
{
    TickType_t tick_num2;
    Time_3000_Count++;
    tick_num2 = xTaskGetTickCount();
    printf("Time_3000_Callback函数执行 %d 次\r\n", Time_3000_Count);
    printf("定时器数值= %d 次\r\n", tick_num2);
}

void Creat_Time_init()
{
    Time_1500_Handle = xTimerCreate("Time1500",                //定时器名称
                                    1500 / portTICK_PERIOD_MS, //定时器周期 1500ms
                                    pdTRUE,                    //周期模式
                                    1,                         //索引唯一ID
                                    Time_1500_Callback);       //回调函数

    if (Time_1500_Handle != NULL)
    {
        xTimerStart(Time_1500_Handle, 0); //开启定时器
    }

    Time_3000_Handle = xTimerCreate("Time3000",                //定时器名称
                                    3000 / portTICK_PERIOD_MS, //定时器周期 3000ms
                                    pdTRUE,                    //周期模式
                                    2,                         //索引唯一ID
                                    Time_3000_Callback);       //回调函数

    if (Time_3000_Handle != NULL)
    {
        xTimerStart(Time_3000_Handle, 0); //开启定时器
    }
}
void Deep_Sleep_Task_Function(void *arg)
{

    while (1)
    {
        if (Time_3000_Count==10)
        {
            switch (esp_sleep_get_wakeup_cause())
            {

            case ESP_SLEEP_WAKEUP_EXT0:
            {
                Time_3000_Count=0;
                printf("Wake up\r\n");
            }
            case ESP_SLEEP_WAKEUP_UNDEFINED: //未定义,不是唤醒
            default:
                printf("Not a deep sleep reset\n");
            }
            esp_sleep_enable_ext0_wakeup(GPIO_NUM_12, 0);//RTC IO,低电平唤醒
            gpio_set_level(BLINK_GPIO, 0);
            gpio_set_level(BLINK_GPIO22, 0);
            printf("a deep sleep start\n");
            esp_deep_sleep_start();
        }

        vTaskDelay(100 / portTICK_RATE_MS);
    }
}

//总任务的创建
void APPTaskCreat_Function(void *arg)
{

    GPIO_init();
    // Creat_Queue_init();
    // Binary_Create_init();
    // Event_Create_init();
    Creat_Time_init();
    // NVS_Flash_init();
    // I2C0_init();
    // ATH10_init();
    // NVS_Task_Function();

    BaseType_t xReturn = pdPASS;

    xReturn = xTaskCreate(Deep_Sleep_Task_Function, //任务函数
                          "Deep_Sleep_Task",        //任务名称
                          4096,                     //任务栈大小
                          NULL,                     //任务入口函数参数
                          2,                        //任务优先级
                          &Deep_Sleep_Task_Handle); //句柄

    if (pdPASS == xReturn)
    {
        //  printf("Deep_Sleep_Task任务创建成功\r\n");
    }

    // xReturn = xTaskCreate(CPU_Task_Function, //任务函数
    //                       "CPU_Task",        //任务名称
    //                       2048,               //任务栈大小
    //                       NULL,               //任务入口函数参数
    //                       2,                  //任务优先级
    //                       NULL); //句柄

    // if (pdPASS == xReturn)
    // {
    //     //  printf("CPU_Task任务创建成功\r\n");
    // }

    //  printf("删除APPTask任务成功\r\n");
    vTaskDelete(APPTaskCreat_Handle); //删除任务
}

void app_main(void)
{
    xTaskCreatePinnedToCore(APPTaskCreat_Function, //任务函数
                            "APPTaskCreat",        //任务名称
                            2048,                  //任务栈大小
                            NULL,                  //任务入口函数参数
                            1,                     //任务优先级
                            &APPTaskCreat_Handle,  //任务句柄
                            tskNO_AFFINITY);       //指定运行任务的CPU,使用这个宏表示不会固定到任何核上

    //   xReturn=xTaskCreate(APPTaskCreat_Function,//任务函数
    //                           "APPTaskCreat",//任务名称
    //                           2048,//任务栈大小
    //                           NULL,//任务入口函数参数
    //                           1,//任务优先级
    //                           &APPTaskCreat_Handle);
    // configASSERT( APPTaskCreat_Handle );
    // //启动任务调度器
    //   if (pdPASS==xReturn)
    //  {
    //     /* code */
    //    // vTaskStartScheduler();
    //     printf("启动任务,开启调度器成功\r\n");
    //  }
    //  else
    //  {
    //   return (-1);

    // }

    // while(1);
}
效果:实现30秒休眠,唤醒后运行30秒后再休眠以此反复

结果

 作者:小梦小图 https://www.bilibili.com/read/cv13635271 出处:bilibili

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值