Forum: Mikrocontroller und Digitale Elektronik Verständnisproblem bei Interrupts


von Gast (Gast)


Lesenswert?

Hallo zusammen,
habe folgendes Problem mit Interrupts!
Ich habe ein Programm geschrieben, welches einen externen Timer benutzt, 
dieser Timer hat einen Timer overflow interrupt, der auch einwandfrei 
funktioniert. Zusätzlich, habe ich auch eine Interruptroutine, die 
ausgelöst wird, wenn ein Bit über die USART0 geschickt wird. Jetzt würde 
ich gerne alle Interrupts ausschlaten, also auch den timer anhalten, 
aber mit der Routine aus dem ARV-gcc-tutorial läuft der Timer immer 
noch! Jedoch ist die USART0 Interrupt routine ausgeschlatet, wie kann 
das sein?

Programmiert habe ich es wie im Beispiel!
cli()
aufruf funktion


Funktions Kopf
uint8_t tmp_sreg=0;
tmp_sreg=SREG
cli();

nicht unterbrechbarer code
MCUCSR |= (1<<JTD);
MCUCSR |= (1<<JTD);

SREG = tmp_sreg;

wieder im hauptprogramm

dann habe ich noch eine Frage, wenn ich keine funktion verwende reicht 
es dann wenn ich so etwas programmiere?

void main()
{ programm code
   cli();
   tmp_sreg=SREG;

  nicht unterbrechbarer programm code

  MCUCSR |= (1<<JTD);
  MCUCSR |= (1<<JTD);

  SREG = tmp_sreg;

  sei();
}



oder geht das so nicht?
wäre für jede hilfe dankbar!

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:

> ausgelöst wird, wenn ein Bit über die USART0 geschickt wird. Jetzt würde
> ich gerne alle Interrupts ausschlaten,

Interrupts global ein und ausschalten macht man mittels cli() und sei(). 
Soweit ist das korrekt

> also auch den timer anhalten,

Ob der Timer läuft oder nicht, hat nichts mit Interrupts zu tun.
Ein Timer tickt vor sich hin, sobald er einen Vorteiler gesetzt bekommen 
hat. Setzt du den Vorteiler wieder auf 0, macht auch der Timer keinen 
Mucks mehr.

> Funktions Kopf
> uint8_t tmp_sreg=0;
> tmp_sreg=SREG
> cli();
>
> nicht unterbrechbarer code
> MCUCSR |= (1<<JTD);
> MCUCSR |= (1<<JTD);
>
> SREG = tmp_sreg;

Lass um Himmels willen das SREG in Ruhe.
Prozessorregister gehen dich als C-Programmiere nichts an!

von Gast (Gast)


Lesenswert?

Wenn der timer aktiviert ist dann läuft der solange bis du ihn wieder 
ausschaltest (stoppst) egal ob du die IRQs freischaltest oder sperrst.
Btw. kann man über die usart nur ganze bytes (nicht einzelne bits) 
verschicken, oder?

von Gast (Gast)


Lesenswert?

Hast natürlich recht! Man kann nur Bytes über die USART schicken! Das 
heisst also, dass ich den Timer nicht über einen Stopp der Interrupts 
ausschalten kann? Aber ist diese Routine nicht ein Interrupt?
ISR(TIMER2_OVF_vect)
{
  time++;
}
Und wenn ich die Interrupt routinen stoppe dann kommt er trotzdem da 
rein?

von Gast (Gast)


Lesenswert?

Aber ist das nicht so im avr-gcc tutorial beschrieben, und speicher ich 
nicht das SREG register in einer Variablen, damit das Programm nacher 
wieder weiß wo es war?

von AuchnurGast (Gast)


Lesenswert?

Hallo,

du brauchst das sreg nicht zu sichern, da kümmert sich der µC selber 
drum.
Wenn du es in einer Variable sichern möchtest so müßte die Syntax meiner 
Meinung nach so lauten:

tmp_sreg:=sreg;

Sonst sicherst du den Inhalt der variablen in deinem SREG.

kann aber auch sein, dass ich da jetzt vollkommen falsch liege.

von Karl H. (kbuchegg)


Lesenswert?

AuchnurGast wrote:

> kann aber auch sein, dass ich da jetzt vollkommen falsch liege.

Mit Teil 1 (lass das Zeugs in Ruhe, darum kümmert sich der Compiler) 
liegst du richtig.
Mit Teil 2 liegst du falsch.

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:
> Aber ist das nicht so im avr-gcc tutorial beschrieben, und speicher ich
> nicht das SREG register in einer Variablen, damit das Programm nacher
> wieder weiß wo es war?

Nein. Ist völliger Unsinn.

Lass Dinge in Ruhe, von denen du nichts weißt und (als C-Programmierer) 
auch nichts zu wissen brauchst. Du kannst es nur schlimmer machen wenn 
du dem Compiler ins Handwerk pfuscht.

von Karl H. (kbuchegg)


Lesenswert?

Gast wrote:
> Das
> heisst also, dass ich den Timer nicht über einen Stopp der Interrupts
> ausschalten kann?

Welchen Teil des Satzes:
"Ein Timer läuft sobald er einen Vorteiler eingestellt hat"
verstehst du nicht?

> Aber ist diese Routine nicht ein Interrupt?
> ISR(TIMER2_OVF_vect)
> {
>   time++;
> }
> Und wenn ich die Interrupt routinen stoppe dann kommt er trotzdem da
> rein?

Das was du da hast, ist eine Interrupt Routine. Die kann ausgeführt 
werden, wenn das entsprechende Ereignis eintritt. In deinem Fall ist das 
Ereignis: der Timer läuft über.
Ein Timer der aber nicht zählt kann auch nicht überlaufen.
Kein Überlauf -> kein Interrupt Ereignis -> Funktion wird nicht 
angesprungen

Die anderen Möglichkeiten, wie man das Anspringen der Funktion 
verhindern kann (der Timer aber trotzdem imHintergrund weiterläuft) 
sind:
* Für jedes Interrupt Ereignis gibt es ein Bit in irgendeinem Register, 
welches gezielt nur dieses eine Interrupt Ereignis sperren oder 
freigeben kann
* Die globale Interrupt Freigabe mittels sei() bzw. cli()

von Gast (Gast)


Lesenswert?

Erstmal vielen dank für eure Antworten! werde es jetzt so probieren, das 
ich den Timer TCCR2=0x00 setzen werde!

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.