103-ESP32_SDK開發-硬件定時器timer


<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/LearnESP32" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>

 

說明

硬件定時器有兩組,0和1. 然后每一組都有兩個定時器,0和1.

所以共有四個定時器

 

什么是定時器?定時器具體是怎么到了時間進去中斷的?

定時器里面是啥?就是個計數器.定時器的時鍾,就是計數器的時鍾.假設計數器的時鍾是1Hz

假設設置了計數器計數到1的時候就進入中斷,那么就是每隔1S進入中斷了.

 

假設計數器的時鍾是80MHz,我想每隔1ms進入一次中斷,我應該設置計數值是多少呢???

計數器每記一次需要 1/80000000 秒  也就是  1/80000 毫秒  

要記到80000次才到1ms

想定時多少毫秒,設置初值可以寫成     X*(80000000/1000)  X就是要定時的ms數

 

假設時鍾分頻了8,那么現在就是10MHz

我想每隔1ms進入一次中斷,我應該設置計數值是多少呢???

計數器記一次是 1/10000000 秒  也就是  1/10000 毫秒  

需要多少個 1/10000 毫秒  才能到1ms呢?   10000次

想定時多少毫秒,設置初值可以寫成     X*(80000000/分頻系數/1000)   X就是要定時的ms數

想定時多少微秒,設置初值可以寫成     X*(80000000/分頻系數)   X就是要定時的us數

 

使用定時器分組0的0號定時器產生1S中斷

 

 

 

 

 

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

#define gpio_pin 25


/*定時器中斷函數
因為設置中斷的時候,中斷設置的 ESP_INTR_FLAG_IRAM 所以中斷函數需要加 IRAM_ATTR
*/
void IRAM_ATTR timer_group0_isr(void *para)
{
    //獲取定時器分組0中的哪一個定時器產生了中斷
    uint32_t timer_intr = timer_group_get_intr_status_in_isr(TIMER_GROUP_0);
    if (timer_intr & TIMER_INTR_T0) {//定時器0分組的0號定時器產生中斷
        /*清除中斷*/
        timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_0);
        /*重新使能定時器中斷*/    
        timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_0);
    }

    /*設置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

    /*設置定時器初始化參數*/
    timer_config_t config = {
        .divider = 8,//分頻系數[2-65535]
        .counter_dir = TIMER_COUNT_UP,//計數方式是向上計數
        .counter_en = TIMER_PAUSE,//調用timer_init函數以后不啟動計數,調用timer_start時才開始計數
        .alarm_en = TIMER_ALARM_EN,//到達計數值啟動報警(計數值溢出,進入中斷)
        .auto_reload = 1,//自動重新裝載預裝值
    };
    /*初始化定時器;TIMER_GROUP_0(定時器分組0); TIMER_0(分組0中的0號定時器)*/
    timer_init(TIMER_GROUP_0, TIMER_0, &config);

    /*設置定時器預裝值,0*/
    timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL);
    /*設置報警閾值*/ // 1000[定時1000ms]*(TIMER_BASE_CLK[定時器時鍾]/8[分頻系數]/1000[想延時ms級別所以除以1000]),
    timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, 1000*(TIMER_BASE_CLK/8/1000) );
    /*使能定時器中斷*/
    timer_enable_intr(TIMER_GROUP_0, TIMER_0);
    /*注冊定時器中斷函數*/
    timer_isr_register(TIMER_GROUP_0, TIMER_0, 
        timer_group0_isr,//定時器回調函數
        (void *) TIMER_0, //傳遞給定時器回調函數的參數
        ESP_INTR_FLAG_IRAM, //把中斷放到 IRAM 中
        NULL //調用成功以后返回中斷函數的地址,一般用不到
    );
    /*啟動定時器*/
    timer_start(TIMER_GROUP_0, TIMER_0);
}

 

下載進去之后,會看到led每隔1S閃耀

 

 

 

 

 

如果想讓定時器是一次性的,可以把重新使能屏蔽

 

 

 

 

如果想使用分組1  

TIMER_GROUP_1

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM