首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计时器精度和中断

计时器精度和中断
EN

Stack Overflow用户
提问于 2018-02-04 19:43:05
回答 1查看 248关注 0票数 0

我有一个PIC24F好奇板(PIC24FJ128GA204),我正试图用TIM1获得准确的第二个时钟。作为信号源,我使用辅助振荡器,它使用32678 kHz xtl。

定时器配置为32个周期,相当于1ms

代码语言:javascript
复制
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变量中

代码语言:javascript
复制
void __attribute__ ( ( interrupt, no_auto_psv ) ) _T1Interrupt (  )
{    
    tmr1_obj.count++;
    tmr1_obj.timerElapsed = true;
    IFS0bits.T1IF = false;
}

在主循环中,我在tmr1_obj.count变量上执行了一次繁忙的等待,当它达到1000时,将以UART发送一条消息。

代码语言:javascript
复制
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的累积。

代码语言:javascript
复制
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秒。我原以为结果大致相同,但事实并非如此

代码语言:javascript
复制
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

似乎周期会影响计时器的精度。我不明白是怎么回事。会不会是每一次中断都损失了一些微秒?我在数据表上看不到任何东西,但我找不到任何其他解释。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-07 07:00:23

请记住,在设置PIC24的周期时,您必须将"0“视为刻度,因此您希望将周期设置为比所需周期小1刻度(在本例中为31)。

考虑一下,如果你想要一个5刻度的周期。如果将周期寄存器设置为5,它将执行以下操作:

代码语言:javascript
复制
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秒将非常接近。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48607672

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档