【问题标题】:AVR ATmega32U4 Timer compare interrupt not triggeringAVR ATmega32U4 定时器比较中断未触发
【发布时间】:2015-12-16 22:11:01
【问题描述】:

我试图在我的 ATmega32U4 leonardo 板上创建一个 CTC 定时器中断。当我不断检查OCF1A 的值时,检测输出何时达到所需值没有问题,但是一旦我将代码移动到中断中,中断就永远不会触发。
定时器设置:

#include <avr/io.h>

void setupTimer()
{
    TCCR1B |= (1 << WGM12); // CTC mode
    TCCR1B |= ((0 << CS10) | (0 << CS11) | (1 << CS12)); // set up prescaler
    OCR1A = 6249; // 100 ms set up output compare value for interrupt
    TIMSK1 |= (1 << OCIE1A); // enable interrupt on clock compare
}

有效的循环:

setupTimer();
for (;;) {
    if (TIFR1 & (1 << OCF1A)) {
        PORTC ^= (1 << PORTC7);
        TIFR1 = (1 << OCF1A);
    }
}

不起作用的中断:

#include <avr/interrupt.h>

ISR(TIMER1_COMPA_vect) {
    PORTC ^= (1 << PORTC7);
}

我一定遗漏了一些东西,因为我在教程中看到了上面的代码应该可以工作。这里有一个有趣的观察结果是,如果我在调用 sei() 时同时在代码中同时包含循环和中断,则 LED 不会闪烁,就好像 OCF1A 寄存器被过早清除一样。
我很确定在这种情况下它无关紧要,但保险丝如下:E:CB,H:D8,L:FF。

我使用avr-g++编译,代码分散在几个文件之间。

【问题讨论】:

  • 如果代码使用 _BV() 宏作为位掩码而不是手动移动 1,我发现代码更易于阅读。

标签: timer avr atmega avr-gcc avrdude


【解决方案1】:

鉴于有人在提出这个问题两年后通过谷歌来到这里,我想我应该分享我自己对此事的发现。

我的问题中提供的代码是正确的,并假设在setupTimer() 之后的某个地方调用了sei(),中断应该正确触发。这个问题就像c0redumb 在他的回答中描述的那样——引导加载程序弄乱了一些寄存器,从而阻止了代码正确运行。然而,我对这个问题的解决方案与我的情况略有不同,即使在拔下并重新插入电路板后中断也不会触发(自从我提出这个问题以来,引导加载程序可能在两年内发生了变化)。

防止代码和引导加载程序发生冲突的最简单方法是删除引导加载程序。通过使用 USBasp 编程器,您可以简单地将自己的代码加载到板上,从而确保它是唯一在 CPU 上运行的东西。

【讨论】:

    【解决方案2】:

    你有两个问题:

    1. 您需要确保 main() 不会返回,即使它除了等待中断之外什么都不做

    2. 您需要在设置完所有内容后通过sei() 启用中断。

    这是一个工作示例(我将 LED 端口更改为 PB5,因为我已经在 Arduino Uno 上对此进行了测试,并且已经内置了 LED)

    #include <avr/interrupt.h>
    #include <avr/io.h>
    
    void main ()
    {
        DDRB |= 1 << DDB5;
    
        TCCR1B |= 1 << WGM12;
        TCCR1B |= 1 << CS12;
        OCR1A = 6249;
        TIMSK1 |= 1 << OCIE1A;
    
        sei();
        for(;;);
    }
    
    ISR(TIMER1_COMPA_vect)
    {
        PORTB ^= 1 << PORTB5;
    }
    

    【讨论】:

    • 是的,我知道并且我做了你提到的这两件事,我只是在我的问题中只包含了代码中最相关的部分。中断未触发的问题仍然存在,我可以看到 3 个可能的来源:代码、makefile 或熔断器。在这一点上,除非我错过了一些奇怪的注册表设置,否则问题可能不是代码,我不确定是否有可能通过 makefile 或 fuse 设置引起这样的问题。
    【解决方案3】:

    这个问题今天也让我很困惑。通过搜索我找到了你的问题。我又做了一些搜索,但没有找到这个答案。我原以为我一定忘记启用某些电路或设置某些标志。最后,用一个 LED 作为我的调试器,我找到了原因。

    问题在于引导加载程序,而不是您的代码。为了让它工作,你只需从 USB 上拔下板子(在通过引导加载程序编写代码之后),然后重新插入,这样引导加载程序就会在通电时直接跳转到你的代码,它在那里工作。引导加载程序在上传代码时一定做了一些花哨的工作,但在这种情况下之后就不能正常工作了。

    作为参考,我使用了 ProMicro 板,我相信它的 Caterina 引导加载程序与您使用的 Leonardo 板相同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-22
      • 2020-10-07
      • 2021-12-20
      • 2017-04-03
      • 1970-01-01
      • 2012-02-07
      • 1970-01-01
      相关资源
      最近更新 更多