Forum: Mikrocontroller und Digitale Elektronik ISR springt nicht mehr raus


von Bax 1. (masse)


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.

1
  #include <avr/io.h>                            // I/O Informationen
2
  #include <avr/interrupt.h>                        // Interrupts laden
3
  #include <util/delay.h>
4
  #include <stdlib.h>
5
  #include <inttypes.h>
6
7
  #ifndef F_CPU                                  //Anfang F_CPU definition auch in Projekt einstellungen machen  
8
  #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"  //Sicherheitsmeldung bei falsch einstellung kommt beim Compilieren Fehler
9
  #define F_CPU 1000000UL                              //definiere F_CPU intern 1Mhz
10
  #endif                                        //Ende der Definition
11
       
12
  #define BAUD 9600UL                                    // Baudrate festlegen
13
 
14
  // 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!
15
16
    #define UBRR_VAL ((F_CPU+BAUD*4)/(BAUD*8)-1)                 // clever runden
17
    #define BAUD_REAL (F_CPU/(8*(UBRR_VAL+1)))                   // Reale Baudrate
18
  #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD)                 // Fehler in Promille, 1000 = kein Fehler.
19
 
20
  #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010))
21
   #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! 
22
  #endif
23
24
  #define setbit(P,BIT)  ((P) |= (1<<(BIT)))                // MAKRO >> Bit setzen
25
  #define clearbit(P,BIT)  ((P) &= (1<<(BIT)))                // MAKRO >> Bit löschen
26
27
  int time = 0;
28
  int Zeitlk1,Zeitlk2;
29
30
  int main (void)                              // Hauptprogramm
31
  {
32
33
34
    DDRA = 0xFF;                            // PORT A als Eingang festgelegt
35
    DDRB = 0x00;                            // PORT B als Ausgang festgelegt
36
    DDRC = 0xFF;                            // PORT C als Ausgang festgelegt
37
    DDRD = 0x00;                            // PORT D als Eingang festgelegt
38
39
    PORTB = 0x00;                            // PORTB alle Pins auf 0 gesetzt
40
41
    TCNT0 = 256 - 3 ;                          // Startzeit Timer eingestellt        
42
43
    TCCR0 = (1<<CS02);                          // Takt/Clock intern Prescaler 256
44
45
    TIMSK = (1<< TOIE0);                        // Interrupt Overflow erlauben
46
                
47
sei();                                // Interrupts erlauben
48
    while (1);                              // Endlosschleife
49
  }
50
51
ISR(TIMER0_OVF_vect)                            // Interruptroutine
52
{
53
  
54
    time ++;
55
56
    Zeitlk1 =1;
57
    Zeitlk2 =3;
58
    
59
    if (Zeitlk1 == time)
60
    {
61
      setbit(PORTA,0);                        // Bit für LK 1
62
      setbit(PORTC,0);                        // setzen hochziehen Stufe 1
63
      _delay_ms(90000);                        // Zeitverzögerung in ms
64
      clearbit(PORTC,0);                        // Zurücksetzen von Laufkatze
65
      clearbit(PORTC,0);                        // Zurücksetzen von Joystick
66
    }
67
68
    if (Zeitlk2 == time)            
69
    {
70
      setbit(PORTA,1); 
71
      setbit(PORTC,0);                           // setzen hochziehen Stufe 1
72
      _delay_ms(90000);                        // Zeitverzögerung in ms
73
      clearbit(PORTC,1);                        // Zurücksetzen von Laufkatze
74
      clearbit(PORTC,0);                        // Zurücksetzen von Joystick
75
    }
76
  TCNT0 = 256 - 3; 
77
78
}

von ... .. (docean) Benutzerseite


Lesenswert?

kein delay in ISRs fertig.

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

von (prx) A. K. (prx)


Lesenswert?

In der ISR 90 Sekunden Verzögerung?!?!?!

von Bax 1. (masse)


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.

von (prx) A. K. (prx)


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.

von Justus S. (jussa)


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...

von Bax 1. (masse)


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?

von Lutz (Gast)


Lesenswert?

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

Sicher?

von Lutz (Gast)


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)
       {
...
}

von Karl H. (kbuchegg)


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.

von Peter D. (peda)


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

von kurz (Gast)


Lesenswert?

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

von Harry S. (littlegonzo)


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

von Bax 1. (masse)


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!

von Bax 1. (masse)


Angehängte Dateien:

Lesenswert?

ok anhängen hat irgendwie nicht gefunzt!

von Justus S. (jussa)


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...

von Karl H. (kbuchegg)


Lesenswert?

1
    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
1
....
2
3
  while( 1 ) {
4
5
    if( Laufkatze1_einschalten ) {
6
      Laufkatze1_Aus_Zeit = time + 90;  // 90 Sekunden später ausschalten
7
      einschalten;
8
    }
9
10
    if( time >= Laufkatze1_Aus_Zeit ) {
11
      Laufkatze1_Aus_Zeit = 0;   // oder irgendein anderer Wert, den time
12
                                 // nie erreichen wird
13
      ausschalten;
14
    }
15
16
    .....
17
  }
18
...
19
20
21
ISR( ... )
22
{
23
   ...
24
   // wenn 1 Sekunde vergangen ist (entsprechend viele Aufrufe der ISR
25
   // erfolgt sind) time um 1 Sekunde weiterstellen
26
   time++;
27
}

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
1
....
2
3
  while( 1 ) {
4
5
    if( Laufkatze1_einschalten ) {
6
      Laufkatze1_Running = 90;  // Die Laufkatze soll noch 90 Sekunden laufen
7
      einschalten;
8
    }
9
10
    if( Laufkatze1_Running == 0 ) {
11
      ausschalten;
12
    }
13
14
    .....
15
  }
16
...
17
18
ISR( .... )
19
{
20
21
  if( .... ) {
22
    // wenn wieder 1 Sekunde vergangen ist
23
24
    if( Laufkatze1_Running > 0 )
25
      Laufkatze1_Running--;
26
27
    ....
28
  }
29
}

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.

von Thomas K. (muetze1)


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.

von Karl H. (kbuchegg)


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.

von Peter D. (peda)


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

von Bax 1. (masse)


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

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.