Forum: Mikrocontroller und Digitale Elektronik ATMEGA 32 mit LCD - Probleme mit Interrupt INT0


von Matthias L. (lindner8712)


Angehängte Dateien:

Lesenswert?

Hallo zussamen,

nachdem ich mir ein C-Buch zugelegt habe und das Forum bzw. Codesammlung 
quasi auswendig gelernt habe stehe ich vor einem riesen Problem...

folgendes:
Ich baue gerade ein kleines Netzteil. Hardware funktioniert, Die meisten 
Module des C-Programms auch.

Das Problem ist, ich wollte mit einem NE555 einen Takt generieren, der 
ca alle 500ms das Display aktualisiert (TIMER sind leider keiner mehr 
übrig.) Soll heißen alle Zahlenwerte löschen,
Werte neu berechnen und wieder auf dem LCD anzeigen.

Solange ich das Display mit einem Taster am INT0 Eingang (10kOhm 
Pulldown)
auslöse Funktioniert es auch wenn ich aber den NE555 stecke, hängt sich 
nach einer nicht definierbaren anzahl von INT0 Aufrufen irgendwas auf. 
Das Display wird nicht mehr aktualisiert, wenige sekunden Später fängt 
der µC von vorne im Programm an (schätze mal der Watchdog greift dort 
ein)..

Hat vllt irgendwer eine zündende Idee?

Vielen Dank im Vorraus

Matthias

PS:hier erstmal einige Codeauschnitte ( Im Anhang ist die Komplette 
Quelldatei die ist viel zu lang)

1
int main(void)
2
3
{  
4
   GICR=(1<<INT0);        //INT0 config
5
   MCUCR=(1<<ISC01);      //INT0 config
6
   sei();      //freigabe interrupts
7
  
8
  
9
   while(1)
10
   {
11
      asm("NOP");//Mache nichts in der Haupschleife;
12
      asm("NOP");//Verbrenn nur Zeit und warte auf Interrupts!
13
   }
14
   return 0;
15
}
16
17
ISR(INT0_vect)
18
{
19
  
20
  //dtostrf() wird zwar vergewaltigt, 
21
        //weil sie nicht mit String gefüttert wird
22
  //funktion trotzdem gegeben!
23
24
  //Display Aktualisieren mit NE555 
25
        //Rechteckgeber 5HZ Signal Duty-cycle ca 5%
26
   analog_IL=0;
27
   analog_IH=0;
28
   analog_U=0;
29
   analog_T=0;
30
   analog_IL=adc_read10bit(0,2); 
31
   analog_IH=adc_read10bit(1,2);
32
   analog_U=adc_read10bit(2,2);
33
   analog_T=adc_read10bit(3,2);
34
35
   calc_U=analog_U*adc_10;
36
   lcd_gotoxy(3,1);
37
   lcd_puts("    ");
38
   if(analog_U==1023)
39
   {
40
      dtostrf( calc_U, 3, 1, s );
41
   }
42
   else
43
   {
44
      dtostrf( calc_U, 3, 2, s );
45
   }
46
   lcd_gotoxy(3,1);
47
   lcd_puts(s);
48
   lcd_puts("V");
49
.
50
.
51
.
52
.
53
}

von Georg G. (df2au)


Lesenswert?

VIEL zu viel Code in der ISR. Setze dir ein Flag und mach die Ausgabe 
dann in der main().

von Matthias L. (lindner8712)


Lesenswert?

Hallo,

danke für den Tipp!! :-)

Könnte das die Ursache sein???

mfg

von Georg G. (df2au)


Lesenswert?

Du machst z.B. intensiv Gleitpunkt Operationen im Interrupt. Da kann es 
dir schon passieren, dass sich alles gegenseitig überholt :-)

von Joe S. (bubblejoe)


Lesenswert?

Und du hast doch sicher irgendwo einen "Grundtakt" mit einem Timer?
Daraus kannst du per Software deine Zeit für die LCD Ausgabe machen.

von Karl H. (kbuchegg)


Lesenswert?

Matthias Lindner schrieb:

> nachdem ich mir ein C-Buch zugelegt habe und das Forum bzw. Codesammlung
> quasi auswendig gelernt habe

Dann hätte dir aber auch auffallen müssen

* keine Ausgaben in einer ISR
* keine extensiven Berechnungen in einer ISR, es sei denn es ist 
unumgänglich
* man kann eine Timer-ISR durchaus für mehr als eine Sache hernehmen. Es 
spricht nichts dagegen, dass zb ein für die Tastenentprellung 
zuständiger Timer sich auch noch um so etwas wie eine Systemzeit 
kümmert, bzw. regelmässig wiederkehrende Abläufe anstösst.


Dein Encoder-ISR wird zb regelmässig aufgerufen. Warum kann die nicht 
auch noch ein Flag setzen und dann
1
volatile uint8_t updateDisplay;
2
3
4
int main()
5
{
6
  ....
7
8
  while( 1 ) {
9
10
    if( updateDisplay )
11
    {
12
      updateDisplay = 0;
13
14
      ... dein Code für die ADC Abfrage und Ausgabe
15
    }
16
  }
17
}
18
19
ISR(TIMER0_OVF_vect)
20
{
21
  ....
22
23
  updateDisplay = 1;
24
}

Wenn dir das (wegen der fixen Zeit für die Encoder Auswertung) zu häufig 
ist, dann eben
1
int main()
2
{
3
  ...
4
  while( 1 )
5
  {
6
7
    if( updateDisplay == 100 )
8
    {
9
      updateDisplay = 0;
10
11
      ...
12
    }
13
  }
14
}
15
16
ISR( ... )
17
{
18
  ....
19
  updateDisplay++;
20
}

von Karl H. (kbuchegg)


Lesenswert?

> (schätze mal der Watchdog greift dort ein)..

Was heißt 'schätze mal'.
Du bist der Programmierer! Das musst du WISSEN, nicht schätzen.

von Matthias L. (lindner8712)


Lesenswert?

Das mit der zählenden variable ist auch eine Lösung. Werd ich mal 
versuchen. Danke dafür

wegen dem Interrupt; Interrupts sollen kurzgehalten werden, damit das 
Hauptprogramm nicht "verhungert" soweit mein Schulwissen. Da ich jedoch 
ab und zu wirre Zeichen auf dem Display hatte, wenn ein Interrupt 
während der Display aktualisierung eintrat. hab ich mir weiter nichts 
dabei gedacht. Es ist ja auch keine Zeitkritische Sache dabei.

Jetzt habe ich es mit einer zählenden Flag gelöst und während der 
Abarbeitung sind alle Interrupts gesperrt!!!

von Matthias L. (lindner8712)


Lesenswert?

Karl Heinz Buchegger schrieb:
>> (schätze mal der Watchdog greift dort ein)..
>
> Was heißt 'schätze mal'.
> Du bist der Programmierer! Das musst du WISSEN, nicht schätzen.

Leider kann ich nicht in den Schwarzen Käfer hineingucken da ich kein 
JTAG o.ä. habe. es war auch nicht der Watchdog sondern das Programm ist 
beim Rücksprung aus dem Interrupt wieder zum Beginn der int main(void) 
Methode
gehüpft. warum muss ich nochmal nachforschen. leider fällt ja simulieren 
bei der LCD Library auch flach!

von Georg G. (df2au)


Lesenswert?

Matthias Lindner schrieb:
> Da ich jedoch
> ab und zu wirre Zeichen auf dem Display hatte, wenn ein Interrupt
> während der Display aktualisierung eintrat.

Das sollt dir zu denken geben. Da fummelt ein Interrupt an Dingen, von 
denen er die Finger lassen soll. Falls das aber unumgänglich ist, kann 
man immer noch den kritischen Teil (meist nur ein, zwei Statements) in 
der main() durch "atomic region" schützen.

von Matthias L. (lindner8712)


Lesenswert?

Also,

jetzt läuft der Controller seit fast 15 Minuten ohne Fehler bzw. 
"abstruz". Es war doch die sinnlose Idee mit dem NE555.

Danke für eure Hilfe!!!

Viele Grüße aus der Oberpfalz

Matthias

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.