OK...danke...hört sich logisch an...Zitat von SprinterSB
Jetzt muss ich schauen, wie ich das realisiere...![]()
Das Zeug ist compilerspezifisch. Jeder Compiler hat seinen eingenen Weg, Interrupts und Signale zu definieren und implementiert unterschiedliche Pragmas -- wenn überhaupt.Zitat von funky78
avr-gcc zB implementiert überhaupt keine Pragmas und externen Interrupt0 definiert man via
Eine Möglichkeit, auf Tastendruck/Loslassen zu reagieren, ist über externe Interrupts. Zum Entprellen wartet man danach eine kurze Zeit, bis man wieder auf nen Tastendruck reagiert.Code:#include <avr/interrupt.h> #include <avr/signal.h> // keine rekursiven Interrupts SIGNAL (SIG_INTERRUPT0) { // ... } // rekursive Interrupts INTERRUPT (SIG_INTERRUPT0) { // ... }
Oder man schaut in regelmässigen Abständen in einem Timer-Interrupt, ob sich an den Tastern was getan hat.
Der erste Weg hat den Nachteil, daß man so nur einen Taster checken kann und auch eine Zeitbasis braucht. Zudem landet man bei prellendem Taster oft im Interrupt. Tastendrucke sind keine zeitkritischen Ereignisse, da rechts es wenn man alle 10ms drauf schaut und sich externe Interrupts für wichtige Sachen aufspart.
OK...danke...hört sich logisch an...Zitat von SprinterSB
Jetzt muss ich schauen, wie ich das realisiere...![]()
![]()
Angenommen ich bekomme das mit dem Timer hin (was ich auch bezweifle), muss ich dann in meinem Tasterinterrupt den Timer Interrupt einfügen.
Des weiteren muss ich doch den Taster abfragen, oder?
Ich mein ok, abfragen mit...
a=PIND;
a=a&0b00001000;
kann man ja irgendwie...
aber wie dann der Verweis auf den TasterInterrupt...
Ich schreibe mal eben, wie ich es "versucht"habe...mit einer quick&dirty Zählschleife...
Code:{ int a, b, c; a=PIND; a=a&0b00001000; b=a/8; for (i=0; i<255; i++) //Warteschleife for(j=0; j<255;j++) k++; if (~b) { //Wenn b = 0 gehe in Interruptschleife...bitte nicht lachen... SIGNAL(SIG_INTERRUPT1) // Taster an PD3 löst Interrupt aus { //...Interruptbefehle... }
Ok, neuer versuch...
Kann man das so lassen?Code:SIGNAL(SIG_INTERRUPT1) // Taster an PD3 löst Interrupt aus { for (i=0; i<4000; i++) // Warteschleife... for(j=0; j<20;j++) k++; if(status_taster==1) { PORTB |= (1<<PB3); /*Setzt PB3 HIGH...LED aus \ */ PORTB &= ~(1<<PB4); //Setzt PB4 LOW...LED an } Zustand 1 PORTD |= (1<<PD5); //Setzt PD5 HIGH / status_taster=2; } else { for (i=0; i<4000; i++) // Warteschleife... for(j=0; j<20;j++) k++; PORTB &= ~(1<<PB3); /*Setzt PB3 LOW...LED an \ */ PORTB |= (1<<PB4); //Setzt PB4 HIGH...LED aus } Zustand 2 PORTD &= ~(1<<PD5); //Setzt PD5 LOW / status_taster=1; } GIFR=0; }
Es wird zwar ziemlich langsam umgeschaltet, aber zu mindestens tritt das "Überschwingen" nicht so oft auf...erst dann wenn ich den Taster mit dem Finger leicht und schnell antippe...
Weiterhin sind auch ein 100nF Kondensator und ein 11kOhm Wiederstand an den Taster angelötet...
Reicht das alles aus?
Haupsache es geht mal.
Den C und den R solltest du eigentlich nicht brauchen...
Zu deinem Code:
- Falls du GCC optimieren lässt, wird er die Warteschleife komplett in die Tonne kloppen, weil sie nix macht. Also zB ein k = PORTB oder ein _NOP(); (gibts mit #include <avr/ina90.h>)
- Die 2.Warteschleife ist zu viel, so wartest du 2x.
- Die Warteschleife besser ans Ende der Interrupt-Routine, vor das GIFR=...
- Falls während der Routine der Taster flackert, wird ja wieder das INTF1 Flag gesetzt, das du versuchst zurück zu setzen. Das geht, indem man eine 1 hin schreibt (keine 0):
GIFR = _BV(INTF1); // reset INT1 Flag- INT1 so initialisieren, daß er flankengetriggert ist, also nur bei Änderung anspricht; nicht levelgetriggert, sonst landest du auch dauernd im Interrupt solange der Taster noch gedrückt ist.
Falls dein Prog sonst nix maches soll, ist's ok. Aber wenn sonst noch Zeug zu erledigen ist, muss dir klar sein, daß zu ziemlich lange im Interrupt rumschnarchst...
Hallo und schönen guten Abend...Zitat von SprinterSB
Vielen Dank für diese Tipps...
Die Sache mit der prellenden Taste habe ich dann doch hardwaremäßig gelöst.
Ich habe den 100nF gegen einen 1uF Tantal Kondensator ausgetauscht. Der Widerstand ist bei 10kOhm geblieben. Erreiche hiermit eine Zeit von ca. 11ms wodurch das Problem mit dem prellenden Taster aus der Welt geschaffen ist.
Sicherlich ist es angenehmer die Sache softwaremäßig zu lösen, doch für einen Neuling wird es schwierig, auch noch den Timer zu implementieren.
Ach ja, INT1 ist auf fallende Flanke initialisiert.
So langsam habe ich den gesamten Code, dank eurer Hilfe zusammen...
Heute Abend bin ich noch an den Kommentaren usw. dran...
Im großen Ganzen verstehe ich auch das, was ich geschrieben habe. Doch es gibt bestimmte Stellen, wo ich nicht ganz schlüssig werde.
Würde mich freuen, wenn ich noch einige Verständnisfragen stellen dürfte (falls notwendig)
Hier schon die erste...
GIFR = _BV(INTF1);
was bedeutet hier das _BV?
Nochmals aber vielen Dank für die tolle Unterstützung... =D>
Hallo
_BV steht für Bit Value. Es wird das Bit INF1 gesetzt.
Ist das gleiche wie GIFR = ( 1<< INF1)
Schaui mal in der Doku de AVR LIBC unter Related Pages / FAQ
Gruß
Dieter
Guten Morgen...
_BV...BitValue...wusste ich doch, dass ich das mal irgendwo gelesen hatte...vielen Dank Dieter...
Ok, ein neuer Tag, und ich denke ich stehe heute total auf dem Schlauch.
Irgendwie schaffe ich es nicht mehr, meinem Compiler beizubringen, dass er PD7 bzw. PIND7 erkennt. Er meckert, dass es "undeclared" ist
statt dem PD7 habe ich auchCode:#include <avr/io.h> #include <inttypes.h> #include <avr/interrupt.h> #include <avr/signal.h> DDRD = 0b11110110; //Alles außer PD0 und PD3 als Ausgang PORTD = 0b01111111; /*Nun möchte ich PD7 abfragen, schauen ob er beim Einschalten HIGH oder LOW gesetzt wurde und dementsprechen was auf dem Bildschirm ausgeben (was ich ja mitlerweile mit eurer Hilfe kann :-)...*/ ... if (PD7) //akzeptiert er so nicht... PORTB = 0b11110111; else PORTB = 0b11101111; ...
PORTD&0b10000000
bzw.
PIND7
probiert...hilft alles nichts...
AT90S2313 hat keinen PortD.7
Oder verwendest du inzwischen nen anderen Controller?
In dem Falle must du avr-gcc mit der korrekten -mmcu=... aufrufen, sonst generierst du falschen Code.
Zitat von SprinterSB
![]()
![]()
Mensch bin ich doof...
Ok, dann probier ich das ganze mal mit PD5.
wenn ichCode:int main( void ) { DDRB = 0b11111111; PORTB = 0b11111111; DDRD = 0b00100000; PORTD = 0b11011111; for(;;) { if (PD5) PORTB = 0b11110111; else PORTB = 0b11101111; } }
PORTD = 0b11111111;
sollte er in die if-Schleife rein und LED an PB3 müsste brennen. Tut sie auch.
wenn ich dann
PORTD = 0b11011111;
schreibe, müsste er doch in die else-Schleife und LED ab PB4 müsste brennen...tut sie aber nicht...PB3 brennt immer.
mit dem Oszi an PD5 gemessen kommt das Signal so, wie es kommen soll. Also mal High, mal Low...
Was mache ich falsch?
[-o<
Lesezeichen