我有一个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的时间,然后在一段短时间后触发中断来通知代码发生了这个事件,然后我使用current overflow计数器计算了实时。
我从this answer中得知,中断中的代码不会被另一个中断(例如溢出中断)中断,因此在形式t中添加overflow和captureCount是“原子的”/“线程安全的”。但我现在想知道的是,如果ICR1是由当前ISR值设置的,然后在timer1 (TIMER1_CAPT_vect)通知我的代码之前发生溢出,会发生什么情况。这样,溢出中断可能在事件捕获中断之前运行。这将导致溢出计数器增加1的可能性,但是ICR1仍然保持与旧溢出范围相对应的时间,从而给出错误的t。
因此,通常只有在触发事件捕获中断之前触发溢出中断时才会出现此问题,尽管真正的捕获事件(当ICR1设置为current timer1)发生在溢出之前。
这就引出了一个总体问题:中断的处理顺序是否与Atmega上实际发生的真实事件的顺序相同?
尤其是关于我的两次timer1中断?
发布于 2020-10-27 01:08:21
ATmega328P数据表使其听起来似乎具有较低地址的中断具有较高的优先级。因此,如果多个中断试图同时运行,我希望AVR选择具有最低地址的中断并运行它。
从6.7节重置和中断处理:
矢量的完整列表如第11节所示。“中断”,第49页。该列表还确定不同中断的优先级。地址越低,优先级越高。复位具有最高优先级,其次是INT0,即外部中断请求0。
如果AVR要像你建议的那样运行,就需要很多额外的机器,并记住每个中断发生的顺序。
如果我们转到上面引述的数据表的第11节,我们会看到定时器1捕获中断比定时器1溢出中断具有更高的优先级(因为它的地址较低)。
https://stackoverflow.com/questions/64536189
复制相似问题