精华内容
下载资源
问答
  • windows下实现毫秒定时器实现,非MFC中的定时器。采用windows下的消息实现
  • android 定时器实现

    2011-06-23 12:03:58
    android 定时器实现 保证一看就会
  • 游戏定时器实现

    2012-12-13 22:43:02
    一个游戏编程当中用到的简易定时器实现
  • 时间轮定时器java实现

    2019-02-22 16:20:16
    用java实现最小堆的定时器,和用时间轮实现定时器,可以运行,简单的实现
  • 软件定时器实现

    千次阅读 2019-07-20 09:18:01
    1.什么是软件定时器 ...但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。 2.软件定时器实现原理 在Linux,uC/OS,FreeRTOS等操作系...

    1.什么是软件定时器
    软件定时器是用程序模拟出来的定时器,可以由一个硬件定时器模拟出成千上万个软件定时器,这样程序在需要使用较多定时器的时候就不会受限于硬件资源的不足,这是软件定时器的一个优点,即数量不受限制。但由于软件定时器是通过程序实现的,其运行和维护都需要耗费一定的CPU资源,同时精度也相对硬件定时器要差一些。


    2.软件定时器的实现原理
    在Linux,uC/OS,FreeRTOS等操作系统中,都带有软件定时器,原理大同小异。典型的实现方法是:通过一个硬件定时器产生固定的时钟节拍,每次硬件定时器中断到,就对一个全局的时间标记加一,每个软件定时器都保存着到期时间,程序需要定期扫描所有运行中的软件定时器,将各个到期时间与全局时钟标记做比较,以判断对应软件定时器是否到期,到期则执行相应的回调函数,并关闭该定时器。

    以上是单次定时器的实现,若要实现周期定时器,即到期后接着重新定时,只需要在执行完回调函数后,获取当前时间标记的值,加上延时时间作为下一次到期时间,继续运行软件定时器即可。


    3.基于STM32的软件定时器
    3.1 时钟节拍
    软件定时器需要一个硬件时钟源作为基准,这个时钟源有一个固定的节拍(可以理解为秒针的每次滴答),用一个32位的全局变量tickCnt来记录这个节拍的变化:

    static volatile uint32_t tickCnt = 0;       //软件定时器时钟节拍
    1
    每来一个节拍就对tickCnt加一(记录滴答了多少下):

    /* 需在定时器中断内执行 */
    void tickCnt_Update(void)
    {
        tickCnt++;
    }

    一旦开始运行,tickCnt将不停地加一,而每个软件定时器都记录着一个到期时间,只要tickCnt大于该到期时间,就代表定时器到期了。

    3.2 数据结构
    软件定时器的数据结构决定了其执行的性能和功能,一般可分为两种:数组结构和链表结构。什么意思呢?这是(多个)软件定时器在内存中的存储方式,可以用数组来存,也可以用链表来存。

    两者的优劣之分就是两种数据结构的特性之分:数组方式的定时器查找较快,但数量固定,无法动态变化,数组大了容易浪费内存,数组小了又可能不够用,适用于定时事件明确且固定的系统;链表方式的定时器数量可动态增减,易造成内存碎片(如果没有内存管理),查找的时间开销相对数组大,适用于通用性强的系统,Linux,uC/OS,FreeRTOS等操作系统用的都是链表式的软件定时器。

    本文使用数组结构:

    static softTimer timer[TIMER_NUM];        //软件定时器数组
    1
    数组和链表是软件定时器整体的数据结构,当具体到单个定时器时,就涉及软件定时器结构体的定义,软件定时器所具有的功能与其结构体定义密切相关,以下是本文中软件定时器的结构体定义:

    typedef struct softTimer {
        uint8_t state;           //状态
        uint8_t mode;            //模式
        uint32_t match;          //到期时间
        uint32_t period;         //定时周期
        callback *cb;            //回调函数指针
        void *argv;              //参数指针
        uint16_t argc;           //参数个数
    }softTimer;

    定时器的状态共有三种,默认是停止,启动后为运行,到期后为超时。

    typedef enum tmrState {
        SOFT_TIMER_STOPPED = 0,  //停止
        SOFT_TIMER_RUNNING,      //运行
        SOFT_TIMER_TIMEOUT       //超时
    }tmrState;

    模式有两种:到期后就停止的是单次模式,到期后重新定时的是周期模式。

    typedef enum tmrMode {
        MODE_ONE_SHOT = 0,       //单次模式
        MODE_PERIODIC,           //周期模式
    }tmrMode;

    不管哪种模式,定时器到期后,都将执行回调函数,以下是该函数的定义,参数指针argv为void指针类型,便于传入不同类型的参数。

    typedef void callback(void *argv, uint16_t argc);
    1
    上述结构体中的模式state和回调函数指针cb是可选的功能,如果系统不需要周期执行的定时器,或者不需要到期后自动执行某个函数,可删除此二者定义。

    3.3 定时器操作
    3.3.1 初始化
    首先是软件定时器的初始化,对每个定时器结构体的成员赋初值,虽说static变量的初值为0,但个人觉得还是有必要保持初始化变量的习惯,避免出现一些奇奇怪怪的BUG。

    void softTimer_Init(void)
    {
        uint16_t i;
        for(i=0; i<TIMER_NUM; i++) {
            timer[i].state = SOFT_TIMER_STOPPED;
            timer[i].mode = MODE_ONE_SHOT;
            timer[i].match = 0;
            timer[i].period = 0;
            timer[i].cb = NULL;
            timer[i].argv = NULL;
            timer[i].argc = 0;
        }
    }

    3.3.2 启动
    启动一个软件定时器不仅要改变其状态为运行状态,同时还要告诉定时器什么时候到期(当前tickCnt值加上延时时间即为到期时间),单次定时还是周期定时,到期后执行哪个函数,函数的参数是什么,交代好这些就可以开跑了。

    void softTimer_Start(uint16_t id, tmrMode mode, uint32_t delay, callback *cb, void *argv, uint16_t argc)
    {
        assert_param(id < TIMER_NUM);
        assert_param(mode == MODE_ONE_SHOT || mode == MODE_PERIODIC);
        
        timer[id].match = tickCnt_Get() + delay;
        timer[id].period = delay;
        timer[id].state = SOFT_TIMER_RUNNING;
        timer[id].mode = mode;
        timer[id].cb = cb;
        timer[id].argv = argv;
        timer[id].argc = argc;
    }

    上面函数中的assert_param()用于参数检查,类似于库函数assert()。

    3.3.3 更新
    本文中软件定时器有三种状态:停止,运行和超时,不同的状态做不同的事情。停止状态最简单,啥事都不做;运行状态需要不停地检查有没有到期,到期就执行回调函数并进入超时状态;超时状态判断定时器的模式,如果是周期模式就更新到期时间,继续运行,如果是单次模式就停止定时器。这些操作都由一个更新函数来实现:

    void softTimer_Update(void)
    {
        uint16_t i;
        
        for(i=0; i<TIMER_NUM; i++) {
          switch (timer[i].state) {
              case SOFT_TIMER_STOPPED:
                  break;
            
              case SOFT_TIMER_RUNNING:
                  if(timer[i].match <= tickCnt_Get()) {
                      timer[i].state = SOFT_TIMER_TIMEOUT;
                      timer[i].cb(timer[i].argv, timer[i].argc);       //执行回调函数
                  }
                  break;
                
              case SOFT_TIMER_TIMEOUT:
                  if(timer[i].mode == MODE_ONE_SHOT) {
                      timer[i].state = SOFT_TIMER_STOPPED;
                  } else {
                      timer[i].match = tickCnt_Get() + timer[i].period;
                      timer[i].state = SOFT_TIMER_RUNNING;
                  }
                  break;
            
              default:
                  printf("timer[%d] state error!\r\n", i);
                  break;
          }
      }
    }

    3.3.4 停止
    如果定时器跑到一半,想把它停掉,就需要一个停止函数,操作很简单,改变目标定时器的状态为停止即可:

    void softTimer_Stop(uint16_t id)
    {
        assert_param(id < TIMER_NUM);
        timer[id].state = SOFT_TIMER_STOPPED;
    }

    3.3.5 读状态
    又如果想知道一个定时器是在跑着呢还是已经停下来?也很简单,返回它的状态:

    uint8_t softTimer_GetState(uint16_t id)
    {
        return timer[id].state;
    }

    或许这看起来很怪,为什么要返回,而不是直接读?别忘了在前面3.2节中定义的定时器数组是个静态全局变量,该变量只能被当前源文件访问,当外部文件需要访问它的时候只能通过函数返回,这是一种简单的封装,保持程序的模块化。

    3.4 测试
    最后,当然是来验证一下我们的软件定时器有没达到预想的功能。定义三个定时器:定时器TMR_STRING_PRINT只执行一次,1s后在串口1打印一串字符;定时器TMR_TWINKLING为周期定时器,周期为0.5s,每次到期都将取反LED0的状态,实现LED0的闪烁;定时器TMR_DELAY_ON执行一次,3s后点亮LED1,跟第一个定时器不同的是,此定时器的回调函数是个空函数nop(),点亮LED1的操作通过主循环中判断定时器的状态来实现,这种方式在某些场合可能会用到。

    static uint8_t data[] = {1,2,3,4,5,6,7,8,9,0};

    int main(void)
    {
        USART1_Init(115200);
        TIM4_Init(TIME_BASE_MS);
        TIM4_NVIC_Config();
        LED_Init();
        
        printf("I just grabbed a spoon.\r\n");
        
        softTimer_Start(TMR_STRING_PRINT, MODE_ONE_SHOT, 1000, stringPrint, data, 5);
        softTimer_Start(TMR_TWINKLING, MODE_PERIODIC, 500, LED0_Twinkling, NULL, 0);
        softTimer_Start(TMR_DELAY_ON, MODE_ONE_SHOT, 3000, nop, NULL, 0);
        
        while(1) {
            softTimer_Update();
            if(softTimer_GetState(TMR_DELAY_ON) == SOFT_TIMER_TIMEOUT) {
                LED1_On();
            }
        }
    }
    --------------------- 
    作者:马可波罗包 
    来源:CSDN 
    原文:https://blog.csdn.net/qq_26904271/article/details/83833168 
    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • Android定时器功能实现方法
  • 一个定时器实现多个虚拟定时器具体代码实现
  • 定时器数码管实现.zip

    2020-04-19 11:53:42
    里面包括proteus电路和keil程序源码,通过51单片机内置的定时器寄存器TMOD实现简单的应用,适合刚刚学习单片机的小白,你用定时实现数码管0-9的1s加1循环
  • java定时器实现

    2009-11-05 16:27:38
    java定时器实现 本例依据Java自身提供的接口实现,通过监听器(Listener)和定时器(Timer)定时执行某个任务(Task)。
  • C#定时器实现

    千次阅读 2015-12-29 21:58:34
    C#定时器实现 本文主要介绍的是C#中定时器timer控件的实现。 首先拖动timer控件到界面,其中interval(毫秒)属性是设置中断时间的,enabled属性设置的是打开与关闭定时器。触发事件是Tick。 本文的演示例子是...
    C#定时器的实现

    本文主要介绍的是C#中定时器timer控件的实现。
    首先拖动timer控件到界面,其中interval(毫秒)属性是设置中断时间的,enabled属性设置的是打开与关闭定时器。触发事件是Tick。
    本文的演示例子是设置一个秒自加的程序:
            private void timer1_Tick(object sender, EventArgs e)
            {
                string b = a.ToString();
                label1.Text = b;
                a++;
            }
    
            private void button1_Click(object sender, EventArgs e)
            {
                timer1.Enabled = true ;
            }
    button1的触发键打开定时器,实现每秒自加的效果:




    源代码资源:http://download.csdn.net/detail/laozhuxinlu/9382834。
    展开全文
  • C++定时器功能实现

    万次阅读 2019-06-20 21:15:28
    ,并没有提供定时器功能函数,所以需要自己编写一个定时器功能的函数,Qt中可以通过信号与槽机制实现定时器功能,我们可以模仿类似的功能来实现。 方法一:使用计时器clock函数来实现循环 ①头文件 以及main() ...

    最近编写代码过程中,需要用到一个定时器的功能,我们知道c++只提供了一个头文件#include <ctime>,并没有提供定时器功能函数,所以需要自己编写一个定时器功能的函数,Qt中可以通过信号与槽机制实现定时器功能,我们可以模仿类似的功能来实现。

    方法一:使用计时器clock函数来实现循环  

    ①头文件 以及main()

    #include <iostream>
    #include <ctime>
    
    typedef void(*BACKCALLFUNC)(void *);
    
    int main(int argc, char *argv[])
    {
    	while (1)//不断循环
    	{
    		settimer(1, 2000, backcallfunc);
    	}
    	return 0;
    }

    ②定义一个setTimer函数:void settimer(unsigned int id, int msec, BACKCALLFUNC backcallfunc);

    参数:id(定时器编号)   msec(毫秒量)  backcallfunc(回调函数)

    void settimer(unsigned int id, int msec, BACKCALLFUNC backcallfunc)//方式一实现定时器
    {
    	if (msec < 0) //判断时间段是否满足 >=0
    	{
    		return;
    	}
    	clock_t start, finish;
    	start = clock();//计时函数
    	double totaltime = 0;//定义时间变量
    	while (1)
    	{
    		finish = clock();
    		totaltime = (double)(finish - start);
    		if (totaltime > msec)
    		{
    			backcallfunc(&totaltime);
    			break;
    		}
    	}
    }

    ③定义回调函数:void backcallfunc(void *arg);

    void backcallfunc(void *arg)
    {
    	cout << "go to timer1:" <<*(double *)arg<< endl;
    }

    通过这几个步骤就能实现简单的定时器功能,当需要执行其他动作时可以添加线程来灵活运用。

    方法二:通过windows编程下的SetTimer()来实现,这个可以查看函数的使用方法,在这里就不讲解了。

     

    以上的简单定时器功能,希望能帮助一些初学者。

     

     

    展开全文
  • 定时器实现大家应该都遇到过,最近在学习golang,所以下面这篇文章主要给大家介绍了关于golang time包下定时器实现方法,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。
  • 主要为大家详细介绍了Android控件Chronometer定时器实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • LwIP之定时器实现

    2013-12-21 20:01:21
    我们在学习LwIP时,总会看到关于TCP定时器的描述,但大多数...第四节,TCP定时器实现。本节针对我们所熟悉的TCP定时器,介绍了其添加、执行过程(未涉及TCP定时器的具体功能,因为这方面的资料网上已经非常多了)。
  • 自定义定时器类,VS2010开发,最小堆实现。设置定时间隔,可根据定时器ID删除定时器定时器到期回调
  • C++定时器实现

    千次阅读 2020-05-25 22:19:04
    如何实现定时器 下面是我自己实现定时器逻辑,源码链接最后会附上。 定时器中主要的数据结构 优先级任务队列:队列中存储任务,每个任务会添加时间戳,最近的时间戳的任务会先出队。 锁和条件变量:当有任务...

    个人认为一个完备的定时器需要有如下功能:

    • 在某一时间点执行某一任务
    • 在某段时间后执行某一任务
    • 重复执行某一任务N次,任务间隔时间T

    如何实现定时器

    下面是我自己实现的定时器逻辑,源码链接最后会附上。

    定时器中主要的数据结构

    • 优先级任务队列:队列中存储任务,每个任务会添加时间戳,最近的时间戳的任务会先出队。
    • 锁和条件变量:当有任务需要执行时,用于通知正在等待的线程从任务队列中取出任务执行。
    • 线程池:各个任务会放在线程池中执行
      下面是相关代码:
    class TimerQueue {
       public:
        struct InternalS {
            std::chrono::time_point<std::chrono::high_resolution_clock> time_point_;
            std::function<void()> func_;
            bool operator<(const InternalS& b) const { return time_point_ > b.time_point_; }
        };
        enum class RepeatedIdState { kInit = 0, kRunning = 1, kStop = 2 };
    
       private:
        std::priority_queue<InternalS> queue_;
        bool running_ = false;
        std::mutex mutex_;
        std::condition_variable cond_;
    
        wzq::ThreadPool thread_pool_;
    
        std::atomic<int> repeated_func_id_;
        wzq::ThreadSafeMap<int, RepeatedIdState> repeated_id_state_map_;
    };
    

    初始化

    在构造函数中初始化,主要是配置好内部的线程池,线程池中常驻的线程数目前设为4。
    关于线程池部分可以参考https://www.jianshu.com/p/41b7a1013907

    TimerQueue() : running_(true), thread_pool_(wzq::ThreadPool::ThreadPoolConfig{4, 4, 40, std::chrono::seconds(4)}) {
        repeated_func_id_.store(0);
    }
    

    如何开启定时器功能

    打开内部的线程池功能,用于执行放入定时器中的任务,同时新开一个线程,循环等待任务到来后送入线程池中执行。

    bool Run() {
        bool ret = thread_pool_.Start();
        if (!ret) {
            return false;
        }
        std::thread([this]() { RunLocal(); }).detach();
        return true;
    }
    
    void RunLocal() {
        while (running_) {
            std::unique_lock<std::mutex> lock(mutex_);
            if (queue_.empty()) {
                cond_.wait(lock);
                continue;
            }
            auto s = queue_.top();
            auto diff = s.time_point_ - std::chrono::high_resolution_clock::now();
            if (std::chrono::duration_cast<std::chrono::milliseconds>(diff).count() > 0) {
                cond_.wait_for(lock, diff);
                continue;
            } else {
                queue_.pop();
                lock.unlock();
                thread_pool_.Run(std::move(s.func_));
            }
        }
    }
    

    如何关闭定时器功能

    这里是使用running_标志位控制,标志位为false,调度线程的循环就会自动退出,就不会继续等待任务执行。

    void Stop() {
        running_ = false;
        cond_.notify_all();
    }
    

    如何在某一时间点执行任务

    根据时间戳构造InternalS,放入队列中

    template <typename F, typename... Args>
    void AddFuncAtTimePoint(const std::chrono::time_point<std::chrono::high_resolution_clock>& time_point, F&& f,
                            Args&&... args) {
        InternalS s;
        s.time_point_ = time_point;
        s.func_ = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        std::unique_lock<std::mutex> lock(mutex_);
        queue_.push(s);
        cond_.notify_all();
    }
    

    如何在某段时间后执行任务

    根据当前时间加上时间段构造出时间戳从而构造InternalS,放入队列中

    template <typename R, typename P, typename F, typename... Args>
    void AddFuncAfterDuration(const std::chrono::duration<R, P>& time, F&& f, Args&&... args) {
        InternalS s;
        s.time_point_ = std::chrono::high_resolution_clock::now() + time;
        s.func_ = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        std::unique_lock<std::mutex> lock(mutex_);
        queue_.push(s);
        cond_.notify_all();
    }
    

    如何循环执行任务

    首先为这个循环任务生成标识ID,外部可以通过ID来取消此任务继续执行,代码如下,内部以类似递归的方式循环执行任务。

    template <typename R, typename P, typename F, typename... Args>
    int AddRepeatedFunc(int repeat_num, const std::chrono::duration<R, P>& time, F&& f, Args&&... args) {
        int id = GetNextRepeatedFuncId();
        repeated_id_state_map_.Emplace(id, RepeatedIdState::kRunning);
        auto tem_func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
        AddRepeatedFuncLocal(repeat_num - 1, time, id, std::move(tem_func));
        return id;
    }
    
    int GetNextRepeatedFuncId() { return repeated_func_id_++; }
    
    template <typename R, typename P, typename F>
    void AddRepeatedFuncLocal(int repeat_num, const std::chrono::duration<R, P>& time, int id, F&& f) {
        if (!this->repeated_id_state_map_.IsKeyExist(id)) {
            return;
        }
        InternalS s;
        s.time_point_ = std::chrono::high_resolution_clock::now() + time;
        auto tem_func = std::move(f);
        s.repeated_id = id;
        s.func_ = [this, &tem_func, repeat_num, time, id]() {
            tem_func();
            if (!this->repeated_id_state_map_.IsKeyExist(id) || repeat_num == 0) {
                return;
            }
            AddRepeatedFuncLocal(repeat_num - 1, time, id, std::move(tem_func));
        };
        std::unique_lock<std::mutex> lock(mutex_);
        queue_.push(s);
        lock.unlock();
        cond_.notify_all();
    }
    

    如何取消循环任务的执行

    定时器内部有repeated_id_state_map_数据结构,用于存储循环任务的ID,当取消任务执行时,将此ID从repeated_id_state_map_中移除,循环任务就会自动取消。

    void CancelRepeatedFuncId(int func_id) { repeated_id_state_map_.EraseKey(func_id); }
    

    简单的测试代码

    void TestTimerQueue() {
        TimerQueue q;
        q.Run();
        for (int i = 5; i < 15; ++i) {
            q.AddFuncAfterDuration(std::chrono::seconds(i + 1), [i]() { std::cout << "this is " << i << std::endl; });
    
            q.AddFuncAtTimePoint(std::chrono::high_resolution_clock::now() + std::chrono::seconds(1),
                                 [i]() { std::cout << "this is " << i << " at " << std::endl; });
        }
    
        int id = q.AddRepeatedFunc(10, std::chrono::seconds(1), []() { std::cout << "func " << std::endl; });
        std::this_thread::sleep_for(std::chrono::seconds(4));
        q.CancelRepeatedFuncId(id);
    
        std::this_thread::sleep_for(std::chrono::seconds(30));
        q.Stop();
    }
    

    完整代码

    完整代码可在github中查看。
    https://github.com/fightingwangzq/wzq_utils/blob/master/timer/include/timer/timer.h

    关注一下呗

     

    展开全文
  • gtk定时器功能实现

    2015-07-30 10:04:09
    在linux下编写实现的gtk定时器,附件中有源码,可以make编译执行
  • Linux下实时定时器实现及应用.PDF
  • 主要介绍了SpringBoot集成ElaticJob定时器实现代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 主要介绍了python线程定时器Timer实现原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • STM32通用定时器的基本定时器功能实现灯闪烁
  • C#三种定时器实现

    2013-04-27 10:45:44
    本文详细论述了C#中三种定时器实现,程序开发中常用到定时器
  • 此时需要用到内部定时器来实现,可用两个定时器实现,也可以用一个定时器实现。  用两个定时器的方法是用定时器T0来控制频率,定时器T1来控制占空比。大致的的编程思路是这样的:T0定时器中断让一个I0口输出高电平...
  • 本文主要为单片机定时器中断实现长时间定时程序,希望对你的学习有所帮助
  • C++定时器实现

    2016-07-11 10:23:43
    C++定时器实现,简单易懂,高效
  • linux使用select实现精确定时器详解 Linux下实现定时器Timer的几种方法总结 LINUX内核定时器(高精度&低精度)实现循环定时 Linux时间子系统之六:高精度定时器(HRTIMER)的原理和实现 linux下jiffies定时器和...
  • 定时器实现

    千次阅读 2008-11-24 11:35:00
    定时器实现 通过Reactor机制,还可以很容易的实现定时器的功能,使用方式如下。 编写一个事件反应器,重载handle_timeout()方法,该方法是定时器的触发时间到时,会自动触发该方法。 通过Reactor的schedule_timer...
  • 定时器中断实现步骤

    千次阅读 2018-12-03 17:03:06
    ①1、使能定时器时钟。 &nbsp;RCC_APB1PeriphClockCmd();&nbsp; ②&nbsp; 初始化定时器,配置ARR,PSC。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TIM_TimeBaseInit(); ③3、开启定时器中断...
  • PHP 多任务秒级定时器实现方法 PHP 多任务秒级定时器实现方法

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 203,026
精华内容 81,210
关键字:

定时器是如何实现的