【小技巧】关于时间戳和rtos.tick()的一点使用心得

众所周知,os.time()输出的是时间戳,而rtos.tick()是每秒16384个tick。那么这二者有什么用途呢?


通常而言,如果是需要严格的时间认证,那么必须使用os.time(),至于说同步时钟的方法有很多,可以参考:http://oldask.openluat.com/article/30

但是,不论使用哪个方法,都会出现一个问题:同步成功前后产生巨大的差值,可能导致程序逻辑运行错误


避免错误

如何避免时钟同步前后产生的差值,导致程序错误呢?


方法一、使用rtos.tick()

之前的方式:

a=os.time()

-- 时钟同步后,os.time()瞬间增加成千上万,后边的if会判断为true,并执行

if os.time()-a>20 then xxxx end


现在的方式:

a=rtos.tick()

-- 时钟同步后,os.time()瞬间增加成千上万,但是并不影响rtos.tick(),后边的if逻辑不会出错,程序正常执行

if rtos.tick()-a>20*16384 then xxxx

如此一来,使用rtos就可以完美的计时,且不用担心时钟同步后导致错误了。

但是需要注意,rtos.tick(),根据底层和模块不同,脉冲次数与归零周期不同。其中非float底层,rtos.tick()默认归零时间是38小时,float底层rtos.tick()是72小时。


方法二、使用os.time()

如果程序需要稳定运行,无法接收rtos.tick()定期归零,那么有两个方法避免:

1、记录rtos.tick()归零行为,并把原值做处理

local iLstTick=0                --记录最后一次tick值,开机默认是0

local bTickReset=false    --记录刚刚是否tick重置过

sys.timerStart(function()    --timer,用于判断tick是否重置

    if rtos.tick()<25000 and iLstTick~=0 then

        bTickReset=true

    end

    iLstTick=rtos.tick()

end, 1000)

local iRecTick            --设置变量,记录tick

--判断间隔时间是否符合条件,并执行代码

if bTickReset==true then

    --需要根据底层判断最长,否则可能出错,这里用的是72小时,即4,294,967,295‬

    iRecTick = iRecTick-4294967295‬

    bTickReset=false
end

if rtos.tick()-iRecTick>30*16384 then

    --your code

end


2、记录os.time()同步前后的差值,并将它加入到运算中

local iOldTimeStamp,iLastTimeStamp=0, 0

sys.timerStart(function()

    if os.time()<1500000000 then    --如果ntp同步成功,肯定大于150000000

        iOldTimeStamp=os.time()

        iLastTimeStamp=os.time()

    else

        if iLastTimeStamp<1500000000 then iLastTimeStamp=os.time() end

    end

end, 1000)

--现在获得了同步前后的差值就是iLastTimeStamp-iOldTimeStamp

local a --假设a是标的

if a <1500000000 then a=a+iLastTimeStamp-iOldTimeStamp end    --这里加上同步前后的差值,就不会影响a的值

if os.time()-a>30 then   

    --your code

end



上次更新 2021-01-28