一、GPIO常用函数

esp_err_t gpio_reset_pin(gpio_num_tgpio_num)

将 gpio 重置为默认状态(选择 gpio 功能、启用上拉并禁用输入和输出)。备注此功能还将此引脚的 IOMUX 配置为 GPIO 功能,并断开通过 GPIO 矩阵配置的任何其他外设输出。参数gpio_num – GPIO 编号。返回始终返回ESP_OK。

esp_err_t gpio_set_intr_type(gpio_num_tgpio_num,gpio_int_type_tintr_type)

GPIO 设置中断触发器类型。参数gpio_num – GPIO 编号。如果要设置触发器类型,例如 GPIO16,则应gpio_num GPIO_NUM_16 (16);intr_type– 中断类型,从gpio_int_type_t中选择返回ESP_OK成功ESP_ERR_INVALID_ARG 参数错误

esp_err_t gpio_intr_enable(gpio_num_tgpio_num)

启用 GPIO 模块中断信号。备注ESP32:在启用睡眠模式的情况下使用 ADC 或 Wi-Fi 和蓝牙时,请不要使用 GPIO36 和 GPIO39 的中断。请参考评论。有关此问题的说明,请参阅ESP32 ECO 和 Bug 的解决方法3.11 节。解决方法是在应用中调用 adc_power_acquire()。这将导致更高的功耗(~1mA),但将消除GPIO36和GPIO39上的毛刺。adc1_get_raw参数gpio_num – GPIO 编号。如果要在 GPIO16 上启用中断,则应GPIO_NUM_16 (16) gpio_num;返回ESP_OK成功ESP_ERR_INVALID_ARG 参数错误

esp_err_t gpio_intr_disable(gpio_num_tgpio_num)

禁用 GPIO 模块中断信号。备注当在 ISR 上下文中禁用缓存时,允许通过启用CONFIG_GPIO_CTRL_FUNC_IN_IRAM参数gpio_num – GPIO 编号。如果要禁用例如 GPIO16 的中断,则应GPIO_NUM_16 (16) gpio_num;返回ESP_OK成功ESP_ERR_INVALID_ARG 参数错误

esp_err_t gpio_set_level(gpio_num_tgpio_num,uint32_t级)

GPIO 设置输出电平。备注当在 ISR 上下文中禁用缓存时,允许通过启用CONFIG_GPIO_CTRL_FUNC_IN_IRAM参数gpio_num – GPIO 编号。如果要设置输出电平,例如 GPIO16,则应gpio_num GPIO_NUM_16 (16);级别 – 输出级别。0: 低 ;1:高返回ESP_OK成功ESP_ERR_INVALID_ARG GPIO 编号错误

int gpio_get_level(gpio_num_tgpio_num)

GPIO 获取输入级别。警告如果未为输入(或输入和输出)配置焊盘,则返回值始终为 0。参数gpio_num – GPIO 编号。如果要获得例如引脚GPIO16的逻辑电平,则应gpio_num GPIO_NUM_16(16);返回0 GPIO 输入电平为 01 GPIO 输入电平为 1

esp_err_tgpio_isr_register(void(*fn)(void*),void*arg,int intr_alloc_flags,gpio_isr_handle_t* handle)

注册 GPIO 中断处理程序,处理程序是 ISR。处理程序将附加到运行此函数的同一 CPU 内核。每当发生任何 GPIO 中断时,都会调用此 ISR 函数。请参阅替代 gpio_install_isr_service() 和 gpio_isr_handler_add() API,以使驱动程序支持每个 GPIO ISR。若要禁用或删除 ISR,请将返回的句柄传递给中断分配函数。参数fn – 中断处理程序函数。arg– 处理程序函数的参数intr_alloc_flags– 用于分配中断的标志。一个或多个 (ORred) ESP_INTR_FLAG_* 值。有关详细信息,请参阅 esp_intr_alloc.h。句柄 – 指向返回句柄的指针。如果非 NULL,则将在此处返回中断的句柄。返回ESP_OK成功 ;ESP_ERR_INVALID_ARG GPIO 错误ESP_ERR_NOT_FOUND 未找到具有指定标志的空闲中断

无效gpio_uninstall_isr_service(无效)

卸载驱动程序的 GPIO ISR 服务,释放相关资源。

esp_err_t gpio_isr_handler_add(gpio_num_tgpio_num,gpio_isr_tisr_handler,void*args)

为相应的 GPIO 引脚添加 ISR 处理程序。使用 gpio_install_isr_service() 安装驱动程序的 GPIO ISR 处理程序服务后调用此函数。引脚 ISR 处理程序不再需要使用 IRAM_ATTR 声明,除非您在 gpio_install_isr_service() 中分配 ISR 时传递 ESP_INTR_FLAG_IRAM 标志。将从 ISR 调用此 ISR 处理程序。因此存在堆栈大小限制(可在菜单配置中配置为“ISR 堆栈大小”)。与全局 GPIO 中断处理程序相比,由于间接寻址级别增加,此限制较小。参数gpio_num– GPIO 编号isr_handler – 相应 GPIO 编号的 ISR 处理程序函数。args– ISR 处理程序的参数。返回ESP_OK成功ESP_ERR_INVALID_STATE 状态错误,则 ISR 服务尚未初始化。ESP_ERR_INVALID_ARG 参数错误

esp_err_t gpio_isr_handler_remove(gpio_num_tgpio_num)

删除相应 GPIO 引脚的 ISR 处理程序。参数gpio_num– GPIO 编号返回ESP_OK成功ESP_ERR_INVALID_STATE 状态错误,则 ISR 服务尚未初始化。ESP_ERR_INVALID_ARG 参数错误

struct gpio_config_t

用于gpio_config功能的GPIO垫的配置参数。公共成员

uint64_tpin_bit_mask    //GPIO 引脚:使用位掩码设置,每个位映射到一个 GPIO
gpio_mode_t mode     //GPIO 模式:设置输入/输出模式
gpio_pullup_t pull_up_en    //GPIO 上拉
gpio_pulldown_t pull_down_en    //GPIO 下拉
gpio_int_type_t intr_type

二、定时器函数

通用硬件定时器介绍

esp_err_t esp_timer_early_init(无效)

esp_timer的最小初始化。此函数可以在启动过程的早期调用,在此调用之后只能使用esp_timer_get_time函数。备注此函数从启动代码调用。应用程序在使用其他 esp_timer API 之前不需要调用此函数。返回关于成功的ESP_OK

esp_err_t esp_timer_init(无效)

初始化esp_timer库。备注此函数从启动代码调用。应用程序在使用其他 esp_timer API 之前不需要调用此函数。在调用此函数之前,esp_timer_early_init必须由启动代码调用。返回关于成功的ESP_OKESP_ERR_NO_MEM分配是否失败ESP_ERR_INVALID_STATE(如果已初始化)中断分配器的其他错误

esp_err_t esp_timer_deinit(无效)

取消初始化esp_timer库。备注通常不应从应用程序调用此函数返回关于成功的ESP_OKESP_ERR_INVALID_STATE(如果尚未初始化)

esp_err_tesp_timer_create(常量esp_timer_create_args_t*create_args,esp_timer_handle_t*out_handle)

创建esp_timer实例。备注使用完计时器后,使用esp_timer_delete功能将其删除。参数create_args– 指向具有计时器创建参数的结构的指针。不由库保存,可以在堆栈上分配。out_handle–[out]输出,指向esp_timer_handle_t变量的指针,该变量将保存创建的计时器句柄。返回关于成功的ESP_OKESP_ERR_INVALID_ARG某些create_args是否无效ESP_ERR_INVALID_STATE库是否尚未初始化esp_timerESP_ERR_NO_MEM内存分配失败

esp_err_t esp_timer_start_once(esp_timer_handle_t小时,uint64_t timeout_us)

启动单次计时器。调用此函数时,计时器不应运行。参数计时器 – 使用esp_timer_create创建的计时器句柄timeout_us– 计时器超时,以相对于当前时刻的微秒为单位返回关于成功的ESP_OKESP_ERR_INVALID_ARG句柄是否无效ESP_ERR_INVALID_STATE计时器是否已运行

esp_err_t esp_timer_start_periodic(esp_timer_handle_t定时器,uint64_t周期)

启动定期计时器。调用此函数时,计时器不应运行。此函数将启动计时器,该计时器将触发每“周期”微秒。参数计时器 – 使用esp_timer_create创建的计时器句柄周期 – 计时器周期,以微秒为单位返回关于成功的ESP_OKESP_ERR_INVALID_ARG句柄是否无效ESP_ERR_INVALID_STATE计时器是否已运行

esp_err_t esp_timer_stop(esp_timer_handle_t 小时)

停止计时器。此函数停止之前使用 esp_timer_start_once 或 esp_timer_start_periodic 启动的计时器。参数计时器 – 使用esp_timer_create创建的计时器句柄返回关于成功的ESP_OKESP_ERR_INVALID_STATE计时器是否未运行

esp_err_t esp_timer_delete(esp_timer_handle_t小时))

删除esp_timer实例。删除前必须停止计时器。已过期的单次计时器不需要停止。参数计时器 – 使用 esp_timer_create 分配的计时器句柄返回关于成功的ESP_OKESP_ERR_INVALID_STATE计时器是否正在运行

int64_t esp_timer_get_time(无效)

获取自启动以来的时间(以微秒为单位)。返回自基础计时器启动以来的微秒数

使用方法流程:

单个计时器由esp_timer_handle_t类型表示。计时器有一个与之关联的回调函数。每次计时器经过时,都会从任务中调用此回调函数。esp_timer

请注意,调用 esp_timer_start_once() 或 esp_timer_start_periodic()  时计时器不得运行。要重新启动正在运行的计时器,请先调用 esp_timer_stop(), 然后调用其中一个启动函数。

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/timer.h"
#include "esp_timer.h"

#define gpio_pin 25

esp_timer_handle_t esp_timer_handle_t1 = 0;


/*定时器中断函数*/
void esp_timer_cb(void *arg){
    /*设置gpio输出高低电平*/
    gpio_set_level(gpio_pin, 1-gpio_get_level(gpio_pin));
}

void gpio_init(void){
    gpio_config_t io_conf;
    //禁止中断
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    //输入输出模式
    io_conf.mode = GPIO_MODE_INPUT_OUTPUT;
    //配置要设置的引脚
    io_conf.pin_bit_mask = (unsigned long long)1<<gpio_pin;
    //禁止下拉
    io_conf.pull_down_en = 0;
    //禁止上拉
    io_conf.pull_up_en = 0;
    //配置gpio(不设置上下拉默认输出低电平)
    gpio_config(&io_conf);

}

void app_main(void)
{ 
    gpio_init();//初始化gpio

    //定时器结构体初始化
    esp_timer_create_args_t esp_timer_create_args_t1 = {
        .callback = &esp_timer_cb, //定时器回调函数
        .arg = NULL, //传递给回调函数的参数
        .name = "esp_timer" //定时器名称
    };

    /*创建定时器*/                      //初始化参数              //定时器句柄,用于后期对定时器做其它操作
    esp_err_t err = esp_timer_create(&esp_timer_create_args_t1, &esp_timer_handle_t1);
    /*以循环方式启动定时器*/           //定时器句柄       //us级定时,1000*1000就是1s
    err = esp_timer_start_periodic(esp_timer_handle_t1, 1000 * 1000);
    /*单次启动*/
    //err = esp_timer_start_once(esp_timer_handle_t1, 1000 * 1000)
    if(err == ESP_OK){
        printf("ok!\r\n");
    }
}

三、计数器函数

xTimerStart(xTimer,xTicksToWait)

BaseType_t xTimerStart( TimerHandle_t xTimer, TickType_t xTicksToWait );计时器功能由定时服务/守护程序任务提供。许多公共 FreeRTOS 计时器 API 函数通过称为计时器命令队列的队列将命令发送到定时服务任务。timer 命令队列是内核本身的专用代码,应用程序代码无法直接访问。计时器命令队列的长度由configTIMER_QUEUE_LENGTH配置常量设置。xTimerStart() 启动以前使用 xTimerCreate() API 函数创建的计时器。如果计时器已经启动并且已经处于活动状态,则 xTimerStart() 具有与 xTimerReset() API 函数等效的功能。启动计时器可确保计时器处于活动状态。如果计时器同时未停止、删除或重置,则在调用 xTimerStart() 后,与计时器关联的回调函数将调用“n”个时钟周期,其中“n”是计时器定义的时间段。在调度程序启动之前调用 xTimerStart() 是有效的,但是当这样做时,计时器在调度程序启动之前不会实际启动,并且计时器到期时间将相对于调度程序启动的时间,而不是相对于调用 xTimerStart() 的时间。configUSE_TIMERS配置常量必须设置为 1 才能使用 xTimerStart()。用法示例:请参阅 xTimerCreate() API 函数示例使用场景。

参数xTimer– 正在启动/重新启动的计时器的句柄。xTicksToWait– 指定调用任务应保持在“已阻止”状态以等待启动命令成功发送到计时器命令队列的时间(以刻度为单位),如果调用 xTimerStart() 时队列已满。如果在调度程序启动之前调用了 xTimerStart(),则忽略 xTicksToWait。

返回如果启动命令无法发送到计时器命令队列,即使 xTicksToWait 时钟周期已过去,也将返回 pdFAIL。如果命令已成功发送到计时器命令队列,将返回 pdPASS。实际处理命令的时间将取决于定时服务/守护程序任务相对于系统中其他任务的优先级,尽管计时器到期时间相对于实际调用 xTimerStart() 的时间。定时服务/守护程序任务优先级由configTIMER_TASK_PRIORITY配置常量设置。

xTimerStop(xTimer,xTicksToWait)

BaseType_txTimerStop( TimerHandle_t xTimer, TickType_t xTicksToWait );计时器功能由定时服务/守护程序任务提供。许多公共 FreeRTOS 计时器 API 函数通过称为计时器命令队列的队列将命令发送到定时服务任务。timer 命令队列是内核本身的专用代码,应用程序代码无法直接访问。计时器命令队列的长度由configTIMER_QUEUE_LENGTH配置常量设置。xTimerStop() 停止以前使用 xTimerStart()、xTimerReset()、xTimerStartFromISR()、xTimerResetFromISR()、xTimerChangePeriod() 或 xTimerChangePeriodFromISR() API 函数启动的计时器。停止计时器可确保计时器不处于活动状态。configUSE_TIMERS配置常量必须设置为 1 才能使用xTimerStop()。用法示例:请参阅 xTimerCreate() API 函数示例使用场景。

参数xTimer– 正在停止的计时器的句柄。xTicksToWait– 指定调用任务应保持在“已阻止”状态以等待停止命令成功发送到计时器命令队列的时间(以刻度为单位),如果调用xTimerStop() 时队列已满。如果在调度程序启动之前调用了 xTimerStop(),则忽略 xTicksToWait。

返回如果停止命令无法发送到计时器命令队列,即使 xTicksToWait 时钟周期已经过去了,也会返回 pdFAIL。如果命令已成功发送到计时器命令队列,将返回 pdPASS。实际处理命令的时间将取决于定时服务/守护程序任务相对于系统中其他任务的优先级。定时服务/守护程序任务优先级由configTIMER_TASK_PRIORITY配置常量设置。

xTimerDelete(xTimer,xTicksToWait)

BaseType_t xTimerDelete( TimerHandle_t xTimer, TickType_t xTicksToWait );计时器功能由定时服务/守护程序任务提供。许多公共 FreeRTOS 计时器 API 函数通过称为计时器命令队列的队列将命令发送到定时服务任务。timer 命令队列是内核本身的专用代码,应用程序代码无法直接访问。计时器命令队列的长度由configTIMER_QUEUE_LENGTH配置常量设置。xTimerDelete() 删除以前使用 xTimerCreate() API 函数创建的计时器。configUSE_TIMERS配置常量必须设置为 1 才能使用 xTimerDelete()。用法示例:请参阅 xTimerChangePeriod() API 函数示例使用场景。

参数xTimer– 要删除的计时器的句柄。xTicksToWait– 指定调用任务应保持在“已阻止”状态以等待删除命令成功发送到计时器命令队列的时间(以刻度为单位),前提是调用 xTimerDelete() 时队列已满。如果在调度程序启动之前调用 xTimerDelete(),则忽略 xTicksToWait。

返回如果删除命令无法发送到计时器命令队列,即使 xTicksToWait 时钟周期已经过去了,也会返回 pdFAIL。如果命令已成功发送到计时器命令队列,将返回 pdPASS。实际处理命令的时间将取决于定时服务/守护程序任务相对于系统中其他任务的优先级。定时服务/守护程序任务优先级由configTIMER_TASK_PRIORITY配置常量设置。

xTimerReset(xTimer,xTicksToWait)

BaseType_t xTimerReset( TimerHandle_t xTimer, TickType_t xTicksToWait );计时器功能由定时服务/守护程序任务提供。许多公共 FreeRTOS 计时器 API 函数通过称为计时器命令队列的队列将命令发送到定时服务任务。timer 命令队列是内核本身的专用代码,应用程序代码无法直接访问。计时器命令队列的长度由configTIMER_QUEUE_LENGTH配置常量设置。xTimerReset() 重新启动以前使用 xTimerCreate() API 函数创建的计时器。如果计时器已经启动并且已经处于活动状态,则 xTimerReset() 将导致计时器重新评估其到期时间,使其相对于调用 xTimerReset() 的时间。如果计时器处于休眠状态,则 xTimerReset() 具有与 xTimerStart() API 函数等效的功能。重置计时器可确保计时器处于活动状态。如果计时器没有同时停止、删除或重置,则在调用 xTimerReset() 后,与计时器关联的回调函数将被称为 'n' 刻度,其中 'n' 是计时器定义的时间段。在调度程序启动之前调用 xTimerReset() 是有效的,但是当这样做时,计时器在调度程序启动之前不会真正启动,并且计时器到期时间将相对于调度程序启动的时间,而不是相对于调用 xTimerReset() 的时间。configUSE_TIMERS配置常量必须设置为 1 才能使用 xTimerReset()。

参数

xTimer– 正在重置/启动/重新启动的计时器的句柄。xTicksToWait– 指定调用任务应保持在“已阻止”状态以等待重置命令成功发送到计时器命令队列的时间(以刻度为单位),如果在调用 xTimerReset() 时队列已满。如果在调度程序启动之前调用了 xTimerReset(),则忽略 xTicksToWait。

返回

如果重置命令无法发送到计时器命令队列,即使 xTicksToWait 时钟周期已经过去了,也会返回 pdFAIL。如果命令已成功发送到计时器命令队列,将返回 pdPASS。实际处理命令的时间将取决于定时服务/守护程序任务相对于系统中其他任务的优先级,尽管计时器到期时间相对于实际调用 xTimerStart() 的时间。定时服务/守护程序任务优先级由configTIMER_TASK_PRIORITY配置常量设置。

用法示例:

// When a key is pressed, an LCD back-light is switched on.  If 5 seconds pass
 // without a key being pressed, then the LCD back-light is switched off.  In
 // this case, the timer is a one-shot timer.

 TimerHandle_t xBacklightTimer = NULL;

 // The callback function assigned to the one-shot timer.  In this case the
 // parameter is not used.
 void vBacklightTimerCallback( TimerHandle_t pxTimer )
 {
     // The timer expired, therefore 5 seconds must have passed since a key
     // was pressed.  Switch off the LCD back-light.
     vSetBacklightState( BACKLIGHT_OFF );
 }

 // The key press event handler.
 void vKeyPressEventHandler( char cKey )
 {
     // Ensure the LCD back-light is on, then reset the timer that is
     // responsible for turning the back-light off after 5 seconds of
     // key inactivity.  Wait 10 ticks for the command to be successfully sent
     // if it cannot be sent immediately.
     vSetBacklightState( BACKLIGHT_ON );
     if( xTimerReset( xBacklightTimer, 100 ) != pdPASS )
     {
         // The reset command was not executed successfully.  Take appropriate
         // action here.
     }

     // Perform the rest of the key processing here.
 }

 void main( void )
 {
 int32_t x;

     // Create then start the one-shot timer that is responsible for turning
     // the back-light off if no keys are pressed within a 5 second period.
     xBacklightTimer = xTimerCreate( "BacklightTimer",           // Just a text name, not used by the kernel.
                                     ( 5000 / portTICK_PERIOD_MS), // The timer period in ticks.
                                     pdFALSE,                    // The timer is a one-shot timer.
                                     0,                          // The id is not used by the callback so can take any value.
                                     vBacklightTimerCallback     // The callback function that switches the LCD back-light off.
                                   );

     if( xBacklightTimer == NULL )
     {
         // The timer was not created.
     }
     else
     {
         // Start the timer.  No block time is specified, and even if one was
         // it would be ignored because the scheduler has not yet been
         // started.
         if( xTimerStart( xBacklightTimer, 0 ) != pdPASS )
         {
             // The timer could not be set into the Active state.
         }
     }

     // ...
     // Create tasks here.
     // ...

     // Starting the scheduler will start the timer running as it has already
     // been set into the active state.
     vTaskStartScheduler();

     // Should not reach here.
     for( ;; );
 }
/*定时器中断函数*/
void esp_timer_cb(void *arg){
    printf("TIME start \n");
}
void key_createTimer(){
    TimerHandle_t xTimerBPL ;
    xTimerBPL = xTimerCreate("xTimerCreate"
                                    ,(BPL_CHECK_TIME/portTICK_PERIOD_MS)  //毫秒
                                    ,pdTRUE //周期执行
                                    ,( void * ) BPL_pvTimerID //执行ID
                                    ,esp_timer_cb);
    if( xTimerBPL == NULL ) ESP_LOGE(TAG,"%s",esp_err_to_name(-1));
    if( xTimerStart( xTimerBPL, 0 ) != pdPASS ) ESP_LOGE(TAG,"%s",esp_err_to_name(-1));
}