Timer 定时器精度和中断

Timer 定时器精度和中断,timer,interrupt-handling,pic24,Timer,Interrupt Handling,Pic24,我有一个PIC24F好奇板(PIC24FJ128GA204),我正试图用TIM1获得准确的第二次计时。作为一个信号源,我使用的是次级振荡器,它使用一个32678 kHz的xtl 定时器配置有32个周期,对应于1毫秒 void TMR1\u初始化(void) { //tmr10; TMR1=0x0000; //周期=0.001秒;频率=32000 Hz;PR1 32; PR1=0x0020; //TCKPS 1:1;吨启用;TSIDL禁用;TCS外部;TECS SOSC;TSYNC启用;TGATE

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

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

void TMR1\u初始化(void)
{
//tmr10;
TMR1=0x0000;
//周期=0.001秒;频率=32000 Hz;PR1 32;
PR1=0x0020;
//TCKPS 1:1;吨启用;TSIDL禁用;TCS外部;TECS SOSC;TSYNC启用;TGATE禁用;
T1CON=0x8006;
IFS0bits.T1IF=false;
IEC0bits.T1IE=真;
tmr1_obj.timeRecursed=假;
}
因此,每1ms调用一次以下中断,其中ms的计数存储在uint32_t变量上

void\uuuuuuu属性(中断,无自动psv))\uT1interrupt()
{    
tmr1_对象计数++;
tmr1_obj.timeRecursed=真;
IFS0bits.T1IF=false;
}
在主循环中,我对tmr1_obj.count变量执行忙等待,当它达到1000时,一条消息在UART中发送

int main(无效)
{
//初始化设备
系统初始化();
TMR1_Start();
char msg[]=“A\r\n”;
而(1)
{
//添加您的应用程序代码
int value=TMR1_softwareccounterget();
如果(值==1000){
printf(“%s”,msg);
TMR1_软件反旋转();
}        
}
返回-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

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

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

考虑一下,如果你想有一个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赫兹的晶体中获得精确的1ms


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

请记住,在设置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赫兹的晶体中获得精确的1ms

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