Timer pic定时器2中断触发太快
我使用mplab代码配置器生成了计时器(timer2)的代码。在组合框中,我选择计时器周期的最大时间。因此,我在T2OUTPS(1111)中使用1:16的后分频器,在T2CKPS(1x)中使用16的预分频器 该周期应为几秒钟,但每半秒钟触发一次(大约)。我不明白问题出在哪里,因为我给前置和后置定标器的值不重要,周期是一样的 这是相关代码。这是我初始化计时器的方式: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
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来简单地增加一个定时器变量——我假设这就是“主循环中的计数器”的意思。