8177浏览
查看: 8177|回复: 2

[讨论] 关于定时器0溢出中断的疑问

[复制链接]
本帖最后由 Youyou 于 2014-3-27 13:20 编辑

#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()函数,把中断打开,此时刚才的中断函数仍会执行吗?还是会忽略上一次未执行的中断直接等待下一次的中断?求高手指点江山啊

Angelo  初级技匠

发表于 2014-3-28 11:38:58

There are basically two types of interrupts. The first type is triggered by an event that sets the Interrupt Flag. For these interrupts, the Program Counter is vectored to the actual Interrupt Vec- tor in order to execute the interrupt handling routine, and hardware clears the corresponding Interrupt Flag. Interrupt Flags can also be cleared by writing a logic one to the flag bit position(s) to be cleared. If an interrupt condition occurs while the corresponding interrupt enable bit is cleared, the Interrupt Flag will be set and remembered until the interrupt is enabled, or the flag is cleared by software. Similarly, if one or more interrupt conditions occur while the Global Interrupt Enable bit is cleared, the corresponding Interrupt Flag(s) will be set and remembered until the Global Interrupt Enable bit is set, and will then be executed by order of priority.

引自Mega2560 datasheet 19页
回复

使用道具 举报

Youyou  初级技匠
 楼主|

发表于 2014-3-28 11:51:08

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

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail