概述
一、需要的头文件
#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中学到的高精度时间控制与测试所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复