ESP定时器+消息队列的一些代码总结,记录一下

做这个实验的时候,因为之前有STM32定时器的经验,所以基本上只是复习一下。

但还是发现不懂的地方很多,感觉以前学的一点也不扎实。

定时器+消息队列的思路就是,将定时器的每一次中断所产生的信息打印出来,然后放到任务里去处理,这样可以很好的解决中断的阻塞问题


那么定时器到底跟延时有什么区别呢?

  • 延时函数需要占用CPU的使用权,正在延时的时候其他任务没有CPU的使用权就会拖慢执行效率。
  • 定时器是不需要占用CPU的使用权的,它是独立自己运行的。

这里参考了这篇文章:http://t.csdn.cn/e8EIb


做实验的过程中,基本就是参考ESP的编程手册,以及FreeRTOS编程手册。

查看ESP32的数据手册。

定时器有两组,每组有两个。

由定时器+消息队列简单写一个测试的框架。

代码如下:(都有注释!)

#include <stdio.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "esp_log.h"
#include "freertos/queue.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include "esp_log.h"


#include "ds_timer.h"

#define TIMER_DIVIDER           16     //分频器,具体看芯片手册
#define TIMER_SCALE             (TIMER_BASE_CLK/ TIMER_DIVIDER/1000) //将计数值转换为毫秒
#define TIMER_INTERVAL0_SEC     (10)   //每10ms触发一次中断
#define TEST_WITH_RELOAD         1     //设置超时自动重装载               


static const char *TAG = "MAIN APP";
/*
*定义一个要传递的结构体,主要是传递一下每次中断发出的消息
*/
typedef struct {
    uint64_t timer_minute_count;
    uint64_t timer_second_count;
}timer_event_t;


timer_event_t g_timer_event;//结构体实例化

xQueueHandle  timer_queue;


void IRAM_ATTR timer_group0_isr(void *para)
{
    timer_spinlock_take(TIMER_GROUP_0);//中断函数里用自旋锁

    int timer_idx = (int) para;//获取是定时器0,还是定时器1


    //准备中断中要发的事件数据
    //简单定义一个事件
    timer_event_t evt;

    timer_group_clr_intr_status_in_isr(TIMER_GROUP_0,timer_idx);//获取定时器0组定时器的中断状态
    /*
    *这里可以进行一些操作
    *对结构体进行复制等等
    */

    timer_group_enable_alarm_in_isr(TIMER_GROUP_0,timer_idx);//使能报警器,下一次继续触发

    //发送事件数据
    xQueueSendFromISR(timer_queue,&evt,NULL);
    timer_spinlock_give(TIMER_GROUP_0);//释放自旋锁

}



static void example_tg0_timer_init(int timer_idx,bool auto_reload,double timer_interval_sec)//初始化
{
    //配置定时器

    timer_config_t config ={

        .divider = TIMER_DIVIDER,      //分频
        .counter_dir = TIMER_COUNT_UP, //加计数器
        .counter_en = TIMER_PAUSE,     //计数器使能
        .alarm_en = TIMER_ALARM_EN,    //报警器使能
        .auto_reload = auto_reload,    //自动重载首个计数值
    };
    timer_init(TIMER_GROUP_0,timer_idx,&config);//定时器初始化
    timer_set_counter_value(TIMER_GROUP_0,timer_idx,0x00000000ULL);//设置初始值为0
    
    //设置报警
    timer_set_alarm_value(TIMER_GROUP_0,timer_idx,timer_interval_sec * TIMER_SCALE);//10ms一次报警
    timer_enable_intr(TIMER_GROUP_0,timer_idx);//使能定时器中断
    timer_isr_register(TIMER_GROUP_0,timer_idx,timer_group0_isr,
                       (void*)timer_idx,ESP_INTR_FLAG_IRAM,NULL); //注册中断函数

    timer_start(TIMER_GROUP_0,timer_idx);//开启定时器
}


static void timer_example_evt_task(void *arg)//任务函数
{

    while (1) {
        timer_event_t evt;
        xQueueReceive(timer_queue, &evt, portMAX_DELAY);//接受消息
        g_timer_event.timer_minute_count ++;//接受一次加1
        //60s 计算一次 刷新时间
        if(g_timer_event.timer_minute_count >= 6000){
            g_timer_event.timer_minute_count = 0;
        }
        g_timer_event.timer_second_count ++;
        //1s计算一次,10ms*100
        if(g_timer_event.timer_second_count >= 100){
            g_timer_event.timer_second_count = 0;
            ESP_LOGI(TAG,"timer is run");
        }
    }


}

/*
例程实现
*/
void ds_timer_init(void){
    g_timer_event.timer_minute_count = 0;
    g_timer_event.timer_second_count = 0;
    timer_queue = xQueueCreate(10,sizeof(timer_event_t));//动态创建消息队列,记得freertos.h里配置一下
    example_tg0_timer_init(TIMER_0,TEST_WITH_RELOAD,TIMER_INTERVAL0_SEC);//初始化定时器
    xTaskCreate(timer_example_evt_task,"timer_evt_task",2048,NULL,5,NULL);//创建任务

}

这样,我们定时器+消息队列的初始化就完成了,之后可以在其他函数里进行调用,因为最后都封装到ds_timer_init里面了。

然后我就放在我的板子上测试了一下。

设置的是1000ms也就是1s打印一下“timer is run”这句话,可以看到是成功的。

虽然说的比较简单,但是我搞了一天....

把定时器,消息队列以及其他各种知识复习一遍花的时间比较多,总体来说成功了。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值