嵌入式平台使用相对时间实现精准定时器

嵌入式平台使用相对时间实现精准定时器,第1张


一、现存问题

对于资源受限的嵌入式平台,由于多线程抢占内核,在某个线程中使用系统定时器可能达不到理想的定时效果。


例如我使用的MIPS7628, *** 作系统为Linux,最小的睡眠时间单位为4ms,想要定时10ms去内存数据并做相应的处理。


但是定时10ms不准确,每次定时都存在误差,时间长了以后,误差累计越来越大。


处理数据的数量越多,遍历的时间也越长,误差也会越来越大。


对于时间要求很严格的情况下,这是无法接受的。


那么如何消除这个累计误差呢?


二、消除累计时间误差方案

考虑使用相对时间来消除累计误差,即使有一个时间点存在误差,使用该方法也可在后续的定时中恢复正常。


代码逻辑如下: 1、 对每个数据点记录一个起始时间(记为startTv,系统时间,至少精确到1ms,有的可以精确到us)和定时时间(记为tick,例如10ms); 2、睡眠一段时间(睡眠主要是为了释放CPU,避免该线程独占,例如:4ms)遍历数据,获取当前的系统时间(记为curTv); 3、计算系统当前时间和起始时间的差(记为gap),若(gap >= tick)则判定为时间到,执行数据处理流程,并执行步骤4,否则执行步骤5,; 4、更新startTv,这是最为关键的一步,将startTv与tick的的和作为下一轮检查的startTv(这可消除累计误差),然后更新tick; 5、判断下一个数据,直到数据遍历完成,返回步骤2。


注意:在数据处理流程中不应作延时或耗时多的 *** 作,否则将影响定时效果。



三、示例代码

#include 
#include 
#include 
#include 
#include 

typedef struct _time_tick{
    struct timeval startTv;
    int tick;   //10ms
    int data;   //
}TimeTick_T;

//时间差,ms
int TimeGap(struct timeval newTv, struct timeval oldTv)
{
    int gap = 0;
    gap = 1000 * ((int)newTv.tv_sec - (int)oldTv.tv_sec) + (int)(newTv.tv_usec / 1000) - (int)(oldTv.tv_usec / 1000);
    return gap;
}

void ChecktimeAndHandle(TimeTick_T *pt)
{
    int gap = 0;
    struct timeval tv;

    gettimeofday(&tv, NULL);
    gap = TimeGap(tv, pt->startTv);
    if(gap < 0){    //无效时间
        return ;
    }

    gap = gap / 10;
    if(gap < pt->tick){
        //超时时间未到
        return ;
    }

    //超时时间到,更新时间,非常重要
    unsigned int us = pt->startTv.tv_usec + pt->tick * 10 * 1000;    //微秒
    pt->startTv.tv_sec = pt->startTv.tv_sec + us / 1000000;//计算秒
    pt->startTv.tv_usec = us % 1000000;

    //处理数据,不可做延时或耗时多的 *** 作
    pt->data ++;
    printf("current starttv : %d.%d ,gap = %d\n",pt->startTv.tv_sec ,pt->startTv.tv_usec/1000,gap);
}

int main()
{
    TimeTick_T t = {0};
    t.tick = 100;
    gettimeofday(&t.startTv, NULL);
    while (1)
    {
        usleep(4000);
        ChecktimeAndHandle(&t);
        /* code */
    }
    
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/563589.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-02
下一篇 2022-04-02

发表评论

登录后才能评论

评论列表(0条)

保存