我有以下一段称为的代码,大约每秒 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秒或10000厘秒后出现。我怀疑有些问题,但是我看不到。

有谁知道哪个术语导致了这个,为什么?

最佳答案

您错误地转换了get_phase_deviation()的返回值,因为deviation %= 60000的范围是-59999 to 59999(不是0 to 59999)。您应该更改以下行:

 return (int16_t)(deviation<=30000? deviation: deviation-60000);

正确处理偏差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

09-27 03:02