Поскольку в PIC18 тип int
будет иметь только 16 бит , несколько непонятные правила неявного преобразования в C приведут к усечению промежуточных результатов в вашем выражении. Я удивлен, что ваш компилятор не выдал предупреждение для литерала 41667000, так как это явно не будет соответствовать типу PIC18 int
в любом случае.
Эту проблему легко решить, используя явные суффиксы литерального типа для изменения общего типа выражения:
PR4 = 41667000ul / (64ul * Freq) - 1u ;
или, если требуемое разрешение по частоте в кГц, вы можете масштабировать выражение:
PR4 = 41667u / (64u * (Freq/1000)) - 1u ;
Следует отметить, однако, что в обоих этих случаях действительное значение 41667000 / (64 x 20x10 3 )) - 1 равно ~ 31,55, поэтому значение в PR4 будет 31, а не 32, и приведет к фактической частоте 20345 Гц.
Чтобы округлить до ближайшего целочисленного значения выражения real :
PR4 = (41667000ul / (32ul * Freq) - 1u) / 2 ;
Это приведет к PR4 = 32 и частоте 19729 Гц.
Может быть полезно, чтобы функция возвращала фактическую достигнутую частоту:
unsigned SetFrequency_Hz( unsigned ideal_freq )
{
PR4 = (41667000ul / (32ul * ideal_freq ) - 1u) / 2u ;
// Return actual achievable frequency
return 41667000ul / ((PR4 + 1ul) * 64ul)
}