首页 文章

将偏移量添加到预分频硬件定时器时,如何避免这种逐个错误?

提问于
浏览
5

我正在写一个微控制器中断,需要为其中一个硬件定时器添加一个偏移量 . 但是,由于定时器预分频器的工作方式,根据相对于预分频器时钟的中断执行时序,原始方法可能会引入逐个错误 .

timing diagram of ISR off-by-one error

我在ATmega328P(= arduino)上使用定时器1 . 我使用/ 8预分频器在正常模式下进行设置,并使用定时器捕获中断来触发此操作;中断的目标是在触发输入捕获的事件之后将定时器设置为完全溢出 period 个周期(如果在另一个中断或其他禁用中断的情况下发生触发) .

(我正在滥用PWM输出以在可变AC相位偏移处触发两个主电源光耦,而不需要在其上烧掉所有CPU时间;中断由电源相上的过零检测器触发 . )

ISR的代码是这样的:

uint_16 period = 16667;

ISR(TIMER1_CAPT_vect){
    TCNT1 = TCNT1 - ICR1 - period + (elapsed counter ticks during execution);
}

这里的临界间隔是从 TCNT1 读取到何时再次写入之间的临界间隔 .

据我所知,没有办法直接读取预分频器的状态,所以我认为不可能只根据ISR时序应用不同的偏移量 .

我可以在ISR( GTCCR |= _BV(TSM); GTCCR |= _BV(PSRSYNC); GTCCR &= ~_BV(TSM); )之前重置预分频器以进行同步,但这仍然会向定时器引入随机偏移,这取决于ISR时序 .

我正在考虑的另一种方法是使用定时器来产生与预分频器同步的中断 . 我已经在定时器1上使用了两个输出比较寄存器,但是定时器0共享预分频器,因此可以使用它 . 但是,定时器中断执行可能最终被另一个中断或“cli”块延迟,因此无法保证工作 .

如何编写中断以避免此错误?

1 回答

  • 1

    如果你把ISR写成

    ISR(TIMER1_CAPT_vect){
        int counter = TCNT1 - ICR1 - period + 3;
        asm("nop");
        asm("nop");
        TCNT1 = counter;
    }
    

    写入 TCNT1 应该在读取寄存器后的24个周期内进行,因此在同一个预分频器'phase' . (在 ICR1 的设置和 TCNT1 的读取之间发生的nop 's may be adjusted if neccessary, e.g. due to variations between different microcontroller types). However, the solution is not able to take into account the change in prescaler '阶段的数量 .

相关问题