Forum: Mikrocontroller und Digitale Elektronik Interrupt löst ungewollt aus


von Ronald E. (ronald_1)


Angehängte Dateien:

Lesenswert?

Hallo zusammen!

Ich habe folgendes Problem: Ich möchte externe Interrupts über INT0 und 
INT1 (4,7KOhm Pull-Down) bei einem ATMEGA8 einlesen. Das funktioniert 
auch, jedoch scheinen beide Interrupts zu reagieren, wenn an nur einem 
der Beiden einen steigende Flanke anliegt. Die Schaltung kann es nicht 
sein, da ich nur einen Taster habe, und diesen zum Probieren immer an 
den jeweiligen Pin hänge. Hat evt. jemand eine Idee woran es liegen 
könnte? Der Code ist im Anhang. Ich bitte um Hilfe.

MfG Ronald

von Karl H. (kbuchegg)


Lesenswert?

Bleiben da Taster drann?

Wenn ja: Taster liest man nicht mit Interrupts ein.
Schau dir den Atrikel Entprellung im Wiki an. Dort findest du 
genügend Ideen, wie man Tasten zuverlässig einliest.
Taster schliesst man auch nicht so an, dass sie gegen Vcc schalten, 
sondern so dass sie gegen Masse schalten. Dann kann man den internen 
Pullup Widerstand benutzen und braucht keinen externen zusätzlichen 
Widerstand

Für die Grundlagen des Tasteranschlusses, siehe AVR-Tutorial. Das 
Kapitel über I/O
Für die C-Grundlagen siehe AVR-GCC-Tutorial


Und was du da mit dem Komma machst ... das ist doch unnötiger Unsinn. 
Nimm einfach alle Zahlen mal 2, dann hast du eine 'Kommastelle' die nur 
5 oder 0 sein kann.
Anstelle von 20 Grad speicherst du dir intern den Zahlenwert 40. 
Anstelle von 20.5 Grad, dann eben 41, 21 Grad sind der Zahlenwert 42 
usw.
Für Anzeigezwecke zerlegst du dann den Zahlenwert wieder
1
  sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 : 5 );

Oder meinetwegen, wenn dir der ?: Operator noch unheimlich ist
1
  if( Temperatur_Soll % 2 == 0 )
2
    sprintf( buf, "%2d.0C", Temperatur_Soll / 2 );
3
  else
4
    sprintf( buf, "%2d.5C", Temperatur_Soll / 2 );


Aber dadurch, dass du ein intern einfach nur ein geeignet gewähltes 
Vielfaches hast, vereinfachen sich die ganzen internen Vorgänge, wie zb 
Vergleiche oder sonstiges Rechnen mit deinen Temperaturwerten.

(Abgesehen davon, dass deine Kommasteuerung sowieso nicht funktioniert, 
was dich wahrscheinlich zur Annahme bringt, dass irgendwas mit den 
Interrupts nicht stimmt. Lass den Unsinn und verwende einfach ein für 
deine Zwecke geeignetes Vielfaches.)

von Ronald E. (ronald_1)


Lesenswert?

Danke! Ich versuche gleich mal alles umzusetzen.

von Karl H. (kbuchegg)


Lesenswert?

Bei dir sieht das dann zunächst so aus
1
#include <avr/io.h>
2
#define F_CPU 3686400UL
3
#include <util/delay.h>
4
#include <stdint.h>
5
#include <avr/interrupt.h>
6
7
#include "C:\Users\Ronn\Documents\kühlung\lcd\avr_lcd\lcd.h"
8
#include "C:\Users\Ronn\Documents\kühlung\lcd\avr_lcd\temp.h"
9
10
// Temperatur ist immer das Doppelte des wahren Wertes. Dadurch gewinne
11
// ich automatisch 1 Nachkommastelle, ohne sie extre mitschleifen zu
12
// muessen
13
volatile uint8_t Temperatur_Soll = 20;   // 10 Grad
14
15
16
ISR(INT0_vect)
17
{
18
  Temperatur_Soll++;
19
}
20
21
ISR(INT1_vect)
22
{
23
  Temperatur_Soll--;
24
}
25
26
int main(void)
27
{
28
  int8_t puffer[20];
29
  uint8_t buf[20];
30
31
  lcd_init();
32
  lcd_clear();
33
34
  DDRD = 0x0;  
35
36
  GIMSK |= (1 << INT1) | (1 << INT0);     // INT0 + INT1
37
  MCUCR |= (1 << ISC11) | (1 << ISC10) |  // beide auf steigende Flanke
38
           (1 << ISC01) | (1 << ISC00);
39
40
  sei();
41
42
  while (1)
43
  {
44
    therm_read_temperature(puffer);
45
    lcd_setcursor(3,2);
46
    lcd_string(puffer);
47
  
48
    sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 : 5 );
49
    lcd_setcursor(3,1);
50
    lcd_string(buf);
51
  }
52
}

Aber um eine vernünftige, zuverlässige Entprellung kommst du nicht 
herum. Das was du hattest, ist keine Entprellung. Das ist nur ein völlig 
unnötiges und nutzloses Warten in einer ISR. Nur hilft dir das nichts, 
denn wenn der Taster prellt, wird der nächste Interrupt vom prellenden 
Taster angestossen. Ob du nun in der ISR wartest oder nicht.

Entprellung


Und definier deine Ausgabepuffer nicht so knapp!

von Ronald E. (ronald_1)


Lesenswert?

Ich hab mal den Code rüberkopiert und mal schnell ausprobiert (übrigens 
nochmals danke!), jedoch scheinen immer noch beide interrupts 
anzusprechen (Temperatur geht rauf oder runter, beim gleichen 
Interrupt).
Ich bau nun das ganze mal um (nutzung der internen pull-ups usw...).

von Karl H. (kbuchegg)


Lesenswert?

Dann check noch mal deine Pulldown Widerstände. Jede wette, dass du in 
Wirklichkeit offene Eingänge hast.

Besser wäre es, wenn du das Zeugs einfach umverdrahtest.

Die Taster schliessen nach Masse. Die externen Pulldown fallen überhaupt 
weg. Dafür werden die internen Pullup aktiviert und die Interrupts (für 
jetzt, der Teil ist noch zu ersetzen) auf fallende Flanke konfiguriert.

von Ronald E. (ronald_1)


Lesenswert?

Ja nun funktionierts! Nun muss ich mir das mit dem entprellen noch 
anschaun.
Vielen Dank!

von Ronald E. (ronald_1)


Angehängte Dateien:

Lesenswert?

Das Entprellen funktioniert nun, leider liefert die gewünschte 
Temperatur falsche Sprünge:

13 Tastendruck;
14.4 Tastendruck;
14 Tastendruck;
15.5 ...
.
.
.
Die Funktion
1
sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 : 5 );

nimmt die Temperatur und halbiert sie. Der zweite Abschnitt ist modulu 
2. Bei 1 --> Ausgabe 0, bei 0 --> Ausgabe 5.

Leider seh ich nicht wo der Fehler liegt. Ich bitte nochmals um Hilfe.

MfG Ronald

von Karl H. (kbuchegg)


Lesenswert?

Ronald E. schrieb:

> Die Funktion
>
>
1
> sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 :
2
> 5 );
3
>
>
> nimmt die Temperatur und halbiert sie. Der zweite Abschnitt ist modulu
> 2. Bei 1 --> Ausgabe 0, bei 0 --> Ausgabe 5.
>
> Leider seh ich nicht wo der Fehler liegt. Ich bitte nochmals um Hilfe.

Mein Fehler, genau anders rum

  sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 5 
: 0 );

oder ausführlicher

  sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 == 
0 ? 0 : 5 );


Wenn der Ausgangswert gerade ist, dann soll eine 0 angehängt werden, bei 
ungeraden Zahlen eine 5

Du hättest auch die langatmigere Version mit einem if-else nehmen 
können.





>
> MfG Ronald

von Ronald E. (ronald_1)


Lesenswert?

Ahh ja! Jetzt funktionierts :)

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.