函数写入 "wrong" 值到寄存器 - PIC18F
Function writing "wrong" value to register - PIC18F
我编写了一个函数,您应该可以在其中输入一个数字,然后该函数会计算要写入寄存器的值。但是看起来它正在将 "wrong" 值写入寄存器。我使用计算器和 wolframalpha 来确认我没有搞砸操作顺序。函数列表如下:
void SetFrequency_Hz(int Freq) {
PR4 = ((41667000 / (4 * 16 * Freq)) - 1);
}
当我尝试将频率设置为 20kHz(20,000Hz)时,我需要将 PR4 寄存器设置为 32。理论上,如果我将 20000 的值放入函数中,应该会被吐出,但它是出于某种原因吐出179。任何猜测为什么?
单片机:PIC18F67J60
IDE:MP 实验室 X
因为在 PIC18 中,int
类型在 C 中只会是 16 bits, the somewhat arcane implicit conversion rules,这将导致表达式中的中间结果被截断。我很惊讶您的编译器没有对文字 41667000 发出警告,因为在任何情况下这显然都不适合 PIC18 int
类型。
通过使用显式字面量类型后缀来改变表达式的整体类型,可以很容易地解决这个问题:
PR4 = 41667000ul / (64ul * Freq) - 1u ;
或者如果所需的频率分辨率以 KHz 为单位,则可以缩放表达式:
PR4 = 41667u / (64u * (Freq/1000)) - 1u ;
但应注意,在这两种情况下,实际 值为 41667000 / (64 x 20x103)) - 1是 ~31.55,因此 PR4 中的值将是 31 而不是 32,并且将导致 实际 频率为 20345Hz。
舍入到最接近整数值的真实表达式:
PR4 = (41667000ul / (32ul * Freq) - 1u) / 2 ;
这将导致 PR4=32 和 19729Hz 的频率。
可能有用return函数实际达到的频率:
unsigned SetFrequency_Hz( unsigned ideal_freq )
{
PR4 = (41667000ul / (32ul * ideal_freq ) - 1u) / 2u ;
// Return actual achievable frequency
return 41667000ul / ((PR4 + 1ul) * 64ul)
}
我编写了一个函数,您应该可以在其中输入一个数字,然后该函数会计算要写入寄存器的值。但是看起来它正在将 "wrong" 值写入寄存器。我使用计算器和 wolframalpha 来确认我没有搞砸操作顺序。函数列表如下:
void SetFrequency_Hz(int Freq) {
PR4 = ((41667000 / (4 * 16 * Freq)) - 1);
}
当我尝试将频率设置为 20kHz(20,000Hz)时,我需要将 PR4 寄存器设置为 32。理论上,如果我将 20000 的值放入函数中,应该会被吐出,但它是出于某种原因吐出179。任何猜测为什么?
单片机:PIC18F67J60 IDE:MP 实验室 X
因为在 PIC18 中,int
类型在 C 中只会是 16 bits, the somewhat arcane implicit conversion rules,这将导致表达式中的中间结果被截断。我很惊讶您的编译器没有对文字 41667000 发出警告,因为在任何情况下这显然都不适合 PIC18 int
类型。
通过使用显式字面量类型后缀来改变表达式的整体类型,可以很容易地解决这个问题:
PR4 = 41667000ul / (64ul * Freq) - 1u ;
或者如果所需的频率分辨率以 KHz 为单位,则可以缩放表达式:
PR4 = 41667u / (64u * (Freq/1000)) - 1u ;
但应注意,在这两种情况下,实际 值为 41667000 / (64 x 20x103)) - 1是 ~31.55,因此 PR4 中的值将是 31 而不是 32,并且将导致 实际 频率为 20345Hz。
舍入到最接近整数值的真实表达式:
PR4 = (41667000ul / (32ul * Freq) - 1u) / 2 ;
这将导致 PR4=32 和 19729Hz 的频率。
可能有用return函数实际达到的频率:
unsigned SetFrequency_Hz( unsigned ideal_freq )
{
PR4 = (41667000ul / (32ul * ideal_freq ) - 1u) / 2u ;
// Return actual achievable frequency
return 41667000ul / ((PR4 + 1ul) * 64ul)
}