Timer0 interrupt

Gast #1081155
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++;
}
#1081194
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.
Persönliche Seite #1081230
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
}
Gast #1081264
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.
#1188098
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
}
#1188393
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)...
#1188432
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.
#1188564
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.
Persönliche Seite #1189021
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
    }

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