AVR定时器溢出中断不起作用

che*_*hen 5 c embedded avr interrupt attiny

你好堆栈溢出的人.我的问题是一个看似永远不会执行的中断服务程序(ISR)!以下是我设置的一些信息:我正在闪烁avr attiny85.到目前为止,我只使用main.c和两个模块设置项目的基础:timer和hardwareInit.在定时器模块中,我有一个timer0_init函数,我用它来设置Timer0以使CTC模式在1 ms内溢出.这是功能:

void timer0_init( void )
{
    cli();
    TCCR0B |= 3;    //clock select is divided by 64.
    TCCR0A |= 2;    //sets mode to CTC
    OCR0A = 0x7C;   //sets TOP to 124 so the timer will overflow every 1 ms.    
    TIMSK |= 2;     //Enable overflow interrupt
    sei();          //enable global interrupts
}
Run Code Online (Sandbox Code Playgroud)

设置定时器后,每次计数器溢出时我都会添加一个ISR来增加滴答,这样我就可以跟踪已经过了多长时间等等.

ISR(TIMER0_OVF_vect)
{
    cli();
    //ticks ++;
    PORTB |= ( 1 << PORTB0 );   
    sei();
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我注释掉了滴滴答用器因为它没有工作,并用PORTB |= ( 1 << PORTB0 );简单的LED打开就取而代之,所以如果中断被执行,我会通过证明LED亮起来知道.
不幸的是,我无法让它打开,看不到我错过的东西.(为了证明我1.将LED设置在右侧引脚上,并且2.正在操作正确寄存器中的正确位,我将此声明PORTB |= ( 1 << PORTB0 );放在我的无限循环中并确认LED亮起)

有关进一步说明,请参阅我的main.c:

/*================================= main.c =================================*/

#define F_CPU   8000000UL

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#include "timer.h"
#include "hardwareInit.h"


int main(){

    //Initialize hardware HERE  
    DDRB |= ( 1 << PORTB0 );    //set this pin as an output for an LED

    SetClockPrescale(1);    //internal clock divided by 1 = 8 MHz, from hardwareInit

    timer0_init();          //set up timer0 for 1 ms overflow


    while(1)
    {
        /* if( getTicks() > 0 )
        {
            PORTB |= ( 1 << PORTB0 );
            _delay_ms(1000);
            PORTB &= ~( 1 << PORTB0 );
            _delay_ms(1000);
        } */

    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以,你在无限循环中看到的是我首先尝试过的,但是在那之后没有用,我尝试了一些更简单的东西,只是有一个空循环(注释掉以前的东西),并等待中断被触发,这将是打开LED.

你能给予的任何帮助都会非常感激.我很困惑为什么这个没有用.

Ben*_*ics 9

您正在使用错误的ISR,因为@andars已正确指出.在CTC"比较时清零定时器"模式下,定时器永远不会溢出,因为它将在比较匹配时清零.

所以你也启用了错误的定时器中断.TIMSK寄存器的第1位使能Timer0上的定时器溢出中断.由于之前的原因,这不会被触发.取自数据表.

在此输入图像描述

OCR0A用于设置比较值时,必须使能 位4 - OCIE0A:定时器/计数器0输出比较匹配A中断使能.

回到ISR,您需要ISR(TIMER1_COMPA_vect)ISR(TIMER1_COMPB_vect)取决于您在TIMSK中设置的位.注意,比较值也应该写入匹配寄存器,OCR0AOCR0B.


请注意,您可以在代码中使用位名称,就像寄存器名称一样,在我看来,它使代码更加透明.

您的代码应如下更改以启用相应的中断:

void timer0_init( void )
{
    cli();          
    TCCR0B |= (1<<CS01) | (1<<CS00);   //clock select is divided by 64.
    TCCR0A |= (1<<WGM01);              //sets mode to CTC
    OCR0A = 0x7C;                      //sets TOP to 124 so the timer will overflow every 1 ms.    
    TIMSK |= (1<<OCIE0A);              //Output Compare Match A Interrupt Enable
    sei();                             //enable global interrupts
}
Run Code Online (Sandbox Code Playgroud)

ISR:

ISR(TIMER0_COMPA_vect)
{
    cli();
    //ticks ++;
    PORTB |= ( 1 << PORTB0 );   
    sei();
}
Run Code Online (Sandbox Code Playgroud)