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
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!
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.
Ja nun funktionierts! Nun muss ich mir das mit dem entprellen noch anschaun. Vielen Dank!
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.