我有一个PIC24F好奇心板(PIC24FJ128GA204),我试图通过TIM1获得准确的第二个定时。作为一个来源,我使用的是辅助振荡器,它使用32678 kHz xtl。
定时器配置为32个周期,相当于1 ms
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;
}
因此,每隔1 ms调用以下中断,其中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的另一端,我有一个应用程序,它读取消息并记录接收消息的时间和相对于上一条消息的毫秒差异。
问题是每条消息的累积时间约为8毫秒。
22:05.026 1008
22:06.035 1009
22:07.045 1010
22:08.054 1008
22:09.063 1008
怀疑它可能是与UART传输有关的事情经常被中断我试图每10秒发送一次消息而不是1.延迟一直累积到每10秒约80ms。
最后,可能是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
这段时间似乎会影响计时器的准确性。我不明白怎么做。可能是因为每次中断都会丢失几微秒?我在数据表上看不到任何内容,但我找不到任何其他解释。
答案 0 :(得分:2)
请记住,在设置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秒(公差不能承受)。你的中断不会完全达到1毫秒,但你的1秒钟将非常接近。