www.mikrocontroller.net

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


Autor: Ronald E. (ronald_1)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

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

Bewertung
0 lesenswert
nicht 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
  sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 : 5 );

Oder meinetwegen, wenn dir der ?: Operator noch unheimlich ist
  if( Temperatur_Soll % 2 == 0 )
    sprintf( buf, "%2d.0C", Temperatur_Soll / 2 );
  else
    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.)

Autor: Ronald E. (ronald_1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke! Ich versuche gleich mal alles umzusetzen.

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

Bewertung
0 lesenswert
nicht lesenswert
Bei dir sieht das dann zunächst so aus
#include <avr/io.h>
#define F_CPU 3686400UL
#include <util/delay.h>
#include <stdint.h>
#include <avr/interrupt.h>

#include "C:\Users\Ronn\Documents\kühlung\lcd\avr_lcd\lcd.h"
#include "C:\Users\Ronn\Documents\kühlung\lcd\avr_lcd\temp.h"

// Temperatur ist immer das Doppelte des wahren Wertes. Dadurch gewinne
// ich automatisch 1 Nachkommastelle, ohne sie extre mitschleifen zu
// muessen
volatile uint8_t Temperatur_Soll = 20;   // 10 Grad


ISR(INT0_vect)
{
  Temperatur_Soll++;
}

ISR(INT1_vect)
{
  Temperatur_Soll--;
}

int main(void)
{
  int8_t puffer[20];
  uint8_t buf[20];

  lcd_init();
  lcd_clear();

  DDRD = 0x0;  

  GIMSK |= (1 << INT1) | (1 << INT0);     // INT0 + INT1
  MCUCR |= (1 << ISC11) | (1 << ISC10) |  // beide auf steigende Flanke
           (1 << ISC01) | (1 << ISC00);

  sei();

  while (1)
  {
    therm_read_temperature(puffer);
    lcd_setcursor(3,2);
    lcd_string(puffer);
  
    sprintf( buf, "%2d.%0dC", Temperatur_Soll / 2, Temperatur_Soll % 2 ? 0 : 5 );
    lcd_setcursor(3,1);
    lcd_string(buf);
  }
}

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!

Autor: Ronald E. (ronald_1)
Datum:

Bewertung
0 lesenswert
nicht 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...).

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

Bewertung
0 lesenswert
nicht 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.

Autor: Ronald E. (ronald_1)
Datum:

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

Autor: Ronald E. (ronald_1)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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
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

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

Bewertung
0 lesenswert
nicht lesenswert
Ronald E. schrieb:

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

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

Autor: Ronald E. (ronald_1)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ahh ja! Jetzt funktionierts :)

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.