定时器精度和中断

时间:2018-02-04 11:43:05

标签: timer interrupt-handling pic24

我有一个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

这段时间似乎会影响计时器的准确性。我不明白怎么做。可能是因为每次中断都会丢失几微秒?我在数据表上看不到任何内容,但我找不到任何其他解释。

1 个答案:

答案 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秒钟将非常接近。