我有以下代码,大约每秒100次
if (elapsed_centiseconds_mod_60000 < 59999) {
++elapsed_centiseconds_mod_60000;
} else {
elapsed_centiseconds_mod_60000 = 0;
}
if (elapsed_centiseconds_mod_60000 % 6000 == 0) {
++elapsed_minutes;
}
变量和常量的类型是
volatile uint16_t elapsed_centiseconds_mod_60000;
volatile uint8_t start_minute_mod_10;
const int8_t calibration_second = 5;
然后完全每秒一次,以下称为
int16_t get_phase_deviation(uint8_t current_second, uint8_t current_minute_mod_10) {
int32_t deviation=
(int32_t) elapsed_centiseconds_mod_60000 -
((int32_t) current_second + (int32_t)600 - (int32_t)calibration_second) * (int32_t) 100 -
((int32_t) current_minute_mod_10 + (int32_t) 60 - (int32_t)start_minute_mod_10)* (int32_t)6000;
deviation %= 60000;
return (int16_t)(deviation<=30000? deviation: deviation-60000);
}
代码的思想是检测两个振荡器的相对频率误差。但是代码不能按预期工作。它将开始输出零偏差。但是一旦经过的百分之一比它们应该的那么多,它将立即跳到5537的输出,这与2 ^ 16%60000 + 1重合。我试图将中间值转换为int32_t,但问题仍然存在。通常问题出现在100秒或10 000厘秒之后。我怀疑有一些问题,但我没有看到它。
有谁知道导致这个问题的原因是什么?为什么?
答案 0 :(得分:3)
由于get_phase_deviation()
的范围为deviation %= 60000
(不 -59999 to 59999
),您错误地转换了0 to 59999
的返回值。你应该改变这一行:
return (int16_t)(deviation<=30000? deviation: deviation-60000);
正确处理偏差&lt; = -30000或将返回类型更改为int32_t
。
查看具体案例以了解您获得的数字,假设:
calibration_second = 0;
start_minute_mod_10 = 0;
然后,对于一个完美的系统get_phase_deviation()
正在返回:
deviation = -420000; // As computed
deviation %= 60000; // == 0
return 0;
如果您提前1厘米,则更改为:
deviation = -419999; // As computed
deviation %= 60000; // == -59999
return (int16_t) (-59999); // == 5537