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

一、现存问题

对于资源受限的嵌入式平台,由于多线程抢占内核,在某个线程中使用系统定时器可能达不到理想的定时效果。
例如我使用的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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>

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 */
    }
    
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值