C 使用时间溢出中断时出现故障

C 使用时间溢出中断时出现故障,c,timer,interrupt,avr,attiny,C,Timer,Interrupt,Avr,Attiny,我想,我的内存中的溢出中断(用于将8位计时器的分辨率从16µs/步提高到1µs/步)有一些问题。当程序在我的主循环中的if语句中时,溢出中断似乎会触发,从而导致出错 if(pInt == 1) //PCNINT-if-statment { pulse16 = (tot_overflow << 8) | TCNT1; //adds tot_overflow and TCNT1 to be abl

我想,我的内存中的溢出中断(用于将8位计时器的分辨率从16µs/步提高到1µs/步)有一些问题。当程序在我的主循环中的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   
    }
if(pInt==1)//pcnit if station
{           

pulse16=(tot_溢出是,溢出中断可能随时发生(尽管它确实定期发生)。引脚更改中断也可能发生。在这种情况下,它们中的每一个都只接触一个8位易失性变量(
tot_溢出
pInt
),然后由主循环轮询。除非主循环有其他工作要做,这些工作可能需要超过一个完整的计时器周期(在这种情况下,256*8=2048个周期),否则这种构造并不能真正帮助您

因此,您可以检查GIF位PCIF(而不是pInt),而不是启用中断和TIFR位为主循环中的V1,这将使您更容易理解行为。重置它们是将1写入该位且仅写入该位的特殊情况。这将为您节省引脚更改中断的时间,因为主循环检查可能会更频繁地进行,并且不需要跳到中断服务路由的延迟伊恩

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

当出现计时器溢出时,会增加tot_溢出,当检测到引脚变化时,会读取TCNT1以合并值。这两个计数器(其中一个为另一个提供数据)不会同时读取。阈值为0x5d2和0x613。如果在读取tot_溢出后但在读取TCNT1之前发生翻转,则很可能会在应该是0x601的时间获得类似于0x501的时间。类似地,如果您停止更新tot_溢出。如果您在tot_溢出之前读取了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
}
static uint8\u t ovf;

如果(TIFR&1@YannVernier感谢你把我推向了正确的方向,或者给了我正确的方法!;-)我想,在一位朋友的小小帮助下,我终于成功了!
这是决赛 首先我没有意识到我必须删除TIMSK enable ande sei()和ISR例程,还有意外放在后面的else语句:

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

if((TIFR&(1)我真的很感兴趣为什么有人否决了这一点。对我来说,这似乎是一个很好的记录问题。OP甚至懒得包括一个视频。在我看来,你的计时器处理看起来还不错。也许你的代码中有一些我不知道的其他逻辑错误。代码足够小,可能有助于再次重写它。也许它修复了它的错误f、 它不在if语句中,而是行设置脉冲16;这两个读数根本不能同时发生。@jwsc我被否决的原因可能是因为我编辑前帖子的外观。我总是在发布后编辑帖子,因为我经常会错过一些东西,或者在发布后看到一些我第一次没有添加的东西,糟糕习惯!你可以检查我的第一个版本,如果你愿意的话,然后再判断;-)我不知道如何显示我的新代码,所以我编辑了我的第一篇文章,并在那里添加了代码@YannVernierWow!这是一个很长很好的答案,谢谢!我需要一些时间来消化所有信息,但我想我理解你写的内容。在我的第一个版本的代码中,我将预分频器设置为8MHz/128(16µs/步),当时我认为我需要数到3000µs以上,这非常有效。我现在真的不需要1µs/步的高分辨率,它看起来更好,我想做一些更复杂的东西(对我来说),但如果你想控制伺服或类似的东西,你需要更高的分辨率……我不知道该把代码放在哪里,它是在TIMER1_OVF或PCINT的中断例程中,还是在TIMER1_OVF和其他int PCINT中的第一个if语句中?对不起,我对这一点很陌生,需要时间来适应思维方式,请b我对我很耐心;-)啊!我觉得自己很愚蠢!我已经读了很多遍你的答案,每次都读错了,但我想我正在慢慢地到达那里!;-)
        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
{ 

}
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
}
    if ( ((TIFR & (1 << TOV1)) && ((pulse & 0xff))) < 0x80)
    {
        pulse += 0x100;   // Overflow had not been counted
    }