Linux高精度延时 您所在的位置:网站首页 最好用的延时 Linux高精度延时

Linux高精度延时

2024-07-11 01:09| 来源: 网络整理| 查看: 265

1、能降低CPU占用就行

只要我的进程不出现在高cpu占用榜单上,不被其他组员锤死就行!

#include // 引入 usleep() int main(void) { while(1) { //没有特殊要求延时最好放到前面,避免忘记 usleep(1000); //没有精神的干活 ; } return 0; } 2、听别人说usleep延时不准,还有没有别的方法?

传说中通过select来间接得到准确延时的方法

#include // 引入 NULL #include // 引入 struct timeval void delayUs(long int us) { struct timeval tv; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; select(0, NULL, NULL, NULL, &tv); } int main(void) { while(1) { delayUs(1000); //假装有精神的干活 ; } return 0; }

但从我的实际测试结果来看(树莓派4B),usleep和select的延时效果相差不多,他们有一个共同的问题就是实际延时要多几百us,手动矫正一下还是可以用的。后面在其它平台测了一下,准确的说应该是usleep在树莓派里超长发挥了,select还是比较稳定的。

3、严格周期任务

由于干活的内容所花时长不定,导致下一个周期开始时要么提前了一点、要么晚了一点,有没什么办法保证周期固定?比方约好了每天中午12点搬砖,那么周期就是24小时,今天花10个小时把砖搬完,就休息14小时;花13个小时把砖搬完,就休息11个小时。首先要识别当前干活花了多少时间,然后根据时间差进行延时。

#include // 引入 NULL #include // 引入 struct timeval // 获取系统tick可以作为us时长参考 long int getTickUs(void) { struct timeval tv = {0}; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000u + tv.tv_usec; } void delayUs(long int us) { struct timeval tv; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; select(0, NULL, NULL, NULL, &tv); } // 延时初始化 #define DELAY_INIT \ long int _tick1 = 0, _tick2; // 检查时差,差多少延时多少 #define DELAY_US(us) \ _tick2 = getTickUs(); \ if (_tick2 > _tick1 && _tick2 - _tick1 < us)\ delayUs(us - (_tick2 - _tick1)); \ _tick1 = getTickUs(); int main(void) { DELAY_INIT; while(1) { DELAY_US(500000); //随机时长的干活(我也不知道接下来要干多久,总之500ms以内就是了) ; } return 0; }

这种延时的特点就是周期固定,当你不知道接下来的内容会花费多长时间,但又希望周期轮询当前内容时就适合这种延时。

4、严格周期任务 - 改

每种延时都是有误差的,如何用有误差的延时搭建稳定的周期任务?可以利用延时偏大的特点,每次延时目标时差的一半,结束后计算误差,再一半,如此循环多次,即使每次延时都不准确,但最后总能把误差压到最小;另外,循环不可能无限次,应设定一个可接受的误差以结束循环。

#include // 引入 NULL #include // 引入 struct timeval // 获取系统tick可以作为us时长参考 long int getTickUs(void) { struct timeval tv = {0}; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000u + tv.tv_usec; } void delayUs(long int us) { struct timeval tv; tv.tv_sec = us / 1000000; tv.tv_usec = us % 1000000; select(0, NULL, NULL, NULL, &tv); } // 延时初始化 #define DELAY_INIT2 \ long int _tick = 0, _tickErr; // 每次延时一半时差,直至延时满us或差值小于err,注意要放在循环开始 #define DELAY_US2(us, err) \ _tickErr = getTickUs() - _tick; \ if (_tickErr > 0 && us > _tickErr) \ { \ _tickErr = us - _tickErr; \ if (_tickErr > err) \ { \ delayUs(_tickErr / 2); \ continue; \ } \ } \ _tick = getTickUs(); int main(void) { DELAY_INIT2; while(1) { //目标延时500ms,接受误差50us DELAY_US2(500000, 50); //安心的干活 ; } return 0; }

这种延时周期性精度高、抗干扰能力强,可以用在对周期和稳定性要求都较高的场景,如音、视频播放,帧数据传输等。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有