你好堆栈溢出的人。我的问题是一个看似永远不会执行的中断服务程序(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
}
设置定时器后,每次计数器溢出时,我都会添加一个ISR来增加滴答,所以我可以跟踪已经过了多长时间等等。
ISR(TIMER0_OVF_vect)
{
cli();
//ticks ++;
PORTB |= ( 1 << PORTB0 );
sei();
}
正如你所看到的,我注释掉了滴滴答案++,因为它没有工作,并用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;
}
所以,你在无限循环中看到的是我先尝试过的,但在那之后没有工作,我尝试了一些更简单的东西,只是有一个空循环(注释掉以前的东西),并等待中断被触发可以打开LED。
你能给予的任何帮助都会非常感激。我很困惑,为什么这还没有奏效。
答案 0 :(得分:9)
您正在使用错误的ISR,因为@andars已正确指出。在CTC&#34;清除定时器比较&#34;模式定时器永远不会溢出,因为它将在比较匹配时被清除。
所以你也启用了错误的定时器中断。 TIMSK寄存器的第1位使能Timer0上的定时器溢出中断。由于之前的原因,这不会被触发。取自datasheet。
在使用OCR0A
设置比较值时,必须使能 Bit 4 - OCIE0A:T / C0输出比较匹配A中断使能。
回到ISR,您需要ISR(TIMER1_COMPA_vect)
或ISR(TIMER1_COMPB_vect)
,具体取决于您在TIMSK中设置的位。请注意,比较值也应写入匹配寄存器OCR0A
或OCR0B
。
请注意,您可以像使用注册名一样使用代码中的位名称,在我看来,它使代码更加透明。
您的代码应按如下方式更改以启用相应的中断:
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
}
ISR:
ISR(TIMER0_COMPA_vect)
{
cli();
//ticks ++;
PORTB |= ( 1 << PORTB0 );
sei();
}