需要帮助计时器

时间:2010-11-04 17:26:04

标签: c embedded avr

过去2周我正在尝试学习计时器&中断&写了一个程序(据我的理解)在ATMEGA2560上闪烁LED,但无论我做什么,TCNT0都不会增加&永远不会调用ISR()函数。我哪里出错了,我该如何解决?这是我的代码:

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

#define READ_ATMEGA(ADDR) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER)))
#define WRITE_ATMEGA(ADDR, DATA) *((P_CHAR)(BASE_ADDR + ((ADDR) * ADDR_MULTIPLIER))) = DATA

#define BASE_ADDR 0x20

void init_timer0_ovf_interrupt(void);
void timer0_interrupt_isr(void);
void initialize_ports(void);
 void delay(unsigned int no_65_5ms_interrupts);

 void __attribute__((ISR)) timer0_interrupt_isr(void);

 //#pragma interrupt_handler timer0_interrupt_isr:24

 unsigned int delay_timer;

 int main(void)
 {
  initialize_ports();
 init_timer0_ovf_interrupt();
 delay(46);
 return 0;
  }

 void initialize_ports(void)
 {
  READ_ATMEGA(4) = 0xff;
  WRITE_ATMEGA(5, 0x00);
 }

 void delay(unsigned int no_65_5ms_interrupts)
 {
  TCNT0 = 0x00;
  delay_timer = 0;
  while(delay_timer <= no_65_5ms_interrupts)
  {
   ;
  }
 }

 void init_timer0_ovf_interrupt(void)
 {
  TCCR0A = 0X00;
  TCCR0B = 0x02;
  TIMSK0 = 0x01;
  TIFR0 = 1<<0;
  OCR0A = 25;
   sei();
 }

 void timer0_interrupt_isr(void)
 {
  delay_timer++;
  if(delay_timer >= OCR0A)
  {
   PORTB = ~(PORTB);
   delay_timer = 0;
  }
 }

3 个答案:

答案 0 :(得分:1)

全局变量delay_timer在中断和非中断代码之间共享。它应声明为volatile,因为值可以在delay()之外更改。

如果查看生成的delay()代码,您可能会看到在while循环中旋转时不会重新读取delay_timer的值。

另外,volatile还不够。你有非中断代码和中断代码写入同一个变量(delay_timer)。你需要在非中断代码中保护对变量的写入,那里存在竞争条件。简单/懒惰的方法是禁用中断和在非中断代码中恢复它们。

(至于设置你的中断和启动你的计时器,这些信息应该在芯片的数据表中。通常这是更容易理解的部分,它是咬人的共享数据。)

答案 1 :(得分:1)

3-4天前,我用同样的方式编写了相同的程序。 LED眨眼但仍不确定是否正确使用定时器和放大器。打断。任何人都可以看到这个&amp;告诉我这是否正确?我设法通过读取计时器,中断程序来编写这个程序。

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

volatile uint8_t intrs;

ISR(TIMER0_OVF_vect) {
    /* this ISR is called when TIMER0 overflows */
    intrs++;

    /* strobe PORTB.5 - the LED on arduino boards */
    if (intrs >= 61){
        PORTB = ~PORTB;
        intrs = 0;
    }

}


int main(void) {

    TCCR0B = 0x02;

    /* Enable Timer Overflow Interrupts */
    TIMSK0 = 0x01;

    /* other set up */
    DDRB = 0xff;
    TCNT0 = 0;
    intrs = 0;

    /* Enable Interrupts */
    sei();

    while (1)
        ; /* empty loop */
}

如果这是正确的方法,那么我可以开始下一步了。

由于

答案 2 :(得分:0)

如果延迟函数中的while循环可能没有做任何事情而且不会增加delay_timer,那么你就会陷入无限循环:

void delay(unsigned int no_65_5ms_interrupts) 
 { 
  TCNT0 = 0x00; 
  delay_timer = 0; 
  while(delay_timer <= no_65_5ms_interrupts) 
  { 
   ; //Nothing is happening here!!
  } 
 }