Hallo Gemeinde, ich kämpfe hier gerade mit dem externen Interrupt des Atmega 32. Initialisiert ist er folgendermaßen: void init_interrupt0() { DDRD &= ~ (1 << PD2); //als Eingang deklarieren PORTD |=(1<<PD2); //Pullup aktivieren GICR |= (1<<INT0); //externen Interrupt 0 freigeben MCUCSR |=(1<<ISC01); //Interrupt auf fallende Flanke } in der Interruptroutine steht folgendes: ISR(INT0_vect) { weiter =1; //Boolsche Variable auf 1 setzen = Bestätigungsbedingung } Die globale Interruptfreigabe ( sei () ) erflogt im Hauptprogramm. Angeschlossen daran ist ein entprellter Taster. Entrellung siehe Anahang. Ich möchte eigentlich, dass der Interrupt genau einmal bei der Fallenden Flanke ausgelöst wird. Sollte ja laut Datenblatt so initalisiert werden. Tut er aber nicht, stattdessen löst er permanent Inerrupts aus, solange ich den Taster gedrück halte. Was mache ich falsch. Wäre cool, wenn mir jemand weiterhelfen könnte.
wt schrieb: > wie lange prellt denn der Schalter? gar nicht, da ja der Taster im moment des drückens den Kondensator schlagartig gegen Masse entlädt und somit auch dieses Potential an dem Interrupt eingang anliegt. Diese Schaltung hat sich eigentlich bewährt die hab ich auf einem unserer experimentierboards in der Schule gesehen. Zwar an einem 8051 aber das sollte ja keinen Unterschied machen. Spera schrieb: > Ist die weiter-Variable als volatile deklariert? Ja, die "weiter- Variable" ist als volatile deklariert.
Und setzt du sie in der while Schleife auch wieder zurück?^^ Wäre besser, wenn du gleich den ganzen Source Code postest. Grüße
Ich hab mir gerade die Schaltung angeschaut. Wieso hast du einen externen Pull-up Widerstand, wenn du sowieso den internen nutzt? Grüße
Der komplette Code ist noch ziemlich lang und SEHR unübersichtlich. Das ganze soll folgende Anwendung erfüllen: Ich möchte über 2 Taster (1x Inerrupt / 1x Polling) und ein LCD Display die Ladeart und den Ladestrom eines Akkus einstellen. Dazu ist die Taste die die Kapazität bzw. die Ladeart verändert im Pollingbetrieb geschalten und die OK Tast, die das ganze dann übernimmt im Interruptbetrieb, wofür die Variable weiter verantwortlich ist. Hier mal die betreffenden Zeilen:
1 | volatile bool weiter=0; //OK Taste auswahlmenü |
2 | |
3 | //*********************************************************************************************************************************
|
4 | // Externen Interrupt 0 initialisieren
|
5 | //**********************************************************************************************************************************
|
6 | |
7 | void init_interrupt0() |
8 | {
|
9 | DDRD &= ~ (1 << PD2); //als Eingang deklarieren |
10 | PORTD |=(1<<PD2); //Pullup aktivieren |
11 | GICR |= (1<<INT0); //externen Interrupt 0 freigeben |
12 | MCUCSR |=(1<<ISC01); //Interrupt auf fallende Flanke |
13 | }
|
14 | |
15 | //************************************ END ****************************************************************************************
|
16 | |
17 | |
18 | ISR(INT0_vect) |
19 | {
|
20 | weiter =1; //Boolsche Variable auf 1 setzen = Bestätigungsbedingung |
21 | }
|
22 | |
23 | unsigned int AkkuSetting(char Akku) |
24 | {
|
25 | weiter=0; |
26 | char wahl =0; |
27 | int Kapazitat=100; |
28 | weiter=0; |
29 | LcdClear(); |
30 | LcdGotoXY(3,1); |
31 | LcdStr( FONT_1X," Akku "); |
32 | LcdGotoXY(9,1); |
33 | LcdStr( FONT_1X,dtostrf(Akku,1,0,string) ); |
34 | LcdUpdate(); |
35 | |
36 | |
37 | while (weiter <1) |
38 | {
|
39 | if (wahl == 0) |
40 | {
|
41 | LcdGotoXY(1,3); |
42 | LcdStrINV( FONT_1X," Schnelladen "); |
43 | LcdGotoXY(1,4); |
44 | LcdStr( FONT_1X," 14h Laden "); |
45 | LcdGotoXY(1,5); |
46 | LcdStr( FONT_1X," Kapazitaet "); |
47 | LcdUpdate(); |
48 | }
|
49 | |
50 | if (wahl ==1) |
51 | {
|
52 | LcdGotoXY(1,3); |
53 | LcdStr( FONT_1X," Schnelladen "); |
54 | LcdGotoXY(1,4); |
55 | LcdStrINV( FONT_1X," 14h Laden "); |
56 | LcdGotoXY(1,5); |
57 | LcdStr( FONT_1X," Kapazitaet "); |
58 | LcdUpdate(); |
59 | |
60 | }
|
61 | |
62 | if (wahl==2) |
63 | {
|
64 | LcdGotoXY(1,3); |
65 | LcdStr( FONT_1X," Schnelladen "); |
66 | LcdGotoXY(1,4); |
67 | LcdStr( FONT_1X," 14h Laden "); |
68 | LcdGotoXY(1,5); |
69 | LcdStrINV( FONT_1X," Kapazitaet "); |
70 | LcdUpdate(); |
71 | }
|
72 | |
73 | while (!(PIND& (1<<PD3))&&(weiter<0x01)); //Abwarten bis Taster gedrückt |
74 | while ( PIND & (1 << PD3)&&(weiter<0x01)); //Abwarten bis Taster wieder gelöst oder Interrupt (OK Taste betätigt) |
75 | |
76 | wahl++; |
77 | |
78 | if (wahl==3) |
79 | {
|
80 | wahl=0; |
81 | }
|
82 | }
|
83 | wahl= wahl-1; |
84 | LcdClear(); |
85 | LcdGotoXY(3,1); |
86 | LcdStr( FONT_1X," Akku "); |
87 | LcdGotoXY(9,1); |
88 | LcdStr( FONT_1X,dtostrf(Akku,1,0,string) ); |
89 | LcdGotoXY(1,3); |
90 | LcdStr( FONT_1X,"Kapazitaet?" ); |
91 | LcdUpdate(); |
92 | weiter =0; |
93 | |
94 | |
95 | while (weiter<1) |
96 | {
|
97 | LcdGotoXY(5,5); |
98 | LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string)); |
99 | LcdGotoXY(10,5); |
100 | LcdStr( FONT_1X,"mA/h" ); |
101 | LcdUpdate(); |
102 | |
103 | while (!(PIND&(1<<PD3))&&(weiter0x01)); |
104 | while ( (PIND & (1 << PD3))&&(weiter<0x01)) ; |
105 | |
106 | Kapazitat = Kapazitat +100; |
107 | |
108 | if (Kapazitat ==3100) |
109 | {
|
110 | Kapazitat =100; |
111 | LcdGotoXY(8,5); |
112 | LcdStr( FONT_1X," "); |
113 | }
|
114 | |
115 | |
116 | }
|
117 | |
118 | weiter=0; |
119 | Kapazitat = Kapazitat -100; |
120 | //Auswerten der Eingaben
|
121 | |
122 | if (wahl==0) |
123 | {
|
124 | Kapazitat = Kapazitat *2/3; |
125 | }
|
126 | |
127 | if (wahl==1) |
128 | {
|
129 | Kapazitat = Kapazitat / 10; |
130 | }
|
131 | |
132 | if (wahl ==2) |
133 | {
|
134 | Kapazitat = Kapazitat *2/3; |
135 | }
|
136 | |
137 | LcdClear(); |
138 | LcdGotoXY(3,1); |
139 | LcdStr( FONT_1X," Akku "); |
140 | LcdGotoXY(9,1); |
141 | LcdStr( FONT_1X,dtostrf(Akku,1,0,string) ); |
142 | |
143 | LcdGotoXY(1,3); |
144 | LcdStr( FONT_1X,dtostrf(Kapazitat,1,0,string) ); |
145 | LcdUpdate(); |
146 | |
147 | |
148 | |
149 | return Kapazitat; |
150 | }
|
Spera schrieb: > Ich hab mir gerade die Schaltung angeschaut. > Wieso hast du einen externen Pull-up Widerstand, wenn du sowieso den > internen nutzt? Berechtigte Frage! Habe das ganze gerade so aus einem Schaltplan unseres Schulboards übernommen. Aber es ändert auch nichts, wenn ich den externen Pullup Widerstand ziehe und nur den internen verwende. Ist der Interrupt überhaupt richtig initalisiert? Gruß
Lass die Schaltung so wie sie ist und lass den internen Pullup Widerstand weg, indem du PORTD |=(1<<PD2); rauslöscht.
Nein das ist nicht der komplette Code, jedoch greift der Interrupt nur auf diese Funktion zu. Also "weiter" wird nur in Akku Settings verwendet. Das Problem ist eben, sobald ich den Interrupt auslöse, springt es mir wie gewünscht aus der while schleife wo ich die Ladeart (schnelladen, 14h Laden, Kapazität) einstelle raus. "weiter" wird ja danach wieder auf 0 gesetzt. Jedoch muss zeitgleich ein Interrupt kommen der Weiter sofort wieder auf 1 setzt und in die nächste while schleife (Eingabe der Kapazität) gar nicht mehr hineingesprungen wird, da die Bedingung zum beenden der while schleife bereits erreicht ist. Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable ein int genommen. und deren wert in der Interruptroutine hochzählen lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000 also Taktzyklen. und das bei einem 8MHz Quarz. Für mich sieht das so aus also ob der permanent interrupts bringt so lange der Taster gedrückt bleibt. Ich kann jedoch mit dem Datenblatt kein Indiz finden was ich falsch initalisiert habe. Das deaktiviern von PORTD |=(1<<PD2); ändert auch nichts.
> Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable > ein int genommen. und deren wert in der Interruptroutine hochzählen > lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000 > also Taktzyklen. und das bei einem 8MHz Quarz. > Für mich sieht das so aus also ob der permanent interrupts bringt so > lange der Taster gedrückt bleibt. Ich kann jedoch mit dem Datenblatt > kein Indiz finden was ich falsch initalisiert habe. Schau Die mal PeDas Entprellung in Software (im Timer-Interrupt) an, sie enthält auch eine Flankenerkennung. Duch die Vierfachabfrage ist sie auch sehr störfest und kommt mit den labrigsten Tastern zurecht. Taster am ext.-Interrupt macht man eigentlich nur, wenn man damit den AVR aus dem Power-Down-Sleep holen will. Das eigentliche Tastenauslesen macht nach dem Wecken dann wieder der Timer-Int. ...
Genau. Für die Tastenabfrage würde ich auch einen Timer und keinen Interrupt verwenden. Trotzdem würde ich dir raten, an deiner Stelle ein neues kleines Projekt zu machen, wo du versuchst, jeweils mit Interrupt und dannach mit Timer eine Taste abzufragen. Wenn es dort funktioniert, kannst du es auch bei deinem großen Projekt verwenden. Grüße
Dirk K. schrieb: > Ich hab mir vorhin mal den Spaß gemacht und anstatt einer Bool Variable > ein int genommen. und deren wert in der Interruptroutine hochzählen > lassen. Nach 1 Tastendruck stand die irgendwo zwichen 20000 und 40000 Weil du den Interrupt nicht auf Flanke konfiguriert hast. Du setzt ISC01 im falschen Register.
Stimmt auch. Du musst es im MCUCR Register setzen. So wie du es jetzt hast, triggert der Interrupt solange, wie der INT0 auf Low ist.
Danke euch, das war es... Wenn ich den ISC01 im MCUCR setze, dann geht es auch wie es soll. Weiß auch nicht woher ich noch ein S im MCUCR hatte. Komisch nur, dass der Kompiler nicht gemeckert hat. Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im gegensatz zu dem externen Interrupt?
Dirk K. schrieb: > auch nicht woher ich noch ein S im MCUCR hatte. Komisch nur, dass der > Kompiler nicht gemeckert hat. Warum sollte er. MCUSR gibt es ja auch. > Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist > dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im > gegensatz zu dem externen Interrupt? Och nö, das wurde hier doch schon mehrfach bis zum Erbrechen und bis in das letzte Detail "ausdiskutiert". Wiki und Suche liefern massenhaft Infos.
Stefan Ernst schrieb: > Och nö, das wurde hier doch schon mehrfach bis zum Erbrechen und bis in > > das letzte Detail "ausdiskutiert". Wiki und Suche liefern massenhaft > > Infos. alles klar, dann les ich mich da mal schlau. Danke mal dafür Stefan Ernst schrieb: > Warum sollte er. MCUSR gibt es ja auch. klingt logisch! Vielen Dank nochmals für euere Hilfe.
Dirk K. schrieb u.A.: > Aber jetzt noch mal was grundlegendes. Tasterabfrage über Timer. Wie ist > dabei die generelle Vorgehensweiße und welchen Vorteil bringt es mir im > gegensatz zu dem externen Interrupt? Ich habe nicht umsonst in meinem Beitrag weiter oben Beitrag "Re: Problem mit externem Inerrupt" das Wort Entprellung als Link eingesetzt... ;-) Da ist das nämlich alles beschrieben bzw. da gibt es weiterführende Links. Brauchste nur zu lesen und zu verstehen. In der Codesammlung unter dem Suchbegriff "bulletproof" findest Du auch eine umfangreiche Diskussion, in der alle Fragen, die Dir einfallen könnten bereits gestellt und erschöpfend beantwortet wurden. ...
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.