Forum: Mikrocontroller und Digitale Elektronik 8Bit Timer Atmega16/Overflow Interrupt


von Tobias D. (Gast)


Lesenswert?

Hallo,
ich hab ein problem. ich verstehe nicht, wie ich bei dem 8 bit zähler 
ein interrupt programmiere. hab mir das im tutorial mal angesehen:

/* uC: AT90S2313 */
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
  // Timer 0 konfigurieren
  TCCR0 = (1<<CS01); // Prescaler 8

  // Overflow Interrupt erlauben
  TIMSK |= (1<<TOIE0);

  // Global Interrupts aktivieren
  sei();

  while(1)
  {
    /* Sonstige Aktionen */
  }
}

/*
Der Overflow Interrupt Handler
wird aufgerufen, wenn TCNT0 von
255 auf 0 wechselt (256 Schritte),
d.h. ca. alle 2 ms
*/
ISR (TIMER0_OVF0_vect)
{
  /* Interrupt Aktion alle
  (1000000/8)/256 Hz = 488,28125 Hz
  bzw.
  1/488,28125 s = 2,048 ms
  */
}


ich verstehe nicht ganz, was das "ISR (TIMER0_OVF0_vect)" im code soll? 
kann es villt sein, dass wenn der interrupt ausgelöst wird, dass program 
dort weiterläuft? hab auch versucht das programm mal in meinen code 
einzubinden, aber bei "ISR (TIMER0_OVF0_vect)" meckert er rum. ich bin 
dabei eine uhr zu programmieren, da is die timerfunktion ganz hilfreich.

kann mir jemand villt weiterhelfen? nicht nutze einen atmega16. 4mhz 
qaurz.

mfg

von Karl H. (kbuchegg)


Lesenswert?

Tobias D. schrieb:

> ich verstehe nicht ganz, was das "ISR (TIMER0_OVF0_vect)" im code soll?
> kann es villt sein, dass wenn der interrupt ausgelöst wird, dass program
> dort weiterläuft?

ganz genau.

Das ist wie eine normale C-Funktion
1
void foo()
2
{
3
  mach irgendwas
4
}

nur mit dem Unterschied, dass die letzte Funktion du selber aufrufen 
musst, während eine ISR vom 'System' automatisch aufgerufen wird, wenn 
das auslösende Ereignis eintritt.

> hab auch versucht das programm mal in meinen code
> einzubinden, aber bei "ISR (TIMER0_OVF0_vect)" meckert er rum.

Dann musst du nachsehen, wie die entsprechende Interrupt routine bei 
deinem µC konkret heißt. Die Namen unterscheiden sich leicht, je nach 
Prozessor. Normalerweise heißen die Dinger so, wie sie auch im 
Datenblatt genannt werden, nur mit einem _vect hinten drann.

Wenn das übereinstimmt, dann sieh dir deine Projektkonfiguration an, ob 
du den richtigen Prozessor eingestellt hast.

Aus dem Bauch heraus würde ich nämlich sagen, dass der Interrupt beim 
Mega16 TIMER0_OVF_vect und nicht TIMER0_OVF0_vect heißt (da ist bei OVF0 
eine 0 zuviel). Der Timer hat nur einen Overflow, daher macht es keinen 
Sinn von OVF0 im Gegensatz zu zb OVF1 zu reden. Mit TIMER0_OVF_vect ist 
genau festgelegt was gemeint ist: Der Overflow vom Timer 0

von Tobias D. (Gast)


Lesenswert?

ja das habe ich auch schon mal gelesen. aber ich finde es nicht mehr im 
datenblatt. wenn ich:

ISR (TIMER0_OVF_vect)
{
  /* Interrupt Aktion alle
  (1000000/8)/256 Hz = 488,28125 Hz
  bzw.
  1/488,28125 s = 2,048 ms
  */
}

in meinen code einbinde, dann erscheinen 2 fehlermeldungen:
../ProjektWecker.c:113: error: static declaration of '__vector_9' 
follows non-static declaration
und:
../ProjektWecker.c:113: error: previous declaration of '__vector_9' was 
here

was ist mit dem global enable interrupt flag? hab ich das mit:
// Global Interrupts aktivieren
  sei();
gesetzt?

von Karl H. (kbuchegg)


Lesenswert?

Tobias D. schrieb:

> in meinen code einbinde, dann erscheinen 2 fehlermeldungen:
> ../ProjektWecker.c:113: error: static declaration of '__vector_9'
> follows non-static declaration
> und:
> ../ProjektWecker.c:113: error: previous declaration of '__vector_9' was
> here

zeig nochmal den ganzen Code.
da könnte irgendwo eine Klammer fehlen, oder sowas in der Richtung.

Schieb auch mal die ISR vor alle anderen Funktionen. Fehlermeldungen im 
Zusammenhang mit ISR können sehr irritierend sein und nicht immer sitzt 
der Fehler auch wirklich in der ISR

>
> was ist mit dem global enable interrupt flag? hab ich das mit:
> // Global Interrupts aktivieren
>   sei();
> gesetzt?

ja.
Siehe AVR-GCC-Tutorial

von Tobias D. (Gast)


Lesenswert?

der code:

#define F_CPU 4000000      //Takt 4Mhz


#include <avr/io.h>
#include <util/delay.h>      //Headerfile für Zeitschleife
#include <stdlib.h>
#include <stdio.h>        //für sprintf
#include "define.h"        //header
#include <avr/interrupt.h>


int main ()
{

  DDRA = 0x03;
  DDRB = 0xff;
  DDRC = 0xff;
  DDRD = 0xff;
// Timer 0 konfigurieren
TCCR0 = (1<<CS02); // Prescaler 256
// Overflow Interrupt erlauben
TIMSK |= (1<<TOIE0);

// Global Interrupts aktivieren
  sei();


//init LCD
  RS_0;

  PORTC = 0b00111000;
  E();
  wait();
  PORTC = 0b00001100;
  E();
  wait();
  PORTC = 0b00000001;
  E();
  wait();



while (1)
{

if (TCNT0 == 0xff)
{
zaehler++;
}

if (zaehler == 61)
{
zeitsec++;
zaehler = 0;
}

if (zeitsec == 60)
{
zeitmin++;
zeitsec = 0;
}

if (zeitmin == 60)
{
zeitstd++;
zeitmin = 0;
}

if (zeitstd == 24)
{
zeitstd = 0;
}

sprintf( bufferstd, "%d: ", zeitstd);
ausgabestd();
sprintf( buffermin, "%d: ", zeitmin);
ausgabemin();
sprintf( buffersec, "%d ", zeitsec);
ausgabesec();

switch (zeitsec)
{
case 0:  PORTB = 0b00000100;
    PORTD = 0b00000010;
    break;
case 1: PORTB = 0b00000100;
    PORTD = 0b00000001;
    break;
case 2: PORTB = 0b00000010;
    PORTD = 0b10000000;
    break;
case 3: PORTB = 0b00000010;
    PORTD = 0b01000000;
    break;
case 4: PORTB = 0b00000010;
    PORTD = 0b00100000;
    break;
case 5: PORTB = 0b00000010;
    PORTD = 0b00010000;
    break;
case 6: PORTB = 0b00000010;
    PORTD = 0b00001000;
    break;
case 7: PORTB = 0b00000010;
    PORTD = 0b00000100;
    break;
case 8: PORTB = 0b00000010;
    PORTD = 0b00000010;
    break;
case 9: PORTB = 0b00000010;
    PORTD = 0b00000001;
    break;
}

  //Licht
  if (PINA&(1<<PINA5))
  {
  DDRA |=(1<< DDA5);
  PORTA |=(1<<PA5);

  _delay_ms(3000);

  PORTA &=~( 1<<PA5);
  DDRA &=~( 1<<DDA5);
  }

ISR (TIMER0_OVF_vect)
{
}

}
return 0;
}

der code ist aber lang noch nicht fertig.
vor welche funktionen soll dich dir ISR schieben.
die fehlermeldungen kommen schon wieder -.-'.

von Oliver (Gast)


Lesenswert?

Tobias D. schrieb:
> vor welche funktionen soll dich dir ISR schieben.

Egal. Die darf nur nicht, wie jede andere Funktion auch, innerhalb einer 
anderen Funktionen stehen. Verschachtelte Funktionen kennt C nicht.

Oliver

von Karl H. (kbuchegg)


Lesenswert?

Tobias D. schrieb:


Ach nö!


> while (1)
> {
>
> if (TCNT0 == 0xff)
> {
> zaehler++;
> }
>
> if (zaehler == 61)
> {
> zeitsec++;
> zaehler = 0;
> }
>
> if (zeitsec == 60)
> {
> zeitmin++;
> zeitsec = 0;
> }
>
> if (zeitmin == 60)
> {
> zeitstd++;
> zeitmin = 0;
> }
>
> if (zeitstd == 24)
> {
> zeitstd = 0;
> }
>
> sprintf( bufferstd, "%d: ", zeitstd);
> ausgabestd();
> sprintf( buffermin, "%d: ", zeitmin);
> ausgabemin();
> sprintf( buffersec, "%d ", zeitsec);
> ausgabesec();
>
> switch (zeitsec)
> {
> case 0:  PORTB = 0b00000100;
>     PORTD = 0b00000010;
>     break;
> case 1: PORTB = 0b00000100;
>     PORTD = 0b00000001;
>     break;
> case 2: PORTB = 0b00000010;
>     PORTD = 0b10000000;
>     break;
> case 3: PORTB = 0b00000010;
>     PORTD = 0b01000000;
>     break;
> case 4: PORTB = 0b00000010;
>     PORTD = 0b00100000;
>     break;
> case 5: PORTB = 0b00000010;
>     PORTD = 0b00010000;
>     break;
> case 6: PORTB = 0b00000010;
>     PORTD = 0b00001000;
>     break;
> case 7: PORTB = 0b00000010;
>     PORTD = 0b00000100;
>     break;
> case 8: PORTB = 0b00000010;
>     PORTD = 0b00000010;
>     break;
> case 9: PORTB = 0b00000010;
>     PORTD = 0b00000001;
>     break;
> }
>
>   //Licht
>   if (PINA&(1<<PINA5))
>   {
>   DDRA |=(1<< DDA5);
>   PORTA |=(1<<PA5);
>
>   _delay_ms(3000);
>
>   PORTA &=~( 1<<PA5);
>   DDRA &=~( 1<<DDA5);
>   }


Ich habe jetzt ehrlich gesagt keine Lust die { und  } abzuzählen um zu 
sehen, wo du eine vergessen hast. Rück deinen Code ein, so wie es jeder 
andere Programmierer auch tut. Nach einer { erhöht sich die Einrücktiefe 
um 2 Leerzeichen. Eine } wird wieder um 2 Zeichen nach links ausgerückt 
und dann in dieser Spalte darunter weitergeschrieben. Dann muss man am 
Ende der Funktion wieder ganz am linken Rand rauskommen. Wenn nicht - da 
stimmt doch was nicht.

> vor welche funktionen soll dich dir ISR schieben.

Ganz nach vorne
1
....
2
3
ISR( ... )
4
{
5
  ...
6
}
7
8
int main()
9
{
10
  ....
11
}

von XXX (Gast)


Lesenswert?

Hallo

Eine Einrückung wurde ungemein helfen. Ich habe das Gefühl, deine
ISR-Routine steht innerhalb der main.

Gruß
Joachim

von Tobias D. (Gast)


Lesenswert?

hab ich doch auch nicht, aber es geht trotzdem nicht -.-'
ich brauch nur noch diesen richtigen ISR code für den atmega 16. sonst 
läuft alles. kann mir den mal jemand sagen?!^^

Tobias

von Karl H. (kbuchegg)


Lesenswert?

XXX schrieb:
> Hallo
>
> Eine Einrückung wurde ungemein helfen. Ich habe das Gefühl, deine
> ISR-Routine steht innerhalb der main.

Beim drüberscrollen würde ich sogar sagen: die steht innerhalb der 
while(1).

Wie du (und ich) schon sagten: Er soll mal seinen Code vernünftig 
einrücken.

von Karl H. (kbuchegg)


Lesenswert?

Tobias D. schrieb:
> hab ich doch auch nicht, aber es geht trotzdem nicht -.-'
> ich brauch nur noch diesen richtigen ISR code für den atmega 16. sonst
> läuft alles. kann mir den mal jemand sagen?!^^

Rück deinen verdammten Code endlich ein!

Deine ISR steht nicht auf der Schachtelungstiefe auf der Funktionen 
erlaubt sind.

verdammt nochmal.

von XXX (Gast)


Lesenswert?

Hallo

ISR (TIMER0_OVF_vect)
{
}

}
return 0;
}

Da paßt doch was nicht mit den }. Rück das ganze mal
anständig ein!

Gruß
Joachim

von ich (Gast)


Lesenswert?

Deine ISR steht in der main(),da muss sie raus.

Wenn würde an deiner Stelle den Timer so einstellen, dass er jede 
Sekunde ein Interrupt auslöst und die Zeit in der ISR hochzählen.

von Tobias D. (Gast)


Lesenswert?

also das mit den interrupts klappt jetzt. sitze jedoch schon die ganze 
zeit an der zeit. normalerweise müssten die sekunden jede sec um 1 
steigen. jedoch brauchen sie fast 2 sec.

der code:
#define F_CPU 4000000      //Takt 4Mhz


#include <avr/io.h>
#include <util/delay.h>      //Headerfile für Zeitschleife
#include <stdlib.h>
#include <stdio.h>        //für sprintf
#include "define.h"        //header
#include <avr/interrupt.h>


int main ()
{

  DDRA = 0b10000011;
  DDRB = 0xff;
  DDRC = 0xff;
  DDRD = 0xff;
// Timer 0 konfigurieren
TCCR0 = 0b00000011; // Prescaler 256
// Overflow Interrupt erlauben
TIMSK |= (1<<TOIE0);

//Global Interrupts aktivieren
sei();


//init LCD
  RS_0;

  PORTC = 0b00111000;
  E();
  wait();
  PORTC = 0b00001100;
  E();
  wait();
  PORTC = 0b00000001;
  E();
  wait();


while (1)
{

//Licht
  if (PINA&(1<<PINA5))
  {
  DDRA |=(1<< DDA5);
  PORTA |=(1<<PA5);

  _delay_ms(5000);

  PORTA &=~( 1<<PA5);
  DDRA &=~( 1<<DDA5);
  }

  //Zeiteinstellung
/*  if (PINA&(1<<PINA2))
  {
  _delay_ms(2000);
  }
    if (PINA&(1<<PINA2))
    {
    PORTA |=(1<<PA7);
    _delay_ms(300);
    PORTA &=~( 1<<PA7);
    }
        while (!(PINA&(1<<PINA4)))
        {
          if (PINA&(1<<PINA2))
          {
          zeitstd++;
          sprintf( bufferstd, "%d: ", zeitstd);
          ausgabestd();
          _delay_ms(300);
          }

        }*/



}
return 0;
}

ISR (TIMER0_OVF_vect)
{

zaehler++;
if (zaehler == 61)
{
zeitsec++;
zaehler = 0;
}

if (zeitsec == 60)
{
zeitmin++;
zeitsec = 0;
}

if (zeitmin == 60)
{
zeitstd++;
zeitmin = 0;
}

if (zeitstd == 24)
{
zeitstd = 0;
}

sprintf( bufferstd, "%d: ", zeitstd);
ausgabestd();
sprintf( buffermin, "%d: ", zeitmin);
ausgabemin();
sprintf( buffersec, "%d ", zeitsec);
ausgabesec();

led();
}

von Karl H. (kbuchegg)


Lesenswert?

Tobias D. schrieb:

1) hast du dein Programm immer noch nicht eingerückt

2)

> #define F_CPU 4000000      //Takt 4Mhz

nachrechnen ergibt: das ist glatt gelogen

3)
> // Timer 0 konfigurieren
> TCCR0 = 0b00000011; // Prescaler 256

das ist kein Prescaler von 256

4)
> ISR (TIMER0_OVF_vect)

Die Zeit in der ISR hochzuzählen ist in Ordnung. Aber die Ausgabe
muss dort raus. Das dauert viel zu lange für eine ISR.

von Tobias D. (Gast)


Lesenswert?

danke für die ganzen informationen. jetzt läuft alles :)

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.