0

我有一个 PIC24F Curiosity Board (PIC24FJ128GA204),我正在尝试使用 TIM1 获得准确的第二次计时。作为源,我使用的是辅助振荡器,它使用 32678 kHz xtl。

定时器配置了32个周期,对应1毫秒

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 秒约 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

似乎周期会影响计时器的准确性。我不明白怎么做。是不是每次中断都会丢失一些微秒?我在数据表上没有看到任何内容,但我找不到任何其他解释。

4

1 回答 1

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 个滴答声)。

现在开始你的 8 毫秒。由于您将其设置为 32,因此您将获得 33 个刻度。每个刻度是:1/32768 秒

其中 33 个是 33/32768 或大约 1.007 毫秒。其中 1000 给你额外的 7 毫秒,这非常接近你的 8。所以你真正的问题是你试图使用一个不精确的值,并且随着时间的推移它会累积错误。即使您将周期设置为 31(给出 32 个滴答声),您也将关闭,因为您无法从 32768 Hz 晶体中获得准确的 1ms。

您可以做的一件事是将您的周期设置为 31(或 32 个刻度)并与 1024 个刻度(而不是 1000)进行比较。如果不准确(公差无法承受),那应该更接近 1 秒。您的中断不会精确到 1 毫秒,但您的 1 秒将非常接近。

于 2018-04-06T23:00:23.227 回答