AVR上的定时器逻辑

时间:2015-08-07 17:55:32

标签: timer logic avr

我试图理解这段代码,我无法理解的是当OCR1A得到更新时中断例程是如何工作的。我正在使用AVR系列控制器来运行此代码。

 void TimerInit(void)
    {
        DISABLE_TIMER_INT;  // Disable timer interrupt

        m_nGlobalTime = 0;  // Reset system time

        OCR1A  += TICKS_PER_MSECOND;    // Set first clock period

        TCCR1A  = 0;// Set TimerMode to Normal
        TCCR1B |= (1 << CS10);// ClckIo, no pre-scaler; set TimerMode

        ENABLE_INTERRUPTS;
        ENABLE_TIMER_INT;// Enable send timer interrupt (1 ms)
    }



    ISR( TIMER1_COMPA_vect) {
        uint16_t nTemp; 

        nTemp = TCNT1;  // Get current time
        nTemp -= OCR1A; // Subtract interrupt time

        if (nTemp < (TICKS_PER_MSECOND / 2))// If more than half period left    
        {
            OCR1A += (TICKS_PER_MSECOND);// Add Offset to OCR1A relative
        } 
        else
        {
            OCR1A = TCNT1 + (TICKS_PER_MSECOND);// Set OCR1A to 1 ms absolute
        }

        m_nGlobalTime++;                                                            
    }

1 个答案:

答案 0 :(得分:0)

以常规间隔获取输出比较中断的常用方法是向OCR1A添加一个常量。这发生在

OCR1A += (TICKS_PER_MSECOND);

出于某种原因,作者增加了一些额外的逻辑来处理坏运气。也许,周期太短,或者由于某些其他中断运行,OC中断可能会延迟。

如果发生这些情况,则下一个OC中断不会比最后一个发生TICKS_PER_MSECOND,而是TICKS_PER_MSECOND加上计数器的整个周期。也就是说,错过了正确的时间,因为OC寄存器将在数字通过后设置为一个数字。

此代码试图纠正这种情况。话虽如此,我不确定它是否正常工作。潜在的问题是nTemp是无符号的,因此<比较可能不会达到作者所期望的。