Forum: Mikrocontroller und Digitale Elektronik Timer0 interrupt


von Bernd (Gast)


Lesenswert?

Hallo

habe auf dem Gebiet AVR noch recht wenig Erfahrung, deshalb bitte etwas 
Nachsicht ;-)

ich versuche mit dem Timer0 (AT90S8515) einen interrupt zu erzeugen. 
Aber irgendwie funzt das im Simulator von AVR Studio nicht. Ich weiss 
beim besten Willen nicht mehr wo ich noch suchen soll.
Hat jemand eine Idee und kann mir helfen?

Im Voraus schonmal vielen Dank.


Der Sourcecode sieht so aus und macht natürlich nicht wirklich Sinn. Wie 
gesagt sind die ersten Gehversuche.

#include <avr/interrupt.h>

int main(void)
{

InitTimer();

  while(1)
  {
  ;
  }
}


void InitTimer()
{

TCCR0 =TCCR0 | (1<<CS00);
TIMSK = TIMSK | (1<<TOIE0);

sei();
}


ISR(TIMER0_OVF_vect)
{
static int a = 0;

a++;
}

von Johannes M. (johnny-m)


Lesenswert?

Bernd wrote:
> habe auf dem Gebiet AVR noch recht wenig Erfahrung, deshalb bitte etwas
> Nachsicht ;-)
Naja, jeder hat mal angefangen (auch wenn manch einer das scheinbar 
schon vergessen hat...)

> ich versuche mit dem Timer0 (AT90S8515)
Oh, ein historischer AVR. Solltest vielleicht mal bei Gelegenheit auf 
was Aktuelles umsteigen...

> einen interrupt zu erzeugen.
> Aber irgendwie funzt das im Simulator von AVR Studio nicht.
Zunächst mal hat der Simulator manchmal so seine Problemchen mit Timern. 
Allerdings stellt sich natürlich auch die Frage, wie Du simulierst...

> Der Sourcecode sieht so aus und macht natürlich nicht wirklich Sinn.
Macht nicht nur nicht viel Sinn, sondern müsste auch mindestens zwei 
fette Fehler produzieren:
- Du hast die avr/io.h nicht eingebunden, weshalb überhaupt keine 
I/O-Register bekannt sind
- Die Funktion InitTimer ist zum Zeitpunkt ihres Aufrufes unbekannt 
(kein Prototyp, Definition erst weiter unten)

Das kann so schon mal gar nicht compilieren und deshalb auch nichts 
Simulierbares ergeben.

Lies Dir bitte im AVR-GCC-Tutorial mal durch, wie es geht. Und ein 
C-Buch wäre auch nicht verkehrt.

Außerdem solltest Du Code, den Du hier postest, auch vernünftig 
formatieren. Die Forensoftware hat dafür extra eine Möglichkeit, die 
unter den Forenregeln angegeben ist.

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Der Code sieht OK aus.

Wo hast du den Breakpoint im Simulator sitzen? Mein Vorschlag ist 
Position #1 (s.u.).

Gibt es in der Doku von deinem AVR Studio (welche Version?) eine Liste 
mit bekannten Problemen bei der Simulation von Timern?

Nebensachen:

Das Forum besitzt eine schöne Möglichkeit zur Formatierung von 
Quelltexten ;-)

Die Reihenfolge der Funktionen wurde etwas umsortiert. Die wichtige ISR 
am Anfang, dann die Hilfsfunktionen (damit der Compiler deren Prototypen 
kennt) und am Schluss die main(). Ist auch eine gängige Leseordnung von 
Programmierern.

sei() wurde aus der InitTimer() nach main() verschoben: Wenn es später 
mal noch andere Interrupts gibt, sollte sei() nach allen 
Initialisierungen gemacht werden.
1
#include <avr/io.h>        // ADD: Anmerkung von Johannes M.
2
#include <avr/interrupt.h>
3
4
ISR(TIMER0_OVF_vect)
5
{
6
  static int a = 0;
7
  a++; // Breakpoint #1 im Simulator
8
}
9
10
void InitTimer(void)
11
{
12
  TCCR0 = TCCR0 | (1<<CS00);  // Prescaler CK/8
13
  TCNT0 = 0;
14
  TIMSK = TIMSK | (1<<TOIE0);
15
}
16
17
int main(void)
18
{
19
  InitTimer();
20
  sei();
21
22
  while(1)
23
  {
24
  }
25
}

von Bernd (Gast)


Lesenswert?

Vielen Dank für die Antworten. Hat sich aber auch schon erledigt. Man 
muss eben nur den richtigen µC im Simulator wählen und schon geht es. 
Das hätte ich auch schneller haben können.

von Johannes M. (johnny-m)


Lesenswert?

Bernd wrote:
> Vielen Dank für die Antworten. Hat sich aber auch schon erledigt. Man
> muss eben nur den richtigen µC im Simulator wählen und schon geht es.
> Das hätte ich auch schneller haben können.
Mit dem Code? Nie im Leben! Jetzt veräppelst Du uns aber.

von Bernd (Gast)


Lesenswert?

jo, mit dem code!
hab lediglich die beiden Header die im posting fehlen nicht mit ins 
posting kopiert, aber trotzdem waren sie da. ok, wenn man die Funktionen 
so herum schreibt braucht man nur den io.h, aber auch der war vorhanden 
im orginal code.

von Johannes M. (johnny-m)


Lesenswert?

Also doch nicht mit dem Code, sondern mit einem, den wir hier nicht 
sehen können!

von Christoph P. (sirbundy)


Lesenswert?

Hallo!
Ich hab mir aufgrund des ähnlichen Problems mal diesen Thread für meine 
Frage geschnappt. Leider konnt ich es trotz diverser ähnlicher 
Forenbeiträge und Artikel noch nicht lösen. Ich habe mir mal das 
Beispiel des Zählers des Funk-AVR-Evaluationsboardes ausgesucht 
http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#2-Bit_Z.C3.A4hler
Mittels eines längeren Tastendruckes wollte ich nun den Zähler (counter) 
wieder auf Null setzen. Mit der deklarierten Variable repeater hat das 
auch geklappt. Das habe ich jetzt auskommentiert und wollte es mit dem 
Timer0 und einer ISR lösen, verzweifle daran aber seit gestern. Es geht 
quasi um den Code ab dem Kommentar "button long pushed => set counter 0" 
sowie um die ISR(Timer0_OVF_vect). Zählen klappt also, aber bei der ISR 
und dem damit verbundenen Rücksetzen counter = 0 hab ich ein ziemliches 
Denkproblem. Wäre nett, wenn mir jemand weiterhelfen könnte. Danke schon 
mal!
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
//#include <avr/iotn2313>
4
#include <stdint.h>
5
#include <util/delay.h>
6
7
#define LED1  PD6
8
#define LED2  PD5
9
#define BUTTON1  PB1
10
11
#define LED_ON(LED)    (PORTD |= (1<<LED))    //x or  1 = 1
12
#define LED_OFF(LED)  (PORTD &= ~(1<<LED))  //x and 0 = 0
13
#define LED_TOGGLE(LED)  (PORTD ^= (1<<LED))    //x xor 1 = !x
14
#define BUTTON1_PUSHED  (PINB & (1<<BUTTON1))
15
#define ON        1            //for old_state (button pushed
16
#define OFF        0            //for old_state (button not pushed)
17
18
volatile uint8_t counter;
19
20
21
ISR(TIMER0_OVF_vect)
22
{
23
  counter = 0;
24
}
25
26
27
void output(uint8_t counter_out)
28
{
29
  if (counter_out & (1<<0))  //bit 0
30
    LED_ON(LED1);
31
  else
32
    LED_OFF(LED1);
33
34
  if (counter_out & (1<<1))  //bit 1
35
    LED_ON(LED2);
36
  else
37
    LED_OFF(LED2);
38
}
39
40
41
int main(void)
42
{
43
  uint8_t old_state;
44
  uint16_t repeater;
45
46
  DDRD |= (1<<LED1) | (1<<LED2);  //set PD6, PD5 (LEDs) as output
47
  DDRB &= ~(1<<BUTTON1);      //set PB1 (push-button) as input
48
49
  counter = 0;
50
  old_state = OFF;
51
//  repeater = 0;          //checking pushing duration
52
53
  sei();              //global interrupt enable
54
55
  while(1)
56
  {
57
    output(counter);      //calling output function
58
59
    //button switched from open to closed => counting 1 up
60
    if(BUTTON1_PUSHED && old_state == OFF)
61
    {
62
      counter++;
63
      old_state = ON;
64
//      repeater = 0;
65
      TCNT0 = 0;
66
    }
67
68
    //button open
69
    if(!BUTTON1_PUSHED)
70
    {
71
      old_state = OFF;
72
//      repeater = 0;
73
      TCNT0=0;
74
    }
75
76
    //button long pushed => set counter 0
77
    if(BUTTON1_PUSHED && old_state == ON)
78
    {
79
      //configure timer interrupt
80
      TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00);  //set prescaler = 1
81
      TCNT0 = 0;            //counter register = 0
82
      TIFR |= (1<<TOV0);        //delelte timer overflow flag
83
      TIMSK |= (1<<TOIE0);      //timer0 overflow enable
84
85
/*      repeater++;
86
87
      if(repeater == 20000)
88
      {
89
        counter = 0;
90
        repeater = 0;
91
      }*/
92
    }
93
  }
94
}

von Christoph P. (sirbundy)


Lesenswert?

Hm, zu viel zu lesen oder zu undurchsichtig?! Ich bin leider auch allein 
noch nicht schlauer geworden.

von Johannes M. (johnny-m)


Lesenswert?

Christoph P. wrote:
1
> //#include <avr/iotn2313>
Das hat auch in auskommentiertem Zustand da nichts zu suchen! 
Device-spezifische Header werden nie direkt eingebunden. Weg damit!
1
>       TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00);  //set prescaler = 1
Ich frage mich, wann es sich wohl endlich herumspricht, dass eine 
VerODERung mit einer Null völlig witzlos ist... Und das Schieben einer 
Null genauso.

Des weiteren erschließt sich mir die Funktionsweise des Programmes 
derzeit überhaupt nicht. Ich hab keinen Schimmer, was Du da wirklich 
machen willst. Der Timer wird gestartet und nirgends wieder angehalten. 
In irgendwelchen Programmteilen wird das Zählregister einfach mal 
zurückgesetzt, aber nirgends ist erkennbar, was das bringen soll. Eine 
Zählvariable namens counter wird ab und zu inkrementiert, aber 
nirgends ausgewertet. Im Timer Overflow Handler wird sie zurückgesetzt, 
aber was soll das bezwecken?

Tipp: Bitte zeichne den von Dir gewünschten Ablauf in Form eines 
Programmablaufplanes oder Flussdiagramms hin. Und dann fängst Du an, zu 
programmieren. Durch das da oben steigt niemand durch (Du selber 
offensichtlich auch nicht)...

von Christoph P. (sirbundy)


Lesenswert?

Danke erstmal für die Antwort. Die verODERung ist nur durch rumprobieren 
da so reingerutscht. Würd ich jetzt mal nicht überbewerten.
Das Programm soll einfach mit jedem Tastendruck eins hochzählen und das 
Ergebnis an (in diesem Fall nur zwei) LEDs ausgeben. Das macht es auch. 
Soll der Zähler nun wieder auf Null gesetzt werden, soll das durch einen 
längeren Tastendruck geschehen. Statt einem kurzen tippen eben 3s Halten 
oder ähnlich. Das hat, wie gesagt, mit der deklarierten Variable 
repeater auch geklappt. Nun wollte ich das Zurücksetzen aber über den 
"eingebauten" Timer0 und der ISR realisieren. Und das funktioniert noch 
nicht.

Das Zählregister wird immer dann zurückgesetzt, wenn der Taster nicht 
oder nur kurz gedrückt wird. In die ISR scheint das Programm aber gar 
nicht zu kommen, so dass der counter nie zurückgesetzt wird.
Eine weiterführende Auswertung will ich an dieser Stelle gar nicht 
betrachten, einfach nur einen Zähler mit Rücksetzen bei langem 
Tastendruck und Hochzählen bei kurzem.

von Stefan E. (sternst)


Lesenswert?

Christoph P. wrote:

> Das Zählregister wird immer dann zurückgesetzt, wenn der Taster nicht
> oder nur kurz gedrückt wird.

Dir scheint nicht so recht klar zu sein, dass beim Drücken der Taste der 
dritte if-Block immer wieder und wieder ausgeführt wird, inklusive der 
Timer-Initialisierung mit dem "TCNT0=0" darin.

von Stefan B. (stefan) Benutzerseite


Angehängte Dateien:

Lesenswert?

Bei der Initialisierung des Timer0 gibt es einen Fehler (TCCR0A 
verwendet statt TCCR0B), so dass der Timer nie lief. So wie im Anhang 
geht es auf meinem Pollin Board mit Attiny2312 und 8 MHz. Die 3s sind 
Pi*Daumen, siehe Anmerkung im Quellcode.

von Christoph P. (sirbundy)


Lesenswert?

Oh! Vielen Dank für die Hilfe euch beiden! Endlich gehts wieder vorran 
:)

von Stefan B. (stefan) Benutzerseite


Lesenswert?

So nachträglich ist mir noch eine Unschönheit aufgefallen, die zwar die 
Funktion nicht beeinträchtigt, aber die einen wurmen kann ;-)

Wenn die Taste vor dem 3 s Timeout losgelassen wird, läuft der Timer 
weiter.

Man könnte das beheben, wenn man den button open Fall so anlegt:
1
    //button open
2
    if(!BUTTON1_PUSHED && (old_state == ON))
3
    {
4
      DISABLE_TIMER0();
5
      duration = 0;
6
      old_state = OFF;
7
    }

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.