mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timer0 interrupt


Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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++;
}

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

#include <avr/io.h>        // ADD: Anmerkung von Johannes M.
#include <avr/interrupt.h>

ISR(TIMER0_OVF_vect)
{
  static int a = 0;
  a++; // Breakpoint #1 im Simulator
}

void InitTimer(void)
{
  TCCR0 = TCCR0 | (1<<CS00);  // Prescaler CK/8
  TCNT0 = 0;
  TIMSK = TIMSK | (1<<TOIE0);
}

int main(void)
{
  InitTimer();
  sei();

  while(1)
  {
  }
}


Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Bernd (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Johannes M. (johnny-m)
Datum:

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

Autor: Christoph P. (sirbundy)
Datum:

Bewertung
0 lesenswert
nicht 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_Fun...
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!
#include <avr/io.h>
#include <avr/interrupt.h>
//#include <avr/iotn2313>
#include <stdint.h>
#include <util/delay.h>

#define LED1  PD6
#define LED2  PD5
#define BUTTON1  PB1

#define LED_ON(LED)    (PORTD |= (1<<LED))    //x or  1 = 1
#define LED_OFF(LED)  (PORTD &= ~(1<<LED))  //x and 0 = 0
#define LED_TOGGLE(LED)  (PORTD ^= (1<<LED))    //x xor 1 = !x
#define BUTTON1_PUSHED  (PINB & (1<<BUTTON1))
#define ON        1            //for old_state (button pushed
#define OFF        0            //for old_state (button not pushed)

volatile uint8_t counter;


ISR(TIMER0_OVF_vect)
{
  counter = 0;
}


void output(uint8_t counter_out)
{
  if (counter_out & (1<<0))  //bit 0
    LED_ON(LED1);
  else
    LED_OFF(LED1);

  if (counter_out & (1<<1))  //bit 1
    LED_ON(LED2);
  else
    LED_OFF(LED2);
}


int main(void)
{
  uint8_t old_state;
  uint16_t repeater;

  DDRD |= (1<<LED1) | (1<<LED2);  //set PD6, PD5 (LEDs) as output
  DDRB &= ~(1<<BUTTON1);      //set PB1 (push-button) as input

  counter = 0;
  old_state = OFF;
//  repeater = 0;          //checking pushing duration

  sei();              //global interrupt enable

  while(1)
  {
    output(counter);      //calling output function

    //button switched from open to closed => counting 1 up
    if(BUTTON1_PUSHED && old_state == OFF)
    {
      counter++;
      old_state = ON;
//      repeater = 0;
      TCNT0 = 0;
    }

    //button open
    if(!BUTTON1_PUSHED)
    {
      old_state = OFF;
//      repeater = 0;
      TCNT0=0;
    }

    //button long pushed => set counter 0
    if(BUTTON1_PUSHED && old_state == ON)
    {
      //configure timer interrupt
      TCCR0A |= (1<<CS02) | (0<<CS01) | (0<<CS00);  //set prescaler = 1
      TCNT0 = 0;            //counter register = 0
      TIFR |= (1<<TOV0);        //delelte timer overflow flag
      TIMSK |= (1<<TOIE0);      //timer0 overflow enable

/*      repeater++;

      if(repeater == 20000)
      {
        counter = 0;
        repeater = 0;
      }*/
    }
  }
}

Autor: Christoph P. (sirbundy)
Datum:

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

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christoph P. wrote:
> //#include <avr/iotn2313>
Das hat auch in auskommentiertem Zustand da nichts zu suchen! 
Device-spezifische Header werden nie direkt eingebunden. Weg damit!
>       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)...

Autor: Christoph P. (sirbundy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Stefan B. (stefan) Benutzerseite
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.

Autor: Christoph P. (sirbundy)
Datum:

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

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:

    //button open
    if(!BUTTON1_PUSHED && (old_state == ON))
    {
      DISABLE_TIMER0();
      duration = 0;
      old_state = OFF;
    }


Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.