2015-05-29 46 views
1

我在我的CODE中遇到了一些问题,我猜想溢出中断(用于将8位定时器的分辨率从16μs/ step提高到1μs/ step)。看起来像溢出中断触发,而程序是在我的主循环中的if语句,从而螺丝起飞!使用时间溢出中断时出现毛刺

if(pInt == 1)   //PCNINT-if-statment 
    {   
     pulse16 = (tot_overflow << 8) | TCNT1;   //adds tot_overflow and TCNT1 to be able to set if-statements in PCINT-while-loop with µs 

     if(PINB & (1 << PINB3))   //if PB3 is HIGH 
     { 
      TCNT1 = 0;  //resets Timer/Counter1 
      tot_overflow = 0;  //resets tot_overflow variable 
     } 

     else   
     { 
      if (pulse16 >1555)   //when stick 1 travels from 1555 µs towards 2006 µs 
      { 
       PORTB &= ~(1 << relayPin);  //relay pole switch, + & - on motor 
       PORTB |= (1 << greenLED);  //LED green indicates forward motion 
       PORTB &= ~(1 << redLED);  //turn off red LED 
      } 

       else if (pulse16 <1490)   //when stick 1 travels from 1490 ms towards 920 µs 
       { 
        PORTB |= (1 << relayPin);  //relay pole switch, - & + on motor 
        PORTB &= ~(1 << greenLED);  //turn off green LED 
        PORTB |= (1 << redLED);   //LED red indicates backward motion 
       } 

      else  //if µs is 1490> or <1555 - dead-span to prevent gliteches on relay when stick is in centre position 
      { 

      } 

     } 

     pInt = 0;  //resets pInt to exit PCNINT-if-statment 
    } 

品脱是 “旗变量”,其指示PCINT被触发。 tot_overflow变量在每次触发溢出中断时递增。

我使用ATtiny85作为RC-开关,它应该LOW上PB2针时从接收器微秒高于1555和去HIGH的时候微秒低于1490
会发生什么事是这样的:如果微秒检查时高于1555或低于1490,并且使用溢出中断时,有时在1490-1555的“死区”中将PB2引脚变为高电平/低电平,否则有时会超出“死区”!这里有一个VIDEO的故障。请注意,绿色LED是我的代码中的黄色LED是greenLED

我对此很新颖,我不确定为什么会发生这种情况,我不明白为什么代码无法工作。我已经看过CTC功能,但是我看不出它会有帮助,因为我仍然需要使用定时器溢出中断来获得1μs/ step的想要的分辨率。


编辑

我已经尝试了几个变化(的@晏-游标的建议),但仍没有得到它正常工作,这是最接近什么得到一个工作代码:

while(1)  //leave and/or put your own code here 
{ 
    static uint8_t tot_overflow;  //variable to count the number of Timer/Counter1 overflows 

    if (TIFR & (1 << TOV1)) 
    { 
     TIFR |= (1 << TOV1);  // clear timer-overflow-flag 
     tot_overflow ++; 
    } 

    if(GIFR & (1 << PCIF))   //PCINT-flag idicates PCINT 
    { 
     uint16_t pulse;   //variable to make a 16 bit integer from tot_overflow and TCNT1 

//   PORTB |= (1 << debugPin);  //pin is HIGH on when interrupt is intialized 

     pulse = (tot_overflow << 8) | TCNT1;   //adds tot_overflow and TCNT1 to be able to set if-statements in PCINT-while-loop with µs 

这部分我没有得到工作:

 if (((TIFR & (1 << TOV1)) && ((pulse & 0xff))) < 0x80) 
     { 
      pulse += 0x100; // Overflow had not been counted 
     } 

林不知道我得到了上面发生的事情,我唯一知道的是,我可能做错了!当我评论上述部分时,它与mu旧代码的工作原理相同!

 else 
     { 
      if(PINB & (1 << PINB3))   //if PB3 is HIGH 
      { 
       TCNT1 = 0;  //resets Timer/Counter1 
       tot_overflow = 0;  //resets tot_overflow variable 
      } 

      else   
      {  
       if (pulse > 1555)   //when stick 1 travels from 1555 µs towards 2006 µs 
       { 
       PORTB &= ~(1 << relayPin);  //relay pole switch, + & - on motor 
        PORTB |= (1 << greenLED);  //LED green indicates forward motion 
        PORTB &= ~(1 << redLED);  //turn off red LED 
       } 

        else if (pulse < 1490)   //when stick 1 travels from 1490 ms towards 920 µs 
        { 
         PORTB |= (1 << relayPin);  //relay pole switch, - & + on motor 
         PORTB &= ~(1 << greenLED);  //turn off green LED 
         PORTB |= (1 << redLED);   //LED red indicates backward motion 
        } 

       else  //if µs is 1490> or <1555 - dead-span to prevent gliteches on relay when stick is in centre position 
       { 
//     PORTB |= (1 << greenLED);   //for debug to indicate dead-span 
//     PORTB |= (1 << redLED);   //for debug to indicate dead-span 
       } 

      } 

     } 

     GIFR |= (1 << PCIF); //clear PCINT-flag 
    } 

    else 
    { 

    } 

} 

} 

ISR(TIMER1_OVF_vect)   //when Counter/Timer1 overflows 
{ 

} 

ISR(PCINT0_vect)  //when pin-level changes on PB3 
{ 

} 

难道它还是我还是蓝色?

+0

会真正感兴趣的是为什么有人投这个票。对我来说,这似乎是一个很好的记录问题。该OP甚至费心编入视频。正如我所见,你的计时器处理看起来不错。也许你在代码中有一些我不知道的逻辑错误。代码足够小,可能有助于重新编写一次。也许它修复了它自己。 – jwsc

+0

它不在if语句中,但是行设置为pulse16;这两个读取根本不能同时发生。 –

+0

@jwsc我被拒绝的原因可能是因为我编辑之前的帖子看起来如何。在发布帖子后我总是编辑我的帖子,因为我经常在发帖之后错过了一些东西或看到了某些东西,因为我没有第一次添加坏习惯!你可以检查后,我的第一个版本,并判断你想;-) – CrowStudio

回答

1

是的,溢出中断可能在任何时候发生(虽然它经常发生)。所以引脚改变中断。在这种情况下,它们中的每一个只触摸一个8位易失性变量(分别为tot_overflowpInt),然后轮询您的主循环。除非主循环还有其他工作要做,否则可能需要比一个完整的定时器周期更长的时间(在这种情况下,256 * 8 = 2048个周期),这种结构并不能真正帮助您。

因此,您可以在主循环中检查GIFR位PCIF(而不是pInt)和TIFR位TOV1,而不是启用中断,这会让您更容易理解行为。重置它们是将1写入该位并且只写入该位的特殊情况。这样可以节省引脚更改中断的时间,因为主循环检查可能会更频繁地发生,并且不需要跳至中断服务例程的延迟时间。

它不会,但是,解决您的问题。您正在尝试测量一个脉冲宽度,使用定时器输入捕捉功能轻松实现稍大的AVR。 ATtiny85中的定时器没有此功能。在AVR上,输入捕捉和定时器溢出中断的安排方式使得输入捕捉中断可以安全地读取软件驱动的溢出计数器。

当你得到一个定时器溢出,你增加tot_overflow,当你发现一个引脚的变化,你看TCNT1的价值观结合起来。这两个计数器,一个喂另一个,不会同时读取。您的阈值是0x5d2和0x613。如果阅读tot_overflow之后,但阅读TCNT1之前发生侧翻,你可能在这应该是0x601时间得到像0x501的时间。同样如果你停止更新tot_overflow。如果在tot_overflow之前读取TCNT1,则应该读取0x5fe时可能会得到0x6fe。简而言之,没有安全的秩序 - 但有一种关系。我们需要知道的是,如果在计数器值被读取时溢出计数值是最新的还是不是最新的。

static uint8_t ovf; 
if (TIFR & 1<<TOV1) { 
    TIFR = 1<<TOV1; // Clear overflow flag 
    ovf++; 
} 
if (GIFR & 1<<PCIF) { 
    GIFR = 1<<PCIF; // clear pin change flag 
    uint16_t timestamp = ovf<<8 | TCNT1; 
    if (TIFR&1<<TOV1 && (timestamp&0xff)<0x80) 
     timestamp += 0x100; // Overflow had not been counted 
    // Do what we like with the timestamp here 
} 

关键是我们已经加载定时器值后检查溢出。如果溢出发生在我们读取值之前,读取的值必须很低;否则我们希望旧计数。这个特定的示例实际上依赖于在中断中未处理的溢出,但可以通过将该块封装在中断屏蔽中来使用相同的方法。我们需要两次读取TOV1和ovf以匹配,并在TCNT1之后读取TOV1。我们不想要的是有一个中断过程,因此清除TOV1,以便我们不能推断ovf和TCNT1的顺序。请注意,使用引脚更改中断来执行此逻辑会自动授予我们,因为中断处理程序在中断禁用的情况下运行。

您的脉冲宽度不会比响应引脚变化的延迟差异更高,并且在您显示的代码中,定时器复位(也应该复位预分频器,GTCCR中的PSR1位)。这通常意味着你确实想在中断处理程序本身读取定时器。我们也可以观察到,您可以选择一个让您的阈值适合8位值的计时器速度;例如timer1以8MHz/64运行时,您的阈值应该是186和194,偏移量为16-24μs。人们甚至可以做这样的溢出精确设置一个阈值的招数,因为定时器不具有为0

+0

哇!这是一个很长很长的答案,谢谢!我需要一段时间来融合所有的信息,但我想我明白你写的是什么。在我的第一个版本的代码中,我有一个预分频器设置为8MHz/128(16μs/步),我认为当时我需要计数超过3000μs,而且这很好。我现在真的不需要1μs/ step的高分辨率,它看起来更好,我想让一些更复杂的(对我来说),但如果你想控制一个伺服或类似的东西,你需要分辨率更高。 – CrowStudio

+0

...我不确定把代码放在哪里,它是在TIMER1_OVF或PCINT的中断程序中,还是在TIMER1_OVF和另一个int PCINT中的第一个if语句?对不起,我是这个新手,需要时间去习惯思维方式,请耐心等待我;-) – CrowStudio

+0

唉!我觉得我好笨! 我已经多次阅读过你的答案,每次都以错误的方式阅读,但我想慢慢地到达那里,我想! ;-) – CrowStudio

0

@YannVernier由于开始推我朝着正确的方向,或给我分辩的方式来做到这一点! ;-)我想我终于明白了,有一位朋友的额外帮助!
下面是最终CODE 我没有拿到第一,我不得不删除TIMSK使ANDE SEI()加上ISR例程,也是后意外地把别的语句:

if (((TIFR & (1 << TOV1)) && ((pulse & 0xff))) < 0x80) 
    { 
     pulse += 0x100; // Overflow had not been counted 
    }