关于定时器0溢出中断的疑问

2014-03-271.5万


#define MICROSECONDS_PER_TIMER0_OVERFLOW (clockCyclesToMicroseconds(64 * 256))
#define MILLIS_INC (MICROSECONDS_PER_TIMER0_OVERFLOW / 1000)
#define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
#define FRACT_MAX (1000 >> 3)
volatile unsigned long timer0_overflow_count = 0;
volatile unsigned long timer0_millis = 0;
static unsigned char timer0_fract = 0;
ISR(TIMER0_OVF_vect)
{
        // copy these to local variables so they can be stored in registers
        // (volatile variables must be read from memory on every access)
        unsigned long m = timer0_millis;
        unsigned char f = timer0_fract;

        m += MILLIS_INC;
        f += FRACT_INC;
        if (f >= FRACT_MAX) {
                f -= FRACT_MAX;
                m += 1;
        }

        timer0_fract = f;
        timer0_millis = m;
        timer0_overflow_count++;
}
unsigned long micros() {
        unsigned long m;
        uint8_t oldSREG = SREG, t;
        
        cli();
        m = timer0_overflow_count;
#if defined(TCNT0)
        t = TCNT0;
#elif defined(TCNT0L)
        t = TCNT0L;
#else
        #error TIMER 0 not defined
#endif

  
#ifdef TIFR0
        if ((TIFR0 & _BV(TOV0)) && (t < 255))
                m++;
#else
        if ((TIFR & _BV(TOV0)) && (t < 255))
                m++;
#endif

        SREG = oldSREG;
        
        return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
}
Arduino底层库中有这样一些代码,看到micros()函数,我就想到了一个问题:单片机开了定时器0的溢出中断,定义了中断函数,以上代码就是的。如果在快要计数溢出时,比如250,由于需要读取micros,会执行cli()函数,把总中断关闭。过了一会读取完毕后,可能这时定时器已经溢出后重新开始了,比如计数到20。那么退出micros()会执行sei()函数,把中断打开,此时刚才的中断函数仍会执行吗?还是会忽略上一次未执行的中断直接等待下一次的中断?求高手指点江山啊

创作许可协议

本项目采用 None(不开放任何权利,保留所有权利) 进行许可。

评论(2)
Youyou
Youyou
作者
基本上有两种类型的中断。第一种类型是由设置中断标志事件触发。对于这些中断,程序计数器跳转到实际的中断子程序入口,以执行中断处理程序,同时硬件将清除相应的中断标志。中断标志也可以通过写逻辑“1”,来清除该标志位。如果在相应的中断使能位被清除之后,中断条件发生时,中断标志将被设置,并一直保持到中断执行,或者该标志由软件清零。同样,如果全局中断使能位被清除,当一个或多个中断发生时,相应的中断标志位置位并记住,直到全局中断使能位置位,然后根据优先顺序来执行。
Angleo
Angleo

引自Mega2560 datasheet 19页
- 没有更多了 -