Hallo liebe Mikrocontroller Team :) Und zwar hab ich folgendes Problem. Ich hab mir einen 3x3x3 LED Cube gebaut und er funktioniert auch soweit. Ich kann meine Programme ohne Probleme laufen lassen. Nun möchte ich aber mittels einem Taster (Interrupt) zwischen meinen Programmen hin und her schalten. Nur so wie ich das Versuche geht es nicht vllt könnt ihr mir ja weiterhelfen. Hier der Code: #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <inttypes.h> uint8_t status; void delay_ms(uint16_t ms) { for(uint16_t t=0; t<=ms; t++) _delay_ms(1); } int main() { cli(); DDRD = 0b11110111; DDRC = 0xFF; DDRB = 0xFF; GIMSK = (1<<(INT1)); // Interrupt Freigeben MCUCR |= (1<<ISC11) | (1<<(ISC10)) ; // Interrupt löst bei steigender Flanke aus sei(); // Interrupt wird eingeschalet while (1) //Endlos { if (status==1) { void OB(); status=0; } if (status==2) { void ME(); status=0; } if (status==3) { void UE(); status=0; } } return 0; } ISR(INT1_vect) //Interruptvektor { status=1; } void OE () { PORTD &=~(1<< PD2); PORTD |=(1<< PD0); //Ebene 3 PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } void ME () { PORTD &=~(1<< PD0); //Ebene 2 PORTD |=(1<< PD1); PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } void UE () { PORTD &=~(1<< PD1); //Ebene 1 PORTD |=(1<< PD2); PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } Danke im Vorraus :)
> Nun möchte ich aber mittels einem Taster (Interrupt) zwischen meinen > Programmen hin und her schalten. Eine auf den ersten Blick offensichtliche, aber auf den zweiten Blick ungünstige Idee. Stand der Technik ist eine andere Art der Tasterabfrage. Zu dem Thema gibt es 'zig Beiträge hier im Forum und Tutorials in der Artikelsammlung (Entprellung).
Danke für die Schnelle Antwort. Mit der Taserabfrage wollt ich ja auch machen aber ist in unseren Aufgabenstellung nicht so gegeben. Wir sollen es mittels Interrrupts lösen. Blos ich weiß nicht wo meine Fehler im Code ist. eigentlich soll ja wenn der Interrupt ausgelöst wurde der status auf 1 gestzt werden ... jedoch geschieht das nicht, denn in der Main wird dann das Programm nicht aufgerufen. Es werden nur die If anweißungen abgefragt, als wäre nix passiert. MfG Michael
> Blos ich weiß nicht wo meine Fehler im Code ist.
Der eigentliche Fehler in deinem Programm besteht in der Ansteuerung des
Cube.
Die gehört in einen Interrupt (und muss völlig ohne _delay_ms
auskommen), nicht die Tastenabfrage.
Und by the way.
Das hier
if (status==1)
{
void OB();
ist kein Aufruf der Funktion OB.
Was meinst du mit "volatile"? Wie meinste das bei der Ansteurung an meinem Cube? MfG Michael
Michael schrieb: > Was meinst du mit "volatile"? FAQ: Was hat es mit volatile auf sich > Wie meinste das bei der Ansteurung an meinem Cube? Die ganze Ansteuerung ist verkorkst.
So.. ich habs jetzt soweit geschrieben. Jetzt möchte ich noch gerne das das Interrupt mitzählt und 1. Programm auswählt danach 2. und so weiter ... und bis zu einem bestimmten Punkt zählt und wieder aufhört. Hier erstma der Code: #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include <inttypes.h> void OE(),ME(),UE(); volatile int i; void delay_ms(uint16_t ms) { for(uint16_t t=0; t<=ms; t++) _delay_ms(1); } int main() { cli(); DDRD = 0b11110111; DDRC = 0xFF; DDRB = 0xFF; GIMSK = (1<<(INT1)); // Interrupt Freigeben MCUCR |= (1<<ISC11) | (1<<(ISC10)) ; // Interrupt löst bei steigender Flanke aus sei(); // Interrupt wird eingeschalet //B 000 001 Startwert für Wanderbalken //B 000 001 Startwert für Wanderbalken while (1) //Endlos { if (i==1) { OE(); i=0; } if (i==2) { ME(); i=0; } if (i==3) { UE(); i=0; } } return 0; } ISR(INT1_vect) //Interruptvektor { i=1; } void OE () { PORTD &=~(1<< PD2); PORTD |=(1<< PD0); //Ebene 3 PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } void ME () { PORTD &=~(1<< PD0); //Ebene 2 PORTD |=(1<< PD1); PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } void UE () { PORTD &=~(1<< PD1); //Ebene 1 PORTD |=(1<< PD2); PORTB &=~(1<<PB3); PORTC |=(1<< PC5) ; // _delay_ms(200); PORTC &=~(1<< PC5) ; PORTC |=(1<< PC4) ; // _delay_ms(200); PORTC &=~(1<< PC4) ; PORTC |=(1<< PC3) ; // _delay_ms(200); PORTC &=~(1<< PC3) ; PORTC |=(1<< PC2) ; // _delay_ms(200); PORTC &=~(1<< PC2) ; PORTC |=(1<< PC1) ; // _delay_ms(200); PORTC &=~(1<< PC1); PORTC |=(1<< PC0) ; // _delay_ms(200); PORTC &=~(1<< PC0); PORTB |=(1<< PB5) ; // _delay_ms(200); PORTB &=~(1<< PB5); PORTB |=(1<< PB4) ; // _delay_ms(200); PORTB &=~(1<< PB4); PORTB |=(1<< PB3) ; // _delay_ms(200); } MfG Michael Dankeschön schonmal :P
> Jetzt möchte ich noch gerne das das Interrupt mitzählt
Dann darfst du halt nicht schreiben
1 | ISR(INT1_vect) //Interruptvektor |
2 | {
|
3 | i = 1; |
4 | }
|
sondern du müsstest schreiben
1 | ISR(INT1_vect) //Interruptvektor |
2 | {
|
3 | i += 1; |
4 | }
|
damit du andere Werte als i==1 bekommst. Dann wirst du aber sehen, dass es dir mit dem Taster nicht gelingt, gezielt eins der Programme auszuwählen. Das liegt einmal an deiner Programmlogik. Du setzt nämlich i nach dem Ausführen eines Programmteils wieder auf 0, d.h. ein Programmteil wird einmal ausgeführt und nicht wiederholt. Um jetzt z.B. in den Programmteil UE zu kommen (i==3), müsstest du per Taster und Interrupt i dreimal erhöhen, ohne dass ein anderer Programmteil aktiv wird und i wieder nullt. Von der Programmlogik her bräuchtest du also eine Erkennung, wann ist der Benutzer fertig mit der Eingabe und wann kann dar Programmteil gestartet werden. Diese Erkennung kann z.B. eine weitere Taste liefern oder z.B. eine längere Pause nach einer oder mehreren Tastendrücken. Zum anderen liegt es an der verkorksten, d.h. nicht entprellten Tasterabfrage. Du erwartet pro Tastendruck exakt eine steigende Flanke. Das ist aber in der Realität nicht so. Es kommen durch das Prellen wesentlich mehr Flanken und i wird unreproduzierbar oft erhöht! Deswegen wird der "Aufwand" betrieben, der in Entprellung beschrieben ist.
Ich möchte das ja so machen das er das Programm ausführt und per Tastendruck das nächste usw ... wenn er alle Programme durchlaufen hat soll er wieder von neuen beginnen .. gibts es da keine einfache Zählmöglichkeit?
> Mit der Taserabfrage wollt ich ja auch machen aber ist in unseren > Aufgabenstellung nicht so gegeben. Wir sollen es mittels Interrrupts > lösen. Eine Tasterabfrage mit Entprellung kann auch mit dem Timer-Interrupt gemacht werden. so gesehen wäre die Aufgabenstellung doch auch gelöst oder? > Blos ich weiß nicht wo meine Fehler im Code ist. eigentlich soll > ja wenn der Interrupt ausgelöst wurde der status auf 1 gestzt werden ... > jedoch geschieht das nicht, denn in der Main wird dann das Programm > nicht aufgerufen. Es werden nur die If anweißungen abgefragt, als wäre > nix passiert. Wird dein INT1-Interrupt überhaupt aufgerufen? Ich habe deine Schaltung am INT1-Pin nicht gesehen. Besteht das überhaupt die Möglichkeit, dass da eine steigende Flanke auftaucht? Und ich habe deinen Sourcecode zur Einstellung des INT1 nicht mit dem Datenblatt verglichen. Bist du sicher, dass bei deinem hier unbekannten AVR diese Abfolge korrekt und ausreichend ist?
1 | GIMSK = (1<<(INT1)); |
2 | MCUCR |= (1<<ISC11) | (1<<(ISC10)) ; // steigende Flanke |
3 | sei(); |
Wenn möglich installiere an einem freien Output-Pin eine LED (natürlich mit Vorwiderstand) und benutze diese LED zur Anzeige, ob die ISR von INT1 überhauot angesprungen wurde z.B. durch Toggeln dieser ISR-Anzeige-LED. Bei der Programmentwicklung mit Interrupts ist es auch nützlich, wenn man eine LED hat, die zeigt, ob der AVR "abgestürzt" ist und sich resettet hat. Dazu kann man z.b. zu Beginn von main() eine LED 1s leuchten lassen. Wenn das folgende Programm dann korrekt läuft, darf diese RESET-Anzeige-LED nicht mehr leuchten.
> Ich möchte das ja so machen das er das Programm ausführt und per > Tastendruck das nächste usw ... wenn er alle Programme durchlaufen hat > soll er wieder von neuen beginnen .. gibts es da keine einfache > Zählmöglichkeit? Sicher gibt es die, aber du hast was angefangen, dass von Haus aus verkorkst und kompliziert ist. Das möchte man (ich) nicht umbiegen, so dass es doch noch geht. Geh in deiner Programmentwicklung einen Schritt zurück und lerne, wie man sauber eine Taste abfragt. Z.B. mit einer Routinen aus Entprellung oder dem Beispiel http://www.mikrocontroller.net/articles/Pollin_Funk-AVR-Evaluationsboard#Tasty_Reloaded Dann bau damit einen Zähler. Pro sauber entprelltem Tastendruck zählst du eine Variable hoch. Überlege dir, welche Werte die Variable annehmen darf und was passieren soll, wenn der Wertebereich verlassen wird. Soll dann runtergezählt werden oder von vorne angefangen werden? Dann mach was mit der Variablen, also vergleiche sie mit einem Wert und führe die geplanten Aktionen durch. Überlege dir was passieren soll, wenn die Aktion abgeschlossen ist. Soll dann "nix" (was ist das?) gemacht oder soll die Aktion wiederholt werden oder soll die nächste Aktion gemacht werden?
also es funktioniert soweit ... wenn ich ein taster drücke führt er das nächste Programm aus .. dann hab ich in der isr noch eine if Anweisung gemacht die die variable i auf 0 zuruecksetz ... bloß manchmal werden 2 Programme mit einmal ausgeführt und manchmal klappt alles ... liegt das dann am taster ? was ich mir eigentlich schon denke... danke schonmal ... hast mir schon viel geholfen ;) mfg Michael
Michael schrieb: > gemacht die die variable i auf 0 zuruecksetz ... bloß manchmal werden 2 > Programme mit einmal ausgeführt und manchmal klappt alles ... liegt das > dann am taster ? was ich mir eigentlich schon denke... Du hast höchst wahrscheinlich gerade das erste mal Tastenprellen in Aktion gesehen. Warte noch ein Weilchen, bis deine Tasten alt und abgenutzt werden. Dann wird aus dem 'manchmal' ein 'fast immer'
Ok da muss ich die halt noch entprellen ... danke für die Antwort :)
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.