mega8 Timer Interrupt funktioniert nicht.

#976348
Lesenswert?

Hallo zusammen. Habe ein kleines Problem. Die ISR des Timers 0 wird 
einfach nicht aufgerufen. Ich weiß einfach nicht wo der Fehler sein 
soll.

Hier mein Code:
1
#include <avr/io.h>
2
#include <stdlib.h>
3
#include <avr/interrupt.h>
4

5
ISR(TIMER0_OVF_vect)
6
{
7
  PORTD = 0x00;
8
}
9

10
int main(void)
11
{
12
  DDRC = 0b00111100;
13
  DDRD = 0b11111111;
14

15
  TCCR0 |= (1 << CS00) | (1 << CS01);
16
  TIMSK |= TOIE0;
17
  sei();
18

19
  PORTD = 0xFF;
20

21
  while(1);
22
}

Zur Info: An Port D hängen LEDs. Sie werden testweise am Anfang 
eingeschaltet und sollten durch die erste ISR wieder aus gehen.

Wo steckt der Fehler??

Gruß, Dominik
#1095194
Lesenswert?

Hallo,

ich habe auch mal noch eine Frage zur Timerverwendung. Und zwar habe ich 
versucht dieses Beispiel ( 
http://www.mikrocontroller.net/mc-project/Pages/AVR/Software/timer_bsp_interrupts.c 
) auf meinen Atmega8 und AVR-Studio 4 anzupassen.

Es wird zwar ohne Fehler compiliert, aber der Simulator meckert: AVR 
Simulator: Uninitialized stack pointer used at 0x0061 ... und ähnliche 
Fehler (screen01)

Auch wenn ich den Code übertrage, tut sich am PortB nicht. Was mache ich 
falsch? Stimmt evtl. etwas mit den Fuse-Bits nicht (screen02)?



Hier mein Code:

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

volatile char count, i;

int main (void) {
  DDRB = 255;
  TIMSK = (1<<TOIE0);
  TCNT0 = 0;
  TCCR0 = (1<<CS00) | (1<<CS01);
  sei();
  while (1) {
  i=1;
  }
  return 0;
}

ISR (TIMER0_OVF_vect) {
  if (count == 1) {
    PORTB = 255;
    count--;
    return;
  }
  if (count == 0) {
    PORTB = 0;
    count++;
    return;
  }
}
Angehängte Dateien:
Persönliche Seite #1095209
Lesenswert?

@  Heiko B.

Ich kann den Fehler mit AVR-Studio 4.12 SP2 und WinAVR 20071222 
nicht nachvollziehen.

Die Adresse 0x000061 liegt bei meinem Disassembler-Listing in der ISR 
und in der Nähe des 1. return. Probiere mal die ISR so umzuschreiben, 
dass die ISR nur an einer Stelle verlassen wird z.B. so:
1
ISR (TIMER0_OVF_vect) {
2
  if (count == 1) {
3
    PORTB = 255;
4
    count--;
5
  }
6
  else if (count == 0) {
7
    PORTB = 0;
8
    count++;
9
  }
10
}
Gast #1095214
Lesenswert?

1
ISR (TIMER0_OVF_vect) {
2
  if (count == 1) {
3
    PORTB = 255;
4
    count--;
5
    return;
6
  }
7
  if (count == 0) {
8
    PORTB = 0;
9
    count++;
10
    return;
11
  }
12
}

Das ginge bei den neueren AVRs auch einfacher:
1
ISR (TIMER0_OVF_vect) {
2
  PINB = 0xff;
3
}

Damit lassen sich Optimierungs-Bedingte Fehler einfacher ausschliessen 
wenn man eh nur einen Pin toggeln möchte.
Persönliche Seite #1095588
Lesenswert?

Aufruf von main() aus dem AVR Startupcode heraus, nach den ganzen 
Initialisierungen wird mit CALL gemacht. Und das mosert der Debugger an.
1
+00000061:   940E0067    CALL    0x00000067       Call subroutine

Wenn du meine Disassembler-Listing anschaust, dort wird statt CALL ein 
RCALL gemacht und alle JMP am Anfang sind RJMPs.

Es wurde bei deinem Listing beim Kopilieren eine AVR Architektur 
benutzt, für die das (avr-lic interne) Makro _AVR_HAVE_JMP_CALL_ 
definiert ist.

Ich kann mir fast nur vorstellen, dass bei dir als Device kein Atmega8 
sondern ein anderer AVR eingestellt ist. Der Atmega8 braucht die 
Architektur avr4 und bei der ist dieses Makro nicht definiert. In 
einem korrekten Listing für Atmega8 müssen RJMP und RCALL auftauchen.

Kontrolliere bitte mal die Seite (Menü) -> Project -> Configuration 
Options in AVR-Studio, ob du wirklich den atmega8 eingestellt hast. 
Dann einmal alles sauber machen (Clean bei Build...) und neu übersetzen.
#1096611
Lesenswert?

Hallo Stefan,

danke für deine Hilfe. Es war wie du es sagtest. Ich hatte tatsächlich 
den falschen Controller eingestellt. Jetzt funktioniert das ganze 
einwandfrei.

Hier nochmal für alle die es intressiert der Code: Ich nutze das 
AVR-Studio Version 4.14. Es wird der Timer0 beim Atmega8 verwendet. 
Alles Pins des PortB blinken bei einer Prozessorfrequenz von 4 MHz mit 
ca. 0,5 Hz. Es ist lediglich ein erstes Beispielprogramm zur Verwendung 
des Timer0. Die genaue Ausgangsfreqenz habe ich nicht ermittelt.

/*Testprogramm Timer0
  Bei einer Prozessorfrequenz von 4 MHz, wird an Port B eine
  Blinkfrequenz von ca. 0,5 Hz ausgegeben*/

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

volatile char count=0;
volatile char zeitvorgabe=32;    //32 => ca. 0,5 Hz bei Prozessorfreq. 4 
MHz (16 => ca. 1 Hz)
volatile char zeitvorgabe_halbe=0;

/*volatile Variablen können im Zyklischen-Programm und in
Interruptroutinen verwendet werden*/

int main (void) {    //Zyklische-Programm
  DDRB = 255;      //PortB als Ausgangsport definieren
  TIMSK = (1<<TOIE0);  //Beim Timeroverflow von Timer0 Interruptroutine 
starten
  TCNT0 = 0;      //Timer0 Register auf Null setzen
  TCCR0 = (1<<CS00) | (1<<CS02);  //Vorteiler einstellen (Prozesorfreq. 
durch 1024)
  sei();        //Globale Interrupt-Freigabe setzen
  zeitvorgabe_halbe=zeitvorgabe/2;  //Berechnung zur Zeitvorgaben
  while (1) {}      //Endlosschleife Zyklische Programm
  return 0;        //Rückgabewert der main-Funktion
}

ISR (TIMER0_OVF_vect) {  //InterruptServiceRoutine für Timeroverflow0
  if (count >= zeitvorgabe) {
   count = 0;
    return;
  }
  else if (count >= (zeitvorgabe_halbe)) {
    PORTB = 0;    //LEDs an (STK 500)
    count++;
    return;
  }
  else {
    PORTB = 255;  //LEDs aus (STK 500)
   count++;
    return;
  }
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren