首页 > 解决方案 > ICR1 时间会错误地同步到溢出计数器吗?

问题描述

我有一个 Atmega328p,我想对其进行编程以精确捕获输入事件的时间。

但是,如果我的代码在所有情况下都可以工作,现在我遇到了一个问题。我认为这个问题与 Atmega 平台上中断的一般处理有关。

所以我的代码看起来像这样(总结):

volatile uint16_t overflow = 0;

ISR(TIMER1_CAPT_vect) {
    uint16_t captureCount = ICR1;
    uint32_t t = ((uint32_t) overflow << 16) | captureCount;
}

ISR(TIMER1_OVF_vect) {
    overflow++;
}

这应该在中断 ISR(TIMER1_CAPT_vect) 内发生输入事件时捕获,此外,定时器 1 的溢出与另一个中断一起计数。据我了解,ICR1 准确地存储了输入事件发生时 timer1 的时间,然后在短时间内触发中断以通知代码该事件发生,然后我使用当前溢出计数器计算实时时间。

我从这个答案中知道,中断内的代码不会被另一个中断(例如溢出中断)中断,因此在形式 t 中添加溢出和捕获计数是“原子的”/“线程安全的”。但我现在想知道的是,如果 ICR1 由当前的 timer1 值设置并且在发生溢出之后,在 ISR(TIMER1_CAPT_vect)通知我的代码之前会发生什么。有了这个,也许溢出中断在事件捕获中断之前运行。这将导致溢出计数器增加 1 但 ICR1 仍保持对应于旧溢出范围的时间的可能性,从而给出错误的 t。

所以一般来说,这个问题只有在触发事件捕获中断之前触发溢出中断才会发生,尽管真正的捕获事件(当 ICR1 设置为当前 timer1 时)发生在溢出之前。

这让我想到了一个普遍的问题:中断的处理顺序是否与 Atmega 上发生的实际真实事件的顺序相同?

特别是关于我的两个定时器1中断?

标签: microcontrolleratmega

解决方案


ATmega328P 数据表听起来像是地址较低的中断具有较高的优先级。因此,如果多个中断试图同时运行,我希望 AVR 选择具有最低地址的中断并运行它。

从第 6.7 节,复位和中断处理开始:

向量的完整列表显示在第 11 节“中断”(第 49 页)中。该列表还确定了不同中断的优先级。地址越低,优先级越高。RESET 具有最高优先级,其次是 INT0——外部中断请求 0。

如果 AVR 要按照您的建议运行,并记住每个中断发生的顺序,则需要大量额外的机器。

如果我们转到上面引用中提到的数据表的第 11 节,我们会看到 Timer 1 捕捉中断比 Timer 1 溢出中断具有更高的优先级(因为它具有较低的地址)。


推荐阅读