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)中发生输入事件时,这应该捕获,此外,将Timer1的溢出与另一个中断一起计数。据我所知,ICR1准确地存储了输入事件发生时Timer1的时间,然后不久后触发了中断以通知代码该事件发生,然后我使用当前的溢出计数器计算了实时时间。

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

因此,尽管真正的捕获事件(当ICR1设置为当前的timer1时)发生在溢出之前,但通常只有在触发事件捕获中断之前触发了溢出中断时,才会出现此问题。

这使我想到了一个普遍的总体问题:在Atmega发生的中断与实际的真实事件的处理顺序相同吗?

特别是关于我的两个timer1中断?

解决方法

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

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

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

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

如果我们如上引述中所述进入数据表的第11节,我们会发现定时器1捕获中断的优先级高于定时器1溢出中断的优先级(因为它的地址较低)。