【ESP32】IDF配置ESPTIMER定时器

概述

        ESP32-S3 芯片内置一组 52 位系统定时器。该定时器可用于生成操作系统所需的滴答定时 中断,也可用作普通定时器生成周期或单次延时中断。

定时器的功能

       定时器的作用包括但不限于: 

  1. 执行定时任务:定时器常用于周期性执行特定任务。例如,若需要每500毫秒执行某 项任务,定时器能够精准地满足这一需求。
  2. 时间测量:定时器能够精确测量时间,无论是代码段的执行时间还是事件发生的间隔 时间,都能通过定时器进行准确的计量。
  3. 精确延时:对于需要微秒级精度的延时场景,定时器能够提供可靠的解决方案,确保 延时的精确性。
  4. PWM信号生成:通过定时器的精确控制,我们可以生成PWM(脉宽调制)信号,这 对于驱动电机、调节LED亮度等应用至关重要。
  5. 事件触发与监控:定时器不仅用于触发中断,实现事件驱动的逻辑,还可用于实现看 门狗功能,监控系统状态,并在必要时进行复位操作,确保系统的稳定运行。

ESP32-S3的定时器整体框架介绍

        系统定时器内置两个计数器UNIT0和UNIT1(如图14.1.1中①所示)以及三个比较器COMP0、COMP1、COMP2(如图14.1.1中②所示)。比较器用于监控计数器的计数值是否达到报警值。

①计数器

        UNIT0、UNIT1均为ESP32-S3系统定时器内置的52位计数器。计数器使用XTAL_CLK作 为时钟源(40MHz)。XTAL_CLK经分频后,在一个计数周期生成频率为fXTAL_CLK/3的时钟信 号,然后在另一个计数周期生成频率为 fXTAL_CLK/2 的时钟信号。因此,计数器使用的时钟 CNT_CLK,其实际平均频率为fXTAL_CLK/2.5,即16MHz,见图14.1.2。每个CNT_CLK时钟 周期,计数递增1/16µs,即16个周期递增1µs。 用户可以通过配置寄存器SYSTIMER_CONF_REG中下面三个位来控制计数器 UNITn,这 三个位分别是:

①:SYSTIMER_TIMER_UNITn_WORK_EN

②:SYSTIMER_TIMER_UNITn_CORE0_STALL_EN

③:SYSTIMER_TIMER_UNITn_CORE1_STALL_EN

关于这三的配置请参考

https://www.espressif.com.cn/sites/default/files/documentation/esp32-s3_technical_reference_manual_cn.pdf#iomuxgpio

②比较器

        COMP0、COMP1、COMP2均为 ESP32-S3系统定时器内置的 52位比较器。比较器同样使 用XTAL_CLK作为时钟源(40MHz)。

        图14.1.2展示了系统定时器生成报警的过程。在上述过程中用到一个计数器(Timer Countern) 和一个比较器(Timer Comparatorx),比较器将根据比较结果,生成报警中断。

函数解析

必要的头文件 :

#include "esp_timer.h"

 特别注意!!!!!!!!!!!!!

一定一定要在CMakeLists.txt中的set(requires中添加esp_timer;如下图,不然一定会报错,这一点很多教程都没说!!!查错查了很久才找到!!!!

创建事件函数:

esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args, 
                            esp_timer_handle_t* out_handle);


入参

    create_args          //指向arg外设结构体的指针 

    esp_tim_handle       //指定使能的中断 


例程:

     esp_timer_handle_t esp_tim_handle;                      /* 定时器回调函数句柄 */

    /* 定义一个定时器结构体 */
    esp_timer_create_args_t tim_periodic_arg = {
        .callback = &esptim_callback,                       /* 设置回调函数 */
        .arg = NULL,                                        /* 不携带参数 */
    };

    esp_timer_create(&tim_periodic_arg, &esp_tim_handle);   /* 创建一个事件 */


/**
 * @brief       定时器回调函数
 * @param       arg: 不携带参数
 * @retval      无
 */
void esptim_callback(void *arg)
{
   //用户程序
}

 esp_timer_create_args_t :结构体成员变量描述

esp_timer_create_args_t 是一个结构体

typedef struct {
    esp_timer_cb_t callback;        //定时器在周期内调用的函数。

    void* arg;                      //一个指针类型,将参数传递给回调函数。
                                    注:一般设置为NULL,即不携带参数

    esp_timer_dispatch_t dispatch_method;   //从task或ISR调用回调。

    const char* name;               //定时器名称,用于ESPTIMER转储功能。

    bool skip_unhandled_events;     //跳过周期计时器的未处理事件。

} esp_timer_create_args_t;

每个周期内触发一次 

esp_err_t IRAM_ATTR esp_timer_start_periodic(esp_timer_handle_t timer, 
                                              uint64_t period_us);


入参

    timer        //使用esp_timer_create创建的定时器句柄 

    period_us    //计时器周期,以微秒为单位


例程:

    uint32_t tps =  1000000;

    esp_timer_start_periodic(esp_tim_handle, tps);          /* 每周期内触发一次 */

/**
 * @brief       初始化高精度定时器(ESP_TIMER)
 * @param       tps: 定时器周期,以微妙为单位(μs),以一秒为定时器周期来执行一次定时器中断,
 *                   那此处tps = 1s = 1000000μs
 * @retval      无
 */

例程 

        .H文件


#ifndef __ESPTIM_H_
#define __ESPTIM_H_

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "led.h"


/* 函数声明 */
void esptim_int_init(uint64_t tps);                 /* 初始化初始化高分辨率定时器 */
void esptim_callback(void *arg);                    /* 定时器回调函数 */

#endif

        .C文件 


#include "esptim.h"


/**
 * @brief       初始化高精度定时器(ESP_TIMER)
 * @param       tps: 定时器周期,以微妙为单位(μs),以一秒为定时器周期来执行一次定时器中断,
 *                   那此处tps = 1s = 1000000μs
 * @retval      无
 */

void esptim_int_init(uint64_t tps)
{
    esp_timer_handle_t esp_tim_handle;                      /* 定时器回调函数句柄 */

    /* 定义一个定时器结构体 */
    esp_timer_create_args_t tim_periodic_arg = {
        .callback = &esptim_callback,                       /* 设置回调函数 */
        .arg = NULL,                                        /* 不携带参数 */
    };

    esp_timer_create(&tim_periodic_arg, &esp_tim_handle);   /* 创建一个事件 */
    esp_timer_start_periodic(esp_tim_handle, tps);          /* 每周期内触发一次 */
}

/**
 * @brief       定时器回调函数
 * @param       arg: 不携带参数
 * @retval      无
 */
void esptim_callback(void *arg)
{
    LED_TOGGLE();
}

main.C 


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "led.h"
#include "esptim.h"


/**
 * @brief       程序入口
 * @param       无
 * @retval      无
 */
void app_main(void)
{
    esp_err_t ret;
    
    ret = nvs_flash_init();         /* 初始化NVS */

    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND)
    {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    
    led_init();                     /* 初始化LED */
    esptim_int_init(1000000);       /* 初始化高分辨率定时器,此处设置定时器周期为1秒,
                                       但该函数事宜微妙为单位进行计算,
                                       故而1秒钟换算为1000000微秒 */
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值