我是靠谱客的博主 开朗柜子,最近开发中收集的这篇文章主要介绍从EtherCAT中学到的高精度时间控制与测试,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、需要的头文件

#include <stdio.h>
#include <sys/time.h>	// for struct timeval
#include <time.h>
#include <sys/mman.h>
#include <malloc.h>
#include <sched.h> /* sched_setscheduler() */

#include <stdlib.h> // for size_t
#include <stdint.h>

二、前置知识

        timespec时间结构体

//定义
struct timespec
{
  __time_t tv_sec;		/* Seconds.  */
  __syscall_slong_t tv_nsec;	/* Nanoseconds.  */
};

//初始化
struct timespec startTime, endTime, lastStartTime = {};

//timespec时间结构体的加法
#define NSEC_PER_SEC (1000000000L)  //纳秒数10^9
#define PERIOD_NS (NSEC_PER_SEC / FREQUENCY)    /*本次设置周期PERIOD_NS为1ms*/

struct timespec timespec_add(struct timespec time1, struct timespec time2)
{
    struct timespec result;

    if ((time1.tv_nsec + time2.tv_nsec) >= NSEC_PER_SEC) {
        result.tv_sec = time1.tv_sec + time2.tv_sec + 1;    // 纳秒满进1
        result.tv_nsec = time1.tv_nsec + time2.tv_nsec - NSEC_PER_SEC;
    } else {
        result.tv_sec = time1.tv_sec + time2.tv_sec;
        result.tv_nsec = time1.tv_nsec + time2.tv_nsec;
    }

    return result;
}

       基于Linux C语言的时间函数<time.h>,可以用于计算时间,有秒和纳秒两种精度

        获取当前时间:clock_gettime;               其中cld_id类型四种。CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变。CLOCK_MONOTONIC,从系统启动这一刻起开始计时,不受系统时间被用户改变的影响。CLOCK_PROCESS_CPUTIME_ID,本进程到当前代码系统CPU花费的时间。CLOCK_THREAD_CPUTIME_ID,本线程到当前代码系统CPU花费的时间。第一、二两种类型均可

        调用线程以纳秒为精度进行指定的时间间隔睡眠:clock_nanosleep;

三、以1ms为间隔的休眠循环函数

const struct timespec cycletime = {0, PERIOD_NS};//1ms

void cyclic_task()
{


    struct timespec wakeupTime, time;

    // 获取当前时间
    //cld_id类型为CLOCK_MONOTONIC
    clock_gettime(CLOCK_MONOTONIC, &wakeupTime);

    while(1) {

	    //printf("wakeupTime: %10u--%10un",wakeupTime.tv_sec,wakeupTime.tv_nsec);
	    //循环时间 每次增加1个cycletime 从循环开始固定
        wakeupTime = timespec_add(wakeupTime, cycletime);
        //调用线程以纳秒精度指定的时间间隔进行睡眠	(高分辨率休眠)
        clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &wakeupTime, NULL);
    }

}

四、代码运行时间测试

包括延迟时间latency_ns,执行时间exec_ns,周期时间period_ns。单位纳秒

#define DIFF_NS(A, B) (((B).tv_sec - (A).tv_sec) * NSEC_PER_SEC + 
       (B).tv_nsec - (A).tv_nsec)        计算时间差

void cyclic_task()
{

    struct timespec wakeupTime, time;
    //测量时间
#ifdef MEASURE_TIMING
    struct timespec startTime, endTime, lastStartTime = {};
    uint32_t period_ns = 0, exec_ns = 0, latency_ns = 0,
             latency_min_ns = 0, latency_max_ns = 0,
             period_min_ns = 0, period_max_ns = 0,
             exec_min_ns = 0, exec_max_ns = 0;
#endif

    // 获取当前时间系统
    clock_gettime(CLOCK_TO_USE, &wakeupTime);

    while(1) {

        wakeupTime = timespec_add(wakeupTime, cycletime);
        //调用线程以纳秒精度指定的时间间隔进行睡眠	(高分辨率休眠)
        clock_nanosleep(CLOCK_TO_USE, TIMER_ABSTIME, &wakeupTime, NULL);


#ifdef MEASURE_TIMING
        //记录工作代码开始时间
        clock_gettime(CLOCK_TO_USE, &startTime);


        //延迟时间
        latency_ns = DIFF_NS(wakeupTime, startTime);
        //周期时间
        period_ns = DIFF_NS(lastStartTime, startTime);
        //代码执行时间
        exec_ns = DIFF_NS(lastStartTime, endTime);
        //赋值    以记录完整的周期时间
        lastStartTime = startTime;


        //记录延时最大间隔
        if (latency_ns > latency_max_ns) {
            latency_max_ns = latency_ns;
        }
        if (latency_ns < latency_min_ns) {
            latency_min_ns = latency_ns;
        }
        if (period_ns > period_max_ns) {
            period_max_ns = period_ns;
        }
        if (period_ns < period_min_ns) {
            period_min_ns = period_ns;
        }
        if (exec_ns > exec_max_ns) {
            exec_max_ns = exec_ns;
        }
        if (exec_ns < exec_min_ns) {
            exec_min_ns = exec_ns;
        }
#endif

        /....../

#ifdef MEASURE_TIMING
            // 输出时间统计数据
            printf("period     %10u ... %10un",
                    period_min_ns, period_max_ns);
            printf("exec       %10u ... %10un",
                    exec_min_ns, exec_max_ns);
            printf("latency    %10u ... %10un",
                    latency_min_ns, latency_max_ns);
            period_max_ns = 0;
            period_min_ns = 0xffffffff;
            exec_max_ns = 0;
            exec_min_ns = 0xffffffff;
            latency_max_ns = 0;
            latency_min_ns = 0xffffffff;
#endif
        }

        /...主要代码.../
       
#ifdef MEASURE_TIMING
        //代码运行结束时间
        clock_gettime(CLOCK_TO_USE, &endTime);
#endif
    }
}

最后

以上就是开朗柜子为你收集整理的从EtherCAT中学到的高精度时间控制与测试的全部内容,希望文章能够帮你解决从EtherCAT中学到的高精度时间控制与测试所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部