Hy我有两台设备A和B都使用64位定时器。一个刻度等于1ns。我想同步两个计时器的漂移。我已经知道A和B之间的延迟。通常我会将A的当前时间频繁发送到B.在B中我会添加传播延迟并使用此值作为比较值来同步B.在我的情况下我只能发送每100ms降低32位定时器。我试图用A的部分简单地替换B的下部,但只要没有32位的溢出,这个工作。有没有办法检测到这种溢出?溢出示例(缩短计时器):
定时器B:0x00FF
定时器A:0x010A
=> 0x0A到B. 取代导致 定时器B 0x000A而不是定时器B 0x010A。
所以我需要检测A中已经发生的溢出,而B中没有发生溢出。
下溢示例(缩短计时器):
定时器B:0x0205
计时器A:0x01F6
=> 0xF6 =>定时器B:0x02F6而不是0x01F6
在这种情况下,计时器B比计时器A快。
答案 0 :(得分:1)
我在timera
timerb
timera
的{{1}}的最低可能值message
和delay
中的预期传播延迟:
#include <stdint.h>
int64_t expected_timera(const int64_t timerb,
const uint32_t message,
const uint32_t delay)
{
const int64_t timer1 = (timerb / INT64_C(4294967296)) * INT64_C(4294967296)
+ (int64_t)message + (int64_t)delay;
const int64_t timer0 = timer1 - INT64_C(4294967296);
const int64_t timer2 = timer1 + INT64_C(4294967296);
const uint64_t delta0 = timerb - timer0;
const uint64_t delta1 = (timer1 > timerb) ? timer1 - timerb : timerb - timer1;
const uint64_t delta2 = timer2 - timerb;
if (delta0 < delta1)
return (delta0 < delta2) ? timer0 : timer2;
else
return (delta1 <= delta2) ? timer1 : timer2;
}
就个人而言,我还会使用线性调整从实际计时器B计算timerb
:
static volatile int64_t real_timer_b; /* Actual timer b */
static int64_t timerb_real; /* real_timer_b at last sync time */
static int64_t timerb_offset; /* timera at last sync time */
static int32_t timerb_scale; /* Q30 scale factor (0,2) */
static inline int64_t timerb(void)
{
return ((int64_t)(int32_t)(real_timer_b - timerb_real) * (int64_t)timerb_scale) / INT64_C(1073741824) + timerb_offset;
}
使用timerb_real = 0
,timerb_offset = 0
和timerb_scale = 1073741824
,timerb() == real_timer_b
。
当timera > timerb()
时,您需要增加timerb_scale
。在timera < timerb()
时,您需要减少timerb_scale
。您不希望每100ms计算一次精确值,因为传播延迟中的抖动会直接影响timerb()
;你想在几秒钟内缓慢调整它。作为奖励,您可以保持timerb()
单调,而不会突然向前或向后跳跃。
Network Time Protocol实现做了非常相似的事情,您可能会在那里找到进一步的实现帮助。