Interrupt löst ungewollt aus

OP #1971756
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
Angehängte Dateien:
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.)
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!
OP
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...).
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.
OP
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
Angehängte Dateien:
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

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 15 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.