Forum: Compiler & IDEs 2 Timer Interrupts, einer ist stärker


von Constantin Schieber (Gast)


Lesenswert?

Hallo!

Ich weiß, das Thema ist hier schon etwa 999 mal durchgekaut worden, 
allerdings stehe ich vor einem "neuen" unlösbaren Problem.

Ich habe 2 8Bit Counter. Diese werden gleichzeitig gestartet und enden 
gleichzeitig (ist ein Ausnahmefall, normalerweise laufen sie versetzt).
Ich verwende einen Atmega8.
Nun habe ich gelesen dass Interrupts, sollte einer ausgelöst werden 
während ein anderer gerade abgearbeitet wird, einfach beim nächsten 
ausgelösten Interrupt weitermachen.
Also: Interrupt1 --> Wird Abgearbeitet --> 2ter Interrupt wird ausgelöst 
--> 1erste ISR ist fertig --> 2ter Interrupt wird abgearbeitet.

Bei mir ist es aber so dass nur alle 5 Interrupts der 2te Timer 
angesprochen wird (Obwohl beim Softwaredebuggen ein Overflow angezeigt 
wird).

Meine Frage: Sollte das normalerweise gehen? Eigentlich schon, oder?
Ich muss zu meiner Schande zugeben dass ich eine Funktion in beiden ISR 
aufrufe die beim Portsetzen ein _delay_us(1) verwende, kann das für 
Verwirrung sorgen?

Vielen Dank im Voraus und Verzeihung für das Wiederkauen eines schon 
viel zu oft besprochenen Themas.

von Floh (Gast)


Lesenswert?

Constantin Schieber schrieb:
> Meine Frage: Sollte das normalerweise gehen? Eigentlich schon, oder?

Kein Code, keine Antwort. :-)

von g457 (Gast)


Lesenswert?

> Sollte das normalerweise gehen?

Kommt drauf an. Wenn mans richtig(tm) implementiert schon.

Ein delay ist nur dann kritisch wenn die Ausführung der ISR (bzw. aller 
ISR mit höherer Priorität als der 'Verlierer) länger dauert als bis zum 
nächsten Interrupt, weil dann gewinnt jener gemäß Speckifikation (bzw. 
jeder mit höherer Priorität als wie der 'Verlierer'). Sowas nennt man 
'Verhungern' und zeugt von schlechtem (Software)Design (sofern es nicht 
beabsichtigt ist ∗hust∗ :-)

HTH

von Constantin S. (constantin_s)


Lesenswert?

1
ISR (SIG_OVERFLOW0)
2
{
3
  generate_clk(CLK_R);      //Gernerate Click for faster motor
4
  d_tacts_r++;
5
  if(d_tacts_r == r_tacts_r)
6
  {
7
    TCCR0 = (0<<CS00) | (0<<CS01) | (0<<CS02);
8
  }
9
  else
10
    TCNT0 = f_interrupt_r;  
11
}
12
13
ISR (SIG_OVERFLOW2)
14
{
15
  generate_clk(CLK_L);      //Gernerate Click for faster motor
16
  d_tacts_l++;
17
  if(d_tacts_l == r_tacts_l)
18
  {
19
    TCCR2 = (0<<CS20) | (0<<CS21) | (0<<CS22);
20
  }
21
  else
22
    TCNT2 = f_interrupt_l;
23
}
24
/****************************************************************************
25
Toggle Ports to generate clock for stepper
26
****************************************************************************/
27
void generate_clk(char dir)
28
{
29
  cb(PORT_M, dir);
30
  _delay_us(1);
31
  sb(PORT_M, dir);
32
  _delay_us(1);
33
}

Dass ist der Code. Also in diesen 3 Programmteilen manifestiert sich der 
Fehler (der Rest ist Berechnung von Drehzahlen, Winkeln etc).
Ich denke nicht dass man das allzu falsch machen kann, die 
Initialisierung der Timer und die Berechnung des Overflows ist 
vielleicht auch noch interessant:
1
unsigned short set_timer(short hz)
2
{
3
  return (unsigned short)(0xFF - (F_CPU / 1024 / hz));  //Set Timeroverflow, the higher hz is the faster an interrupt will be created
4
}
5
6
void init_Timer()
7
{
8
  //Ersten 8 Bit Timer initialisieren
9
  TCCR0 = (1<<CS00) | (1<<CS02);
10
  TIMSK |= (1<<TOIE0);
11
  //Zweiten 8 Bit Timer initialisieren
12
  TCCR2 = (1<<CS20) | (1<<CS22);
13
  TIMSK |= (1<<TOIE2);
14
}

Ich bin mir jetzt eigentlich keiner höheren Schuld bewusst. Die Timer 
werden beim Programmaufruf initialisiert (Prescaler einstellen und 
Interrupts zulassen).
Danach berechne ich wie oft ein Interrupt ausgelöst werden soll und das 
war's.

Fühle mich also keiner (gröberen) Schuld bewusst, mal abgesehen davon 
dass es schrecklich programmiert ist und das ganze eigentlich über 
Multitasking (http://www.mikrocontroller.net/articles/Multitasking) 
gelöst gehört. Aber erstmal soll sich was tun, danach kann man das ganze 
schön machen!

Danke für die schnelle Antwort übrigens!

von g457 (Gast)


Lesenswert?

Nur der Vollständigkeit halber:

> TCCR0 = (1<<CS00) | (1<<CS02);

und

> TCCR2 = (1<<CS20) | (1<<CS22);

liefern nicht die selben Presacler (1024 für Timer0 und 128 für Timer2).

Falls das noch nicht des Problems Lösung ist: Was ist F_CPU. Wie hoch 
ist die Taktrate tatsächlich?

HTH

von Constantin S. (constantin_s)


Lesenswert?

Oh nein, ich bin ja so dumm!!!
Vor lauter Suche nach einem extrem gefinkelten Fehler hab ich das 
vollkommen übersehen :(
Danke Danke Danke, da starr ich minutenlang aufs Datenblatt und in die 
Doku und übersehe das einfach! :/
Also Danke nochmals und ein schönes Wochenende, Sie haben meinen Tag 
gerettet!!! :)

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.