www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ISR springt nicht mehr raus


Autor: Bax 182 (masse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab einen AT Mega32 und AVR Studio4 hab folgendes Programm geschrieben 
und bis gestern ging noch alles aber jetzt Laüft Timer 0 einmal durch 
dann interrupt und dann beendet er den Interrupt nicht mehr und springt 
immer wieder zum Anfang??? Zeit Lk1 und Zeitlk2 sollen später über Uart 
ausgelesenwerden hab sie jetzt testweise im Programm festgelegt.

  #include <avr/io.h>                            // I/O Informationen
  #include <avr/interrupt.h>                        // Interrupts laden
  #include <util/delay.h>
  #include <stdlib.h>
  #include <inttypes.h>

  #ifndef F_CPU                                  //Anfang F_CPU definition auch in Projekt einstellungen machen  
  #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"  //Sicherheitsmeldung bei falsch einstellung kommt beim Compilieren Fehler
  #define F_CPU 1000000UL                              //definiere F_CPU intern 1Mhz
  #endif                                        //Ende der Definition
       
  #define BAUD 9600UL                                    // Baudrate festlegen
 
  // Berechnungen nur bei UCSRA=(1<<U2X) ansonsten alle 4=8 und alle 8=16 da mit (1<<U2X) Taktrate verdoppelt wird, Formel stimmt sonst nicht!

    #define UBRR_VAL ((F_CPU+BAUD*4)/(BAUD*8)-1)                 // clever runden
    #define BAUD_REAL (F_CPU/(8*(UBRR_VAL+1)))                   // Reale Baudrate
  #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)                 // Fehler in Promille, 1000 = kein Fehler.
 
  #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
   #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
  #endif

  #define setbit(P,BIT)  ((P) |= (1<<(BIT)))                // MAKRO >> Bit setzen
  #define clearbit(P,BIT)  ((P) &= (1<<(BIT)))                // MAKRO >> Bit löschen

  int time = 0;
  int Zeitlk1,Zeitlk2;

  int main (void)                              // Hauptprogramm
  {


    DDRA = 0xFF;                            // PORT A als Eingang festgelegt
    DDRB = 0x00;                            // PORT B als Ausgang festgelegt
    DDRC = 0xFF;                            // PORT C als Ausgang festgelegt
    DDRD = 0x00;                            // PORT D als Eingang festgelegt

    PORTB = 0x00;                            // PORTB alle Pins auf 0 gesetzt

    TCNT0 = 256 - 3 ;                          // Startzeit Timer eingestellt        

    TCCR0 = (1<<CS02);                          // Takt/Clock intern Prescaler 256

    TIMSK = (1<< TOIE0);                        // Interrupt Overflow erlauben
                
sei();                                // Interrupts erlauben
    while (1);                              // Endlosschleife
  }

ISR(TIMER0_OVF_vect)                            // Interruptroutine
{
  
    time ++;

    Zeitlk1 =1;
    Zeitlk2 =3;
    
    if (Zeitlk1 == time)
    {
      setbit(PORTA,0);                        // Bit für LK 1
      setbit(PORTC,0);                        // setzen hochziehen Stufe 1
      _delay_ms(90000);                        // Zeitverzögerung in ms
      clearbit(PORTC,0);                        // Zurücksetzen von Laufkatze
      clearbit(PORTC,0);                        // Zurücksetzen von Joystick
    }

    if (Zeitlk2 == time)            
    {
      setbit(PORTA,1); 
      setbit(PORTC,0);                           // setzen hochziehen Stufe 1
      _delay_ms(90000);                        // Zeitverzögerung in ms
      clearbit(PORTC,1);                        // Zurücksetzen von Laufkatze
      clearbit(PORTC,0);                        // Zurücksetzen von Joystick
    }
  TCNT0 = 256 - 3; 

}

Autor: ... ... (docean) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kein delay in ISRs fertig.

mach das in deiner main, und setz in der ist nur ein flag..

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
In der ISR 90 Sekunden Verzögerung?!?!?!

Autor: Bax 182 (masse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
A. K. schrieb:
> In der ISR 90 Sekunden Verzögerung?!?!?!

Naja ich will halt das die Ausgänge für 90 sec. gesetzt bleiben!?
Und Was fehlt den noch beim Delay muss dazusagen das ich mit
_delay_ms(90000); ja in die <util/delay.h>springe.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie eben schon gesagt: Kein Delay in einer ISR(), jedenfalls keins 
jenseits von ein paar Mikrosekunden!

Man kann beispielsweise den Ausgang im Interrupt #1234 setzen und im 
Interrupt #678647868 wieder zurücksetzen.

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bax 182 schrieb:

> Naja ich will halt das die Ausgänge für 90 sec. gesetzt bleiben!?

Und da wunderst du dich, dass dein Programm in der ISR "hängebleibt"? Oh 
je...

Autor: Bax 182 (masse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab es jetzt so gemacht das alles aus dem Interrupt jetzt in main steht 
und ich im Interrupt nur dem Timer seinen neuen Zeitwert gebe aber er 
springt trotzdem nicht wider aus dem interrupt raus?

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> clearbit(PORTC,0);           // Zurücksetzen von Laufkatze
>> clearbit(PORTC,0);           // Zurücksetzen von Joystick

Sicher?

Autor: Lutz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Übrigens: Verfolge mal die arme time-Variable ...
...
int time = 0;
...
ISR(TIMER0_OVF_vect)                            // Interruptroutine
{
    time ++;
    Zeitlk1 =1;
    Zeitlk2 =3;
    if (Zeitlk1 == time)
       {
...
    if (Zeitlk2 == time)
       {
...
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bax 182 schrieb:
> Hab es jetzt so gemacht das alles aus dem Interrupt jetzt in main steht
> und ich im Interrupt nur dem Timer seinen neuen Zeitwert gebe aber er
> springt trotzdem nicht wider aus dem interrupt raus?

Leider ist meine Glaskugel wieder mal in der Reparatur, sodass ich nicht 
sehen kann, welchen Programmfehler du jetzt in dein Programm eingebaut 
hast.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, ich weiß auch nicht, warum so viele Leute eine riesen Angst haben, 
ein compilierbares *.c anzuhängen (oder *.zip, wenn mehrere Files).


Immer nur diese Schnipselchen, schlimmstenfalls sogar editiert, d.h. 
völlig andere Fehler enthaltend.
Und dann rätselt man wie die blöden, welchen Typ könnten die Variablen 
haben, was könnten die externen Funktionen wohl machen, was sollen die 
Macros bedeuten?


Man kann ja schreiben: "Ich hab in Zeile xxx ein ; eingefügt"
Aber dann gehört trotzdem noch die compilierbare Source als Anhang!!!


Peter

Autor: kurz (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alles streng geheim!!! Alle anderen würden nur abkupfern und Millionen 
scheffeln mit dieser Applikation. ;-)

Autor: Harry S. (littlegonzo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter ich denke es liegt oft am Ton der hier im Forum herscht.
Teilweise werden Anfänger niedergemacht wenn die Programme eben noch 
etwas wuest aussehen.

Du selbst bist ja glücklicherweise jemand der sich mit Anfängern 
auseinander setzt und ihnen wirklich super Einstiegshilfe gibt.
Wenn ich mir so manche erklärungen von Dir ansehe fällt es mir wie 
schuppen aus den Augen wie einfach es doch ist ;-)

Da ich mich selbst längst nicht als C-Profi sehe, trau ich mich auch oft 
nicht mein Source zu veröffentlichen weil man eben sehr oft 
niedergemezelt wird.
Es gibt eben verschiede Arten jemanden klar zu machen das man einen 
Fehler macht. Wie hieß das früher mal? "Der Ton macht die Musik"

In diesem Sinne,
schönes Wochenende
Harry

Autor: Bax 182 (masse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Man man man da haben ja noch richtig viele leute geschrieben ich dachte 
schon ich bin allein mit dem Projekt! Vor Diebstahl der Idee hab ich 
keine angst ist ein Berufsschulprojekt das auch andere Klassen machen 
müssen ;-)
Aber nun zu euren Fragen und ich hab die .c mal angehangen!


Lutz schrieb:
>>> clearbit(PORTC,0);           // Zurücksetzen von Laufkatze
>>> clearbit(PORTC,0);           // Zurücksetzen von Joystick
>
> Sicher?

Ja hat bis jetzt geklappt!



Übrigens: Verfolge mal die arme time-Variable ...
...
int time = 0;
...
ISR(TIMER0_OVF_vect)                            // Interruptroutine
{
    time ++;
    Zeitlk1 =1;
    Zeitlk2 =3;
    if (Zeitlk1 == time)
       {
...
    if (Zeitlk2 == time)
       {
...
}


Ja ich weiß das ist im moment etwas undurchsichtig da ich mir die 
Variablen über RS232 von VB2008express ausgeben lassen möchte!

Autor: Bax 182 (masse)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ok anhängen hat irgendwie nicht gefunzt!

Autor: Justus Skorps (jussa)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bax 182 schrieb:

>
> Ja hat bis jetzt geklappt!

und was hat es für einen Sinn, ein Bit zweimal zu löschen?

und dein angehängter Code macht ja nun mal gar nichts...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
    while (1);

Dein µC hängt hier und kommt nicht weiter.
; entfernen und { } um den Block machen, den du endlos wiederholt haben 
möchtest.

Deine _delay sind immer noch kontraproduktiv.

Du hast ja jetzt eine time Variable, die dir (in der ISR hochgezählt, 
das musst du noch machen) innerhalb des Programms Sekunden zählt.
Wenn du nun eine Laufkatze einschaltest, rechnest du dir aus, zu welchem 
Sekundensignal sie wieder ausgeschaltet werden musst. Du wartest nicht 
die Zeit ab(!) sondern überprüfst in deiner Haupt-while-Schleife immer 
wieder, ob dieser Zeitpunkt erreicht ist und wenn ja, schaltest du ab.

Als Pseudocode, ungefähr so
....

  while( 1 ) {

    if( Laufkatze1_einschalten ) {
      Laufkatze1_Aus_Zeit = time + 90;  // 90 Sekunden später ausschalten
      einschalten;
    }

    if( time >= Laufkatze1_Aus_Zeit ) {
      Laufkatze1_Aus_Zeit = 0;   // oder irgendein anderer Wert, den time
                                 // nie erreichen wird
      ausschalten;
    }

    .....
  }
...


ISR( ... )
{
   ...
   // wenn 1 Sekunde vergangen ist (entsprechend viele Aufrufe der ISR
   // erfolgt sind) time um 1 Sekunde weiterstellen
   time++;
}

Kannst du 'sehen', wie dieses Konstrukt die Laufkatze ebenfalls nach 90 
Sekunden abschalten wird? Allerdings geschieht dies in einer Art und 
Weise, dass der µC keine 90 Sekunden Däumchen drehen muss, sondern in 
der Zwischenzeit andere Dinge machen kann.

Alternativ kannst du das auch so machen

....

  while( 1 ) {

    if( Laufkatze1_einschalten ) {
      Laufkatze1_Running = 90;  // Die Laufkatze soll noch 90 Sekunden laufen
      einschalten;
    }

    if( Laufkatze1_Running == 0 ) {
      ausschalten;
    }

    .....
  }
...

ISR( .... )
{

  if( .... ) {
    // wenn wieder 1 Sekunde vergangen ist

    if( Laufkatze1_Running > 0 )
      Laufkatze1_Running--;

    ....
  }
}  

Hier wird die Zeit, wie lange die Katze noch laufen soll in der ISR 
runtergezählt. Klarerweise in der ISR nur dann, wenn 1 Sekunde vergangen 
ist. In der Haupt-while-Schleife prüfst du nur ob die Zeit-Variable 
wieder bis auf 0 runtergekommen ist, und schaltest gegebenenfalls aus.

Aber egal wie du das machst, du musst deine Denkweise umstellen. 
Momentan bist du im Gedankengang: Ich schalte ein und 90 Sekunden später 
schalte ich aus. Du denkst seriell, du musst aber in Ereignissen denken. 
Die ISR ist dein Ereignislieferent und in der Hauptschleife wird 
überprüft, ob bestimmte Ereignisse (zb 90 Sekunden runtergezählt oder 
ein bestimmter Zeitpunkt ist erreicht) eingetreten sind und darauf 
reagieren.

Autor: Thomas K. (muetze1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
1. Kommentar zur nicht gesetzten F_CPU passt nicht zum gesetzten Wert (1 
MHz <> 4 MHz)
2. Kommentare bezüglich Port xy als Aus/Eingang setzen stimmen nicht mit 
dem Code überein. Wenn dann richtig kommentieren oder gar nicht, aber 
falsch?
3. time muss mit dem Attribute volatile gekennzeichnet werden, wenn es 
in der ISR geändert werden soll
4. Wann denkst du kommt er aus der Endlosschleife while (1); raus um den 
nachfolgenden Code auszuführen?
5. Was soll nun der leere ISR Handler? Hast du die Beiträge zuvor 
gelesen bezüglich Flag in der ISR setzen und in der main() handeln?

Nur mal so ein paar Anmerkungen.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und noch ein Tip.

Bevor du dich da mit 10 Laufkatzen verzettelst, realisiere das alles 
erst mal mit EINER Laufkatze. Und wenn das dann läuft, dann überlege 
dir, wie du (zb mit einem Array) das ganze so gestalten kannst, dass du 
nicht sinnlos COde 10 mal duplizieren musst. Das kommt dann auch der 
Fehlersuche zugute, wenn man nicht endlos langen Code ständig absuchen 
muss.

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn Du 10 verschiedene Zeitabläufe quasi parallel und unabhängig 
ausführen willst, geht das am schönsten über einen Scheduler:

Beitrag "Wartezeiten effektiv (Scheduler)"


Peter

Autor: Bax 182 (masse)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter Dannegger schrieb:
> Wenn Du 10 verschiedene Zeitabläufe quasi parallel und unabhängig
> ausführen willst, geht das am schönsten über einen Scheduler:
>
> Beitrag "Wartezeiten effektiv (Scheduler)"
>
>
> Peter

Danke Peda, dein Tip hat mir sehr weitergeholfen habe das ganze 
Proggramm nochmal auseinander genommen und so aufgebaut wie im Beispiel 
erklärt! Jetzt werden am Anfang einmal alle Variablen festgelegt und 
dann werden nur noch die einzelnen Laufkatzen abgefragt ob die 
setzbedingungen erfüllt sind und zwischendurch kommt immer mal der 
Interrupt und setzt Time Hoch! Super Danke

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.