Timer pic定时器2中断触发太快

Timer pic定时器2中断触发太快,timer,interrupt,pic,Timer,Interrupt,Pic,我使用mplab代码配置器生成了计时器(timer2)的代码。在组合框中,我选择计时器周期的最大时间。因此,我在T2OUTPS(1111)中使用1:16的后分频器,在T2CKPS(1x)中使用16的预分频器 该周期应为几秒钟,但每半秒钟触发一次(大约)。我不明白问题出在哪里,因为我给前置和后置定标器的值不重要,周期是一样的 这是相关代码。这是我初始化计时器的方式: void TMR2_Initialize(void) { // Set TMR2 to the options selected

我使用mplab代码配置器生成了计时器(timer2)的代码。在组合框中,我选择计时器周期的最大时间。因此,我在T2OUTPS(1111)中使用1:16的后分频器,在T2CKPS(1x)中使用16的预分频器 该周期应为几秒钟,但每半秒钟触发一次(大约)。我不明白问题出在哪里,因为我给前置和后置定标器的值不重要,周期是一样的

这是相关代码。这是我初始化计时器的方式:

void TMR2_Initialize(void) {
  // Set TMR2 to the options selected in the User Interface

  T2CON = 0b01111011;
  //T2CON = 0x3A;
  //T2CON.T2OUTPS = 0b0000;


  // PR2 255; 
  PR2 = 0xFF;

  // TMR2 0x0; 
  TMR2 = 0x00;

  // Clearing IF flag before enabling the interrupt.
  PIR1bits.TMR2IF = 0;

  // Enabling TMR2 interrupt.
  PIE1bits.TMR2IE = 1;

  // Start TMR2
  TMR2_StartTimer();
}

void TMR2_StartTimer(void) {
   // Start the Timer by writing to TMRxON bit
   T2CONbits.TMR2ON = 1;
}
这就是我处理中断的方式:

void interrupt SYS_InterruptHigh(void)
{
  if (PIE1bits.TMR2IE == 1 && PIR1bits.TMR2IF == 1) {
      TMR2_ISR();
  }   

......


void TMR2_ISR(void) {

  // clear the TMR2 interrupt flag
  PIR1bits.TMR2IF = 0;


  if (colorUpdate%4 == 1)
  {
      LED_Color(0xFFFF,0x0000,0xFFFF);
  }
  else if (colorUpdate%4 == 2)
  {
      LED_Color(0x0000,0xFFFF,0xFFFF);
  }
  else if (colorUpdate%4 == 3)
  {
      LED_Color(0xFFFF,0xFFFF,0x0000);    
  }
  else if (colorUpdate%4 == 0)
  {
       LED_Color(0x0000,0xFFFF,0x0000);   
  }

  colorUpdate++;
  if (colorUpdate>1000)
      colorUpdate = 0;

  LED_UpdateImage();

  LATCbits.LATC6 = 1;

  LATCbits.LATC6 = 0;

}
必须在中断例程中重新加载TMR2


另外,最好避免中断服务例程中函数调用的开销。做最低限度的必要工作。如果可能的话,如果你能容忍时间上的微小偏差,就向外部任务发出信号,让他们做实际的工作。

这是作为一个评论开始的,但我已经没有空间了,所以我将作为答案发布

OP的最新评论不清楚
f_OSC
是16 MHz还是
f_OSC
是16 MHz x 3(PLL)/CPUDIV——在这种情况下,最小/最大
f_OSC
分别是8/24 MHz

但是让我们使用
f_OSC=16MHz
。据我所知,Timer2时钟源为
f_OSC/4
=4 MHz,后定标器和预定标器的综合效应为/256,因此TMR2在15625 Hz(@16 MHz f_OSC)下递增。PR2在255时,我希望TMR2IF每255/15625=0.01632秒触发一次(~60赫兹)。在
f_OSC=8 MHz时,这将是每0.03264秒(~30 Hz),在
f_OSC=24 MHz时(16 MHz x 3/2),这将是每0.01088秒(~90 Hz)

基于此,我认为您对中断间隔的期望可能基于一个不正确的前提,因为它与您的
f_OSC
相去甚远

即使观察到的中断间隔也远比上面计算的要长。 我怀疑这是由于以下原因之一:

  • 中断不足-it或其他更高优先级的任务需要很长时间才能执行,
    TMR2\u ISR()
    大约每半秒执行一次
  • 引脚C6
    脉冲的持续时间很短,以至于您无法用示波器/LA/捕获所有这些脉冲,无论您使用什么测试设备
  • 我建议进行以下一项或两项调查:

  • 移动
    LATCbits.LATC6=1
    TMR2_ISR()
    顶部-这样,脉冲的高持续时间将指示ISR的执行时间,信号频率将告诉您执行ISR的频率。如果脉冲持续时间太短而无法捕获所有脉冲,这也会更容易发现

  • 在一个程序中测试您的定时器设置,在该程序中,您的设置与现在相同,但定时器2 ISR只做两件事-重置
    TMR2IF
    和切换引脚
    C6
    (切换与脉冲相反,也更容易捕获-当然,您的中断频率是
    C6
    上方波频率的两倍)


  • 你用什么图片,你的系统时钟频率是多少?是否有单独的位启用后/前定标器-其中一个未启用将使您的约0.5秒变为约8秒,这似乎与您期望的相似。我使用pic18f24k50。我认为没有位启用定标器,但我一回到家就会查看pic运行的频率是多少?PLL是否启用?如果是这样的话,计时器计算中是否考虑了这一因素?频率为16 MHz。PLL通过在数据表soys中选择的3x PLL比率模式启用,timer2自动清除tmr2寄存器。反正我也测试过了results@rreiv23好,然后将PR2的值更改为较小的值。值越低,递增到零所需的时间越长。@jolati PR2仅在代码中设置时才会更改。TMR2递增,并在TMR2与PR2匹配时生成中断,因此PR2值越高意味着中断时间越长interval@SigveKolbeinson是的,我现在明白了。我把它和Timer0搞混了,它们一点都不相似。谢谢你的更正。嗨,谢谢你的回复。我猜每X秒触发一次都是不可能的,因为它们的工作时间间隔更短。我用程序主循环中的一个计数器解决了我的问题,这样我就得到了4秒的时间间隔。这不是真正的“在较短的时间间隔内工作”,因为时间间隔是f_OSC的函数。定时器0模块有一个1:256的预分频器(无后置刻度)和一个16位定时器寄存器,因此使用16 MHz f_OSC最多可以计数4.194304s。定时器1/3模块有一个1:8的预分频器,但允许您选择不同的时钟源,包括一个32 kHz的时钟(PCB上需要一个32 kHz的晶体),它允许您最多计数16秒。但通常使用短周期定时器ISR来简单地增加一个定时器变量——我假设这就是“主循环中的计数器”的意思。