我有一个PIC24F好奇板(PIC24FJ128GA204),我正试图用TIM1获得准确的第二个时钟。作为信号源,我使用辅助振荡器,它使用32678 kHz xtl。
定时器配置为32个周期,相当于1ms
void TMR1_Initialize (void)
{
//TMR1 0;
TMR1 = 0x0000;
//Period = 0.001 s; Frequency = 32000 Hz; PR1 32;
PR1 = 0x0020;
//TCKPS 1:1; TON enabled; TSIDL disabled; TCS External; TECS SOSC; TSYNC enabled; TGATE disabled;
T1CON = 0x8006;
IFS0bits.T1IF = false;
IEC0bits.T1IE = true;
tmr1_obj.timerElapsed = false;
}因此,每隔1ms就会调用下面的中断,其中ms的计数存储在uint32_t变量中
void __attribute__ ( ( interrupt, no_auto_psv ) ) _T1Interrupt ( )
{
tmr1_obj.count++;
tmr1_obj.timerElapsed = true;
IFS0bits.T1IF = false;
}在主循环中,我在tmr1_obj.count变量上执行了一次繁忙的等待,当它达到1000时,将以UART发送一条消息。
int main(void)
{
// initialize the device
SYSTEM_Initialize();
TMR1_Start();
char msg[] = "A\r\n";
while (1)
{
// Add your application code
int value = TMR1_SoftwareCounterGet();
if (value == 1000) {
printf("%s", msg);
TMR1_SoftwareCounterClear();
}
}
return -1;
}在UART的另一边,我有一个应用程序,它读取消息并记录收到消息的时间以及与前一条消息的毫秒差。
问题是,我对每条消息有大约8ms的累积。
22:05.026 1008
22:06.035 1009
22:07.045 1010
22:08.054 1008
22:09.063 1008由于怀疑可能与UART传输经常中断有关,我尝试每10秒发送一次消息,而不是1秒。延迟一直累积到每10秒约80毫秒。
最后,这32个刻度可能不对应于1毫秒,而对应于1.x毫秒。为了测试,我将周期更改为32768,即1秒。我原以为结果大致相同,但事实并非如此
31:15.216 999
31:16.216 999
31:17.216 1000
31:18.216 999
31:19.216 999
31:20.215 999
31:21.216 1000似乎周期会影响计时器的精度。我不明白是怎么回事。会不会是每一次中断都损失了一些微秒?我在数据表上看不到任何东西,但我找不到任何其他解释。
发布于 2018-04-07 07:00:23
请记住,在设置PIC24的周期时,您必须将"0“视为刻度,因此您希望将周期设置为比所需周期小1刻度(在本例中为31)。
考虑一下,如果你想要一个5刻度的周期。如果将周期寄存器设置为5,它将执行以下操作:
0->1 = 1 tick
1->2 = 2 ticks
2->3 = 3 ticks
3->4 = 4 ticks
4->5 = 5 ticks
5->0 = 6 ticks因此,您真的希望将该值设置为4以获得5个刻度(或将值设置为31以获得32个刻度)。
现在转到你的8ms。由于您将其设置为32,因此您将获得33个刻度。每个刻度是: 1/32768秒
其中33个是33/32768,或者说大约是1.007ms。1000给你额外的7毫秒,这相当接近你的8毫秒。所以你真正的问题是你试图使用一个不精确的值,随着时间的推移,它会累积误差。即使你将周期设置为31 (给出32个刻度),你也会被关闭,因为你不能从32768 Hz的晶体中得到精确的1ms。
您可以做的一件事是将周期设置为31 (或32刻度),并与1024刻度(而不是1000刻度)进行比较。这应该更接近1秒,如果不准确的话(公差不能承受)。你的中断不会精确到1ms,但你的1秒将非常接近。
https://stackoverflow.com/questions/48607672
复制相似问题