Hallo allerseits, ich würde gerne durch drücken eines Tasters an PD2 die Variable "teiler" jeweils um 1 erhöhen (entprellen hab ich erstmal weggelassen) um damit den Teiler für meine ausgegebene Frequenz zu vergrößern. An den Ausgängen PD5 und PD6 habe ich zwei Led`s angeschlossen die gegenläufig negiert werden. Wenn ich den Taster nun drücke, ändert sich allerdings meine ausgegeben Frequenz nicht. Der Fehler ist für euch warscheinlich nicht so schwer zu sehen, für mich allerdings schon. Danke für jeden Tip #include <avr\io.h> #include <avr\interrupt.h> #include <stdint.h> int count; int teiler; ISR( TIMER0_OVF_vect ) //Interrupt der durch den Timer Overflow ausgelöst wird { count++; if (count >= teiler) { PORTD ^= (1<<PD5) | (1<<PD6); //pin 5 und 6 von Port D Toggeln } } int main(void) { DDRD &= ~(1<<DDD2); /* Pin PD2 als Eingang */ PORTD |= (1<<PD2); /* internen Pull-Up an PD2 aktivieren */ DDRD = (1 << DDD5) | (1 << DDD6); //Pin D5 und D6 als Ausgang definieren PORTD |= (1<<PD5) | (0<<PD6); //Pin D5 auf logisch 1 und D6 auf 0 TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); //Prescaler auf CPUClock/1024 TIMSK = ( 1 << TOIE0 ); //TIMSK: Timer Interrupt Mask sei(); while( 1 ) { if ( PIND & (1<<PIND2) ) { teiler++; } } }
1.: Du müsstest count auch wieder auf Null setzen, wenn die LEDs umgeschaltet wurden. 2.: Variablen, die sowohl im Hauptprogramm als auch in Interrupt-Handlern verwendet werden (also in Deinem Programm die Variable teiler), müssen volatile deklariert werden, da es sonst passieren kann, dass Zugriffe wegoptimiert werden und das ganze nicht mehr funktioniert.
Habe die Beiden Mängel behoben, jetz blinken die Leds komischerweise mit etwa 1Hz und auf den Taster wollen sie auch nicht so richtig hören. Trotzdem danke, werds mir nochmal durch den Kopf gehen lassen.
Gastulus wrote: > Habe die Beiden Mängel behoben, jetz blinken die Leds komischerweise mit > etwa 1Hz und auf den Taster wollen sie auch nicht so richtig hören. Ich hoffe, Du hast das Rücksetzen von count in die Klammer vom if mit reingeschrieben... > Trotzdem danke, werds mir nochmal durch den Kopf gehen lassen. Tu das. Und schick vielleicht noch mal den neuen Code mit den "Verbesserungen".
Ja, hab ich in die Klammer mit rein geschrieben, so sieht er jetzt aus. #include <avr\io.h> #include <avr\interrupt.h> #include <stdint.h> volatile uint8_t count; volatile uint8_t teiler; ISR( TIMER0_OVF_vect ) //Interrupt der durch den Timer Overflow ausgelöst wird { count++; if (count >= teiler) { PORTD ^= (1<<PD5) | (1<<PD6); //pin 5 und 6 von Port D Toggeln count = 0; } } int main(void) { DDRD &= ~(1<<DDD2); /* Pin PD2 als Eingang */ PORTD |= (1<<PD2); /* internen Pull-Up an PD2 aktivieren */ DDRD = (1 << DDD5) | (1 << DDD6);//Pin D5 und D6 als Ausgang PORTD |= (1<<PD5) | (0<<PD6); //Pin D5 auf logisch 1 und D6 auf 0 TCCR0 = ( 1 << CS02 ) | ( 1 << CS00 ); //Prescaler auf CPUClock/1024 TIMSK = ( 1 << TOIE0 ); //TIMSK: Timer Interrupt Mask sei(); while( 1 ) { //Fuehre Aktion aus, wenn Bit Nr. 3 in PINC gesetzt (1) ist // if ( PIND & (1<<PIND2) ) { teiler++; } } }
> //Fuehre Aktion aus, wenn Bit Nr. 3 in PINC gesetzt (1) ist // > if ( PIND & (1<<PIND2) ) Das widerspricht sich! Wo hängt der Taster dran? Port D oder C? Und noch was: Ist der Taster High- oder Low-side angeschlossen? Im zweiten Fall (der aber in den meisten Fällen vorliegt) muss die Abfrage invertiert sein (Taster gedrückt -> Low-Pegel am Pin). Also
1 | if (!(PIND & (1<<PIND2))) |
2 | {}
|
BTW: count muss nicht volatile sein, da es nur in der ISR verwendet
wird.
> PORTD |= (1<<PD5) | (0<<PD6); //Pin D5 auf logisch 1 und D6 auf 0
Das (0 << PD6) bringt an der Stelle überhaupt nichts. Wenn PD6 vorher
gesetzt war (was es nach einem Reset natürlich nicht ist, weshalb das an
dieser Stelle zumindest nicht zu einer Fehlfunktion führt), bleibt es
das auch. Merke:
X | 0 = X
Und eine Null kannst Du schieben wie Du willst, es bleibt immer eine
Null.
0 = 0b00000000
0 << PD6 = 0b00000000
Merkst Du was?
Bei einer 1 hingegen macht es Sinn:
1 = 0b00000001
1 << PD5 = 0b00100000
Hast recht das hat sich wiedersprochen, aber der Taster ist tatsächlich an Port D. Der Taster ist auf Masse gezogen wenn er nicht betätigt wird, bei Betätigung liegen +5V am Pin. Werde morgen nochmal drüber nachdenken. Danke
Gastulus wrote: > Hast recht das hat sich wiedersprochen, aber der Taster ist tatsächlich > an Port D. Der Taster ist auf Masse gezogen wenn er nicht betätigt wird, > bei Betätigung liegen +5V am Pin. Werde morgen nochmal drüber > nachdenken. Danke Sicher? Und warum hast Du dann den Pull-Up aktiviert? Was ist das für ein Taster?
Ich habe gedacht das das so gemacht wird, das ist so ein MiniTaster auf meinem Pollin EvalBoard. Der Taster liegt im ungetasteten Zustand mit der einen Seite über einen 33K-Widerstand auf Masse, die andere Seite wird beim drücken mit +5V verbunden.
Autsch ja, das Pollin-Board... Stimmt, da haben die aus irgendwelchen unerfindlichen Gründen High-Side-Taster mit externen Pull-Downs dran, und das obwohl die AVRs integrierte Pull-Ups haben... Dann musst Du allerdings den internen Pull-Up deaktivieren, weil Du sonst im Zustand "Taster nicht gedrückt" einen Pegel irgendwo zwischen gut und böse hast, der möglicherweise vom µC weder definiert als High noch als Low erkannt werden kann.
Habe den Pullup deaktiviert, und siehe da, die Frequenz reagiert zumindest schon mal auf den Taster. Aber, manchmal blinken die Leds schneller wenn ich drücke und dann wieder ganz langsam... die Frequenz sinkt also nicht kontinuierlich mit zunehmender Tastanzahl ab. Dafür hätten wir das mit den Pullups aber schonmal geklärt.
Gastulus wrote: > Habe den Pullup deaktiviert, und siehe da, die Frequenz reagiert > zumindest schon mal auf den Taster. Aber, manchmal blinken die Leds > schneller wenn ich drücke und dann wieder ganz langsam... die Frequenz > sinkt also nicht kontinuierlich mit zunehmender Tastanzahl ab. Dafür > hätten wir das mit den Pullups aber schonmal geklärt. Doch, ich vermute schon, dass die Frequenz sich kontinuierlich ändert, allerdings so schnell, dass Du das überhaupt nicht mitbekommst. Der Taster wird schließlich ohne jegliche Wartezeit zyklisch abgefragt. Je nach Taktfrequenz des µC gehe ich mal davon aus, dass bei gedrücktem Taster die Erhöhung von teiler alle paar µs geschieht. teiler ist aber eine 8-Bit-Variable, die schon nach 256 Erhöhungen (also nach höchstens ein paar ms) überläuft und wieder bei Null anfängt. Deshalb siehst Du nur zufällige Reaktionen des Controllers. Du musst entweder eine vernünftige Taster-Auswertung einbauen, damit jeder Tastendruck nur einmal erkannt wird und teiler beim Drücken der Taste nur einmal erhöht wird, oder füge nach der Tasterabfrage eine Wartezeit ein.
AAAAAAHHHH, jetzt habe ich verstanden, danke langsam kommt Licht in das Dunkel. Werde einfach mal mit einer einfachen Wartezeit beginnen. Wäre es aber allgemein nicht besser wenn man den Timer im CTC-Modus laufen lässt und mit dem Tastendruck immer diesen Vergleichswert hoch oder auch runter Zählt? Egal, erstmal die Sache mit der Wartezeit ausprobieren. Vielen Dank nochmal
Gastulus wrote: > AAAAAAHHHH, jetzt habe ich verstanden, danke langsam kommt Licht in das > Dunkel. Werde einfach mal mit einer einfachen Wartezeit beginnen. Das ist zum Ausprobieren für den Anfang sicher die einfachste Methode. Bedenke aber, wenn Du die Funktionen aus der util/delay.h benutzen wollen solltest, dass die _delay_ms- und _delay_us-Funktion limitiert sind in Abhängigkeit von der CPU-Frequenz (Details siehe AVR-libc-Doku). > Wäre es aber allgemein nicht besser wenn man den Timer im CTC-Modus > laufen lässt und mit dem Tastendruck immer diesen Vergleichswert hoch > oder auch runter Zählt? Das wäre eine elegantere Methode.
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.