Hi ich arbeite momentan an folgendem Projekt: Beitrag "MSP430 F5529 Wobbel-Generator" dabei habe ich folgendes Problem: ich würde gerne einen Moduswechsel herbeiführen, indem ich beide Taster (p1.1 und P2.1) gleichzeitig drücke. Siehe dazu Funktion void Modiwechsel (void) und die ISR für Port P1 und Port P2 im angehängtem Code. Wie zu erwarten funktioniert das Umschalten nicht. Ich denke dies liegt daran: Niemals werden beide Taster gleichzeit gedrückt und gleichzeit losgelassen (losallsen ist in diesem Fall entscheidend, denn die ISR wird bei negativer Flanke aufgerufen (siehe Code). Ich habe die Funktion Modiwechsel in beide ISR der Ports eingetragen, dadurch wird sie auf jeden Fall aufgrufen. In der Funktion selbst wird dann geprüft, ob beide Taster gedrückt wurden. Die eigentliche ISR für die Ports wird nur durchlaufen, wenn sichergestellt ist, dass der andere Taster nicht gedrückt wurde. Hat jemand eine Idee, wie man die Idee mit Modiwechsel über beide Taster sinnvoll zum laufen bringen kann? Dadurch das die Interrupt-Flags bei beiden ISR am Ende gelöscht werden, dürfte es ja garnicht funktionieren. Muss diese aber löschen. Vielen Dank im Voraus! MfG P.S. Habe noch folgende Probleme: wenn ich Taster P2.1 länger als 2 s drücke, wird die Pulsrichtung zyklisch um plus/minus 5 prozent geändert, anstatt nur einmal geändert zu werden.Außerdem leuchte die LED_WG an P1.0 garnicht.
Antonowan225 schrieb: > ISR für Port P1 und Port P2 Taster prellen, deswegen fragt man die nicht per Interrupt ab. Mach das in der langsamen Hauptschleife alle paar 10ms. Die entprellten Ergebnisse kannst du dir in ein Struct legen und dann bequem abfragen ob beide gedrückt sind.
P.S. ich konnte jetzt erst den Quelltext laden (Handy). Du entprellst in der ISR mit Wartezeit/Delay. Das ist aus tausend Gründen ein richtig schlechtes Konzept. Schau hier ins Wiki wie man das besser lösen kann.
Andre schrieb: > Taster prellen, deswegen fragt man die nicht per Interrupt ab. Mach das > in der langsamen Hauptschleife alle paar 10ms. Die entprellten > Ergebnisse kannst du dir in ein Struct legen und dann bequem abfragen ob > beide gedrückt sind. danke für deine Antwort. kannst du das ein biscchen genauer ausführen? bin mir nicht ganz sicher was du meinst
Schau mal hier: https://www.mikrocontroller.net/articles/Entprellung Mit der Benutzung eines Timers habe ich durchweg gute Erfahrungen in dieser Sache gemacht.
Antonowan225 schrieb: > ich würde gerne einen Moduswechsel herbeiführen, indem ich beide Taster > (p1.1 und P2.1) gleichzeitig drücke. Echte Gleichzeitigkeit beim Drücken gibt es nicht. Die Schalter schalten immer zu verschiedenen Zeitpunkten. Du kannst allenfalls prüfen, ob es einen Zeitraum gibt, in dem beide Schalter gedrückt sind, als ob es einen Überlap der schließphasen gibt.
Antonowan225 schrieb: > danke für deine Antwort. kannst du das ein biscchen genauer ausführen? > bin mir nicht ganz sicher was du meinst Es gibt 1000 Wege zum entprellen von mechanischen Kontakten. Ich verwende folgende Lösung: * für jeden Taster gibt es eine Variable (Byte reicht meist) * alle 50-100ms wird über einen Timer-Interupt eine ISR angesprungen * in dieser ISR werden alle Taster je einmal abgefragt * ist der Taster nicht gedrückt, wird die Variable auf 0 gesetzt * ist der Taster gedrückt, wird die zugehörige Variable um 1 erhöht In der Hauptroutine kann an gewünschter Stelle der Wert der Taster-Variablen abgefragt werden. Ist er größer 2, wurde die Taste sicher gedrückt. Der Vorteil dieser Lösung ist, dass man auch sicher ermitteln kann wenn eine Taste länger gedrückt wird um z.B. in einen besonderen Modus zu gelangen.
Peter D. schrieb: > Gleichzeitig geht mit get_key_common() > > Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung" guter Hinweis, danke dafür. Wie würdest du das für meinen konkreten Anwendungsfall programmieren?
Jens P. schrieb: > Es gibt 1000 Wege zum entprellen von mechanischen Kontakten. Ich > verwende folgende Lösung: > > * für jeden Taster gibt es eine Variable (Byte reicht meist) > * alle 50-100ms wird über einen Timer-Interupt eine ISR angesprungen > * in dieser ISR werden alle Taster je einmal abgefragt > * ist der Taster nicht gedrückt, wird die Variable auf 0 gesetzt > * ist der Taster gedrückt, wird die zugehörige Variable um 1 erhöht > > In der Hauptroutine kann an gewünschter Stelle der Wert der > Taster-Variablen abgefragt werden. Ist er größer 2, wurde die Taste > sicher gedrückt. Der Vorteil dieser Lösung ist, dass man auch sicher > ermitteln kann wenn eine Taste länger gedrückt wird um z.B. in einen > besonderen Modus zu gelangen. leider gehen mir dazu die Timer aus...und ich weiß nicht ob man bei 100 ms 100 prozentig das drücken des tasters erwischt...hast du das Erfahrungen?
Antonowan225 schrieb: > leider gehen mir dazu die Timer aus...und ich weiß nicht ob man bei 100 > ms 100 prozentig das drücken des tasters erwischt... Die übliche Lösung ist ein Timerinterrupt. In der zugehörigen Interrupt-Routine werden alle zeitrelevanten Auswertungen erledigt - so wie Jens P. schon schrieb. Du brauchst also nur einen Timer. Wenn 100ms zuviel ist nimm halt weniger, z.B. 10ms. Das ist für Taster ein nicht schlechter Wert. D.h. du fragst den Taster alle 10ms ab. Für längere Zeiten zählst du die Anzahl Interrupts mit einer Variablen und entscheidest damit, wann die Bedingung erfüllt ist. Ist die Bedingung erfüllt, wird ein Flag gesetzt, das im Hauptprogramm abgefragt und quitiert wird.
Dietrich L. schrieb: > Für > längere Zeiten zählst du die Anzahl Interrupts mit einer Variablen und > entscheidest damit, wann die Bedingung erfüllt ist Genauer: ist der Zustand gedrückt, zählst du eine Variable hoch, solange der Wert kleiner ist als y. Ist der Wert grösser x, setzt du ein Flag für das Hauptprogramm, dass der Taster gedrückt ist, dabei muss natürlich y > x sein. Ist der Zustand nicht gedrückt, setzt du die Variable zurück auf 0. Das ergibt eine effektive Entprellung für geeignete Werte von x, allzu kritisch ist das nicht. Ich würde einen Timer mit 10 ms nehmen und für X 5..10. Je grösser desto langsamer reagiert die Taste. Für den Zustand beide gedrückt machst du genau das gleiche, da kann man sicherheitshalber auch x grösser wählen, z.B. 100 für eine Sekunde. Du hast dann im Hauptprogramm 3 Flags: Taste1, Taste2, beide zugleich. Warum y? Damit die Zählvariable nicht überläuft. Das kann man noch verbessern indem man auch das Öffnen der Tasten entprellt, aber normalerweise ist das nicht notwendig. Georg
Dietrich L. schrieb: > Die übliche Lösung ist ein Timerinterrupt. > In der zugehörigen Interrupt-Routine werden alle zeitrelevanten > Auswertungen erledigt - so wie Jens P. schon schrieb. Du brauchst also > nur einen Timer. > Wenn 100ms zuviel ist nimm halt weniger, z.B. 10ms. Das ist für Taster > ein nicht schlechter Wert. D.h. du fragst den Taster alle 10ms ab. Für > längere Zeiten zählst du die Anzahl Interrupts mit einer Variablen und > entscheidest damit, wann die Bedingung erfüllt ist. Ist die Bedingung > erfüllt, wird ein Flag gesetzt, das im Hauptprogramm abgefragt und > quitiert wird. danke für die erklärung, aber: hast du dir mein Programm angeguckt? habe beim mSP430 f5529 3x Timer A und einmal Timer B. und alle Timer sind bereits in Gebrauch
Mit anderen Worten: ich möchte eine Lösung mit einem Timer umgehen, also die ISR der Ports nutzen
Antonowan225 schrieb: > habe > beim mSP430 f5529 3x Timer A und einmal Timer B. und alle Timer sind > bereits in Gebrauch Einfach Quatsch. Ich habe z.B. einen Timer 10ms und der erledigt ALLES - Tastatur mit Entprellung, Ausgabe ans Display, 4 serielle Schnittstellen... Antonowan225 schrieb: > ich möchte eine Lösung mit einem Timer umgehen, also > die ISR der Ports nutzen Typischer Fall von beratungsresident. Ende der Mitarbeit. Ich mache mir die Mühe einer exakten Beschreibung und alles was kommt ist "ich will das anders als alle, Stampf, Kreisch". Dann mach halt. Georg
georg schrieb: > Einfach Quatsch. Ich habe z.B. einen Timer 10ms und der erledigt ALLES - > Tastatur mit Entprellung, Ausgabe ans Display, 4 serielle > Schnittstellen... Lieber Georg, ich weiß deine Einsatz zu schätzen, werde deinen Lösungsansatz probieren. Jedoch: wollte meinen Ansatz nicght einfach über Bord werfen, deswegen meine Hartnäckigkeit. Also nimm es nicht persönlich. Melde mich dann später, wenn es läuft. grüße
ich weiß trotzdem nicht, welchen Timer ich dazu nutzen könnte! Da zyklisch abgefragt werden muss, sollter der Timer in einem Outmod sein. Die beiden Timer, die das sind, eignen sich nicht zu dieser Aufgabenstellung, da deren Frequenz und Pulsbreite verändert werden. HAbt ihr eine Idee?
Antonowan225 schrieb: > HAbt ihr eine Idee? Machs richtig. Du hast zwei Modi die nicht gleichzeitig stattfinden: Wobbeln und variable PWM. Dafür genügt ein Timer. Den zweiten nimmst Du für die restlichen Aufgaben: z.B. Tastenabfrage und Entprellen und Blinken (?)und Display (?) und ...
Route_66 H. schrieb: > Du hast zwei Modi die nicht gleichzeitig stattfinden: Wobbeln und > variable PWM. Dafür genügt ein Timer. könnte ich das über eine If else schleife im Timer in Abhängigkeit vom Modus realisieren? oder wird das nicht gerne gesehen?
Antonowan225 schrieb: > Route_66 H. schrieb: >> Du hast zwei Modi die nicht gleichzeitig stattfinden: Wobbeln und >> variable PWM. Dafür genügt ein Timer. > > könnte ich das über eine If else schleife im Timer in Abhängigkeit vom > Modus realisieren? oder wird das nicht gerne gesehen? also bei Systemstart gebe ich direkt einen konkreten Modus vor. Mit der if else Anweisung würde der Timer dann unterschiedliche Frequenzen fahren. Soe meine Denke...
[c] void TimerB0 (void) { //Timer für Pulswobbel if (Modus == 1) { TB0CTL = TBCLR; TB0CCR0 = Frequenz; TB0CCTL2 = OUTMOD_7; TB0CCR2 = (int)((float)(PWM_Aktuell) / 100 * (float)(Frequenz)); TB0CTL = TBSSEL_2 + MC_1 + ID_0; // SMCLK, 1:1, UP-Mode } // Timer für Frequenzwobbel else if ( Modus == 2) { TB1CTL = TBCLR; // Timer-Counter RESET auf Null TB1CCR0 = (int) ((float) (FRQ_Aktuell) / 100 *(float)(Periodendauer)); TB1CCTL0 = OUTMOD_7; // Interrupt bei TA1CCR0 TB1CCR1 = Periodendauer; TB1CTL = TBSSEL_2; // Taktquelle SMCLK; 1,048 MHz kHz TB1CTL = ID_0; // Teiler 1 TB1CTL = MC_1; // UP-Modus gewählt } } [c]
dann hätte ich nämlich zwei FLiegen mit einer Klappe geschlagen. Siehe: Beitrag "Brücke zwischen Pin und LED herstellen - für zwei unterschiedliche Timer"
Verlinke dochmal Deinen konkreten Code, ob der wirklich alle Timerinterrupts auslastet. Falls keine Timer frei sind, hat man oft noch weitere periodische Interrupts, die als Timer taugen, z.B. eine nicht benötigte UART, ADC-Interrupt, Watchdoginterrupt. Auch habe Timer oftmals mehrere Interruptvektoren, die man wahlweise oder auch gleichzeitig benutzen kann.
Antonowan225 schrieb: > TB0CCR2 = (int)((float)(PWM_Aktuell) / 100 * (float)(Frequenz)); Float Division innerhalb eines Interrupts dürfte suboptimal sein. Kann man die nicht heraus ziehen? Antonowan225 schrieb: > else if ( Modus == 2) Wenn es nur 2 sind, ist das if überflüssig.
Peter D. schrieb: > Wenn es nur 2 sind, ist das if überflüssig. sinjd Drei, Modus = 0 gibt es auch... Peter D. schrieb: > Verlinke dochmal Deinen konkreten Code, ob der wirklich alle > Timerinterrupts auslastet. sind sie nicht, da Die Timer aber sehr spezielle funktionen haben, macht es keinen Sinn, andere ISR reinzufummeln...zumindest denke ich das. Peter D. schrieb: > Auch habe Timer oftmals mehrere Interruptvektoren, die man wahlweise > oder auch gleichzeitig benutzen kann. genau den Punkt habe ich weiterverfolgt. Die Möglichkeit besteht antürlich. Doch inhaltlich bin ich nicht auf eine Sinnvolle Sache gestoßen. Die Frage: mach if else im Timer Sinn? dann könnte man ja die gleichen Vektoren wiederverwerten.
Antonowan225 schrieb: >> Wenn es nur 2 sind, ist das if überflüssig. > > sinjd Drei, Modus = 0 gibt es auch... deswegen acuh die Verwendung von else if
Antonowan225 schrieb: > Die Frage: mach if else im Timer Sinn? Natürlich, das sind nur 2-3 Befehle, also nichts. Float Division ist dagegen richtig teuer (viele 100 CPU-Zyklen). Ändert sich die Berechnung wirklich in jedem Interrupt? P.S.: Sehe grad, das sind ja nicht die Interrupts mit den float, also alles gut.
:
Bearbeitet durch User
Georg schrieb: > Genauer: ist der Zustand gedrückt, zählst du eine Variable hoch, solange > der Wert kleiner ist als y. Ist der Wert grösser x, setzt du ein Flag > für das Hauptprogramm, dass der Taster gedrückt ist, dabei muss > natürlich y > x sein. Ist der Zustand nicht gedrückt, setzt du die > Variable zurück auf 0. Das ergibt eine effektive Entprellung für > geeignete Werte von x, allzu kritisch ist das nicht. Ich würde einen > Timer mit 10 ms nehmen und für X 5..10. Je grösser desto langsamer > reagiert die Taste. > > Für den Zustand beide gedrückt machst du genau das gleiche, da kann man > sicherheitshalber auch x grösser wählen, z.B. 100 für eine Sekunde. Du > hast dann im Hauptprogramm 3 Flags: Taste1, Taste2, beide zugleich. > > Warum y? Damit die Zählvariable nicht überläuft. > > Das kann man noch verbessern indem man auch das Öffnen der Tasten > entprellt, aber normalerweise ist das nicht notwendig. > > Georg Dietrich L. schrieb: > Die übliche Lösung ist ein Timerinterrupt. > In der zugehörigen Interrupt-Routine werden alle zeitrelevanten > Auswertungen erledigt - so wie Jens P. schon schrieb. Du brauchst also > nur einen Timer. > Wenn 100ms zuviel ist nimm halt weniger, z.B. 10ms. Das ist für Taster > ein nicht schlechter Wert. D.h. du fragst den Taster alle 10ms ab. Für > längere Zeiten zählst du die Anzahl Interrupts mit einer Variablen und > entscheidest damit, wann die Bedingung erfüllt ist. Ist die Bedingung > erfüllt, wird ein Flag gesetzt, das im Hauptprogramm abgefragt und > quitiert wird. was ich mich Frage: wenn die ISR von einem Timer aufgerufen wird, dann müssen beide Taster schon vorher gedrückt worden. Sonst sind die Interrupt_Flag der Taster nicht gesetzt. Probleme: sobald ein Taster gedrückt wird, wird die jeweilge ISR der Ports aufgerufen (siehe Code). wie kann ich das Verhindern? ansonsten hätte ich den Vorschlag wie folgt umgesetzt: #pragma vector=TIMER1_A0_VECTOR __interrupt void TA1_0_ISR() { if (P1IFG & T_OnOff) { while(T1 < 50) T1++; } if (P2IFG & T_Step) { while(T1 < 50) T2++; } if ( T1 > 1 && T2 > 1) { Moduswechsel (); } else { T1 = 0; T2 = 0; } } void Modiwechsel (void) { // Von Pulswobbel auf Frequenzwobbel if ( Modus == 1) { Modus = 2; FRQ_Dir = 1; // zuerst wird Frequenz vergrößert TX_String("\n Wechsel zu Frequenzwobbel ist erfolgt\n\n"); Ausgabe_Fvorgegeben(Pulsbreite_Ak); } // Von Frequenzwobbel auf Pulswobbel else if (Modus == 2) { Modus = 1; PWM_Dir = 1; // Pulsweite wird vergrößert TX_String("\nWechsel zu Pulswobbel ist erfolgt\n\n"); Ausgabe_Pvorgegeben(Frequenz_Ak); } // Flankenereignisse löschen P1IFG &=~ T_OnOff; P2IFG &=~ T_Step; }
Antonowan225 schrieb: > sobald ein Taster > gedrückt wird, wird die jeweilge ISR der Ports aufgerufen (siehe Code). > wie kann ich das Verhindern? ich nehme an, dass ich bei dieser Variante die ISR der Taster nicht verwenden soll. Bedeutet aber, dass ich mein gesamtes Programm umkrempeln muss. Könntene weinen haha
So habe folgende Änderungen vorgenommen ( siehe Code Anhang). Der Microcontroller reagiert jz garnicht mehr auf Drücken der beiden Taster. #pragma vector=TIMER1_A0_VECTOR __interrupt void TA1_0_ISR() { if (P1IFG & T_OnOff) { while(T1 < 50) T1++; } if (P2IFG & T_Step) { while(T2 < 50) T2++; } if ( T1 > 0 && T2 == 0) { void TOnOff (); T1 = 0; } if ( T2 > 0 && T1 == 0) { void TStep (); T2 = 0; } if ( T1 > 1 && T2 > 1) { void Moduswechsel(); } else { T1 = 0; T2 = 0; } }
Antonowan225 schrieb: > Der > Microcontroller reagiert jz garnicht mehr auf Drücken der beiden Taster. > while(T1 < 50) T1++; Oh Wunder ... Wie oft willst du diesen Schrott noch posten? Nimm die hier schon mehrmals gesagten Hinweise an, schreib das ganz um, und gut. leo
leo schrieb: > Oh Wunder ... > Wie oft willst du diesen Schrott noch posten? Nimm die hier schon > mehrmals gesagten Hinweise an, schreib das ganz um, und gut. > > leo mal wieder einer dieser konstruktiven beiträge. Habe das Programm entsprechend umgeschrieben. Es funktioniert nicht. Ich bitte um Hilfe.
Antonowan225 schrieb: > ich würde gerne einen Moduswechsel herbeiführen, indem ich beide Taster > (p1.1 und P2.1) gleichzeitig drücke. Siehe dazu Funktion void > Modiwechsel (void) und die ISR für Port P1 und Port P2 im angehängtem > Code. Wie zu erwarten funktioniert das Umschalten nicht. Warum muß das als Interruptroutine gemacht werden? Das kann man durch ganz einfaches Polling in der Main lösen. Antonowan225 schrieb: > gleichzeit > losgelassen (losallsen ist in diesem Fall entscheidend,... In diesem Fall der falsche Ansatz. Man fragt in der Main ab ob Taster 1 oder 2 gedrückt wurde. Innerhalb dieser Abfrage mach man eine kleine Verzögerung (wegen Prellen der Taster) und fragt nach dieser ab ob immer noch beide Taster gedrückt sind. In Deinem Fall macht man die Verzögerung nicht zu klein. Sind beide Taster auch nach der Verzögerung noch gedrückt führt man die gewünschte Aktion aus. Dannach wartet man noch bis mindestens ein Taster los gelassen wird, so vermeidet man das man wieder in die Abfrage hinein läuft. Antonowan225 schrieb: > danke für die erklärung, aber: hast du dir mein Programm angeguckt? habe > beim mSP430 f5529 3x Timer A und einmal Timer B. und alle Timer sind > bereits in Gebrauch Es geht auch ohne Timer. Es gibt die Funktion __delaycycles() damit kann man (notfalls in einer Schleife) eine ausreichend lange Zeit pausieren. Für den den Fall der Abfrage ob 2 Taster gedrückt sind, würde ich die Zeit nich t kleiner als 500ms - eher größer - machen, so kann man sicher stellen, dass man genügend Zeit hat beide Taster zu drücken und diese auch nicht mehr prellen. Und noch etwas, setze Dich endlich mal auf Deinen Hintern und lerne die Basics, dann lernt man auch wie man solche Sachen macht/löst. Meist führen mehrere Wege zum Ziel, aber man muß es sich eben erarbeiten und nicht einfach vor kauen lassen. Bei Letzterem lernt man nämlich nichts, noch dazu wenn man wie Du beratungsresistent ist und keinen der hier gemachten zahlreichen Vorschläge annnimmt und statt dessn wie ein bockiges Kind auf stampft.
danke für deinen Beitrag Zeno. Du hast einen neunen Ansatz vorgeschlagen. Den würde ich durchführen, wenn ich die anderen entgültig verworfen habe. Zeno schrieb: > keinen der hier > gemachten zahlreichen Vorschläge annnimmt habe ich doch, siehe letzte Beiträge. Hast du dazu noch eine Idee
Zeno schrieb: > Warum muß das als Interruptroutine gemacht werden? Das kann man durch > ganz einfaches Polling in der Main lösen. Kann man natürlich auch. Wichtig ist nur, daß man dazu in der Mainloop ein relativ konstantes Zeitintervall zur Verfügung hat, z.B. 10ms.
aber wenn doch alles basics ist und alles so einfach: warum sagt mir niemand "mal eben" wo der konkrete Fehler in meinem Programm liegt. Es ist ja nicht so, als würde ich es mir einfach machen. Überlege mir die Dinge meist vorher, bringe selbst Lösungsvorschläge mit ein etc. Sonst dürfte man hier ja garkeine Fragen mehr stellen, weil für den einen ist alles basics ... für den anderen eben nicht.
#define TASTERPORT PINC #define TASTERBIT PINC1 char taster(void) { static unsigned char zustand; char rw = 0; if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT))) //Taster wird gedrueckt (steigende Flanke) { zustand = 1; rw = 1; } else if (zustand == 1 && !(TASTERPORT & (1<<TASTERBIT))) //Taster wird gehalten { zustand = 2; rw = 0; } else if (zustand == 2 && (TASTERPORT & (1<<TASTERBIT))) //Taster wird losgelassen (fallende Flanke) { zustand = 3; rw = 0; } else if (zustand == 3 && (TASTERPORT & (1<<TASTERBIT))) //Taster losgelassen { zustand = 0; rw = 0; } return rw; } so ist es im Wiki erklärt. also hatte ich die Abfrage der Pins falsch durchgeführt. mir war die Erklärung ein Stück weit zu abstrakt: Antonowan225 schrieb: > Ist der Wert grösser x, setzt du ein Flag >> für das Hauptprogramm, dass der Taster gedrückt ist, ist mit Flag in diesem Zusammenhang der Aufruf einer anderen Funktion gemeint? erfolgt die Abfrage der Taster in der ISR?
Peter D. schrieb: > Kann man natürlich auch. Wichtig ist nur, daß man dazu in der Mainloop > ein relativ konstantes Zeitintervall zur Verfügung hat, z.B. 10ms. Wieso muß das Zeitintervall konstant sein? das verstehe ich jetzt nicht. Es reicht doch wenn ich in der Main an einer Stelle die mit Sicherheit in jedem Durchlauf durchlaufen wird die 2 Ports mit den Tasten abfrage. Wenn ich dann an einem Port feststelle warte ich eine feste Zeit und prüfe beide Ports ab ob die Tasten noch gedrückt sind. Wenn dem so ist führe ich die passende Funktion aus, ansonsten geht's halt normal weiter. Die Wartezeit würde ich bei Abfrage von 2 Tasten so auf 1s oder sogar größer festlegen, damit ist eigentlich sichergestellt das ich auch beide Tasten drücken kann. Bei einer Userinteraktion kommt's ja nun wirklich nicht auf eine ms an und wenn keine Taste gedrückt wird fällt ja die Wartezeit weg. Ich habe das gerade mal auf meinem MSP probiert und das funktioniert bestens. Sicher kann man das auch eleganter lösen, aber so funktioniert es und es ist einfach zu überblicken was an dieser Stelle im Einzelnen passiert.
mir ist grade aufgefallen, das man in der ISR garkeine subroutine aufrufen kann =)
Antonowan225 schrieb: > aber wenn doch alles basics ist und alles so einfach: warum sagt mir > niemand "mal eben" wo der konkrete Fehler in meinem Programm liegt. Fremden Quelltext lesen und verstehen ist immer schwierig und da Du offensichtlich aus vielen Quellen was zusammen kopierst wird es noch schwieriger, denn jeder Programmierer hat einen anderen Programmierstil und da muß man sich erst mal rein lesen. Achja und die Basic's mußt Du schon selbst lernen - das wird hier keiner für Dich übernehmen. Das was Du hier Beitrag "Re: Moduswechsel durch gleichzeitiges Drücken beider Taster" ist eigentlich fast unlesbar. Hier mal ein Beispiel wo die Taster an Port 1.0 und 1.1 hängen
1 | if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) |
2 | {
|
3 | _delay_cyles(x); |
4 | if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) |
5 | {
|
6 | //tue etwas
|
7 | }
|
8 | }
|
Das ist eigentlich alles.Ob Du da High oder Low abfragst ist erst mal egal. Für x schreibst Du die Anzahl der Wartezyklen.
Zeno schrieb: > offensichtlich aus vielen Quellen was zusammen kopierst habe was kopiert ja! aber was die Funktionalität des WG betrifft, habe ich den mist selbst geschrieben...Ist das so schwer zu glauben?
Zeno schrieb: > Hier mal ein Beispiel wo die Taster an Port 1.0 und 1.1 hängen > if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) > { > _delay_cyles(x); > if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) > { > //tue etwas > } > } > > Das ist eigentlich alles.Ob Du da High oder Low abfragst ist erst mal > egal. Für x schreibst Du die Anzahl der Wartezyklen. nett von dir. Gucke mir das morgen an. Ich habe nämlich die Idee mit den Tastern gleichzeit rücken nach hinten geschoben, möchte erstmal den WG an sich zum laufen bringen
Zeno schrieb: > Wieso muß das Zeitintervall konstant sein? das verstehe ich jetzt nicht. Was ist daran nicht zu verstehen? Das Entprellen funktioniert nur, wenn die Abtastungen nicht zu schnell erfolgen. Bei zu langsam können wiederum Drücke verloren gehen. Und ebenso sollte auch das Zeitintervall für die Erkennung von Gleichzeitigkeit einigermaßen stimmen. Super konstant ist natürlich nicht nötig. Wenn die 10ms auch mal 5ms oder 20ms dauern, ist das kein Problem.
Antonowan225 schrieb: > Ist das so schwer zu glauben? Ja! Peter D. schrieb: > Das Entprellen funktioniert nur, wenn die Abtastungen nicht zu schnell > erfolgen. Das ist schon klar Peter D. schrieb: > Bei zu langsam können wiederum Drücke verloren gehen. Wenn Du meinst. Ich sehe das etwas anders, denn bei einer Userinteraktion bestimme sowieso ich wann es weiter geht. In dem von mir geposteten Beispiel frage ich z.B. in der 2. if auch ab, ob die Tasten los gelassen wurden. Erst wenn die Tasten los gelassen wurden geht es halt weiter. Peter D. schrieb: > Und > ebenso sollte auch das Zeitintervall für die Erkennung von > Gleichzeitigkeit einigermaßen stimmen. Auch hier muß gar nichts stimmen. Es gibt eigentlich nur eine Mindestzeit und zwar die, die ich brauche um meine Griffel zu den Tasten zu bewegen und selbige zu drücken. Wenn ich es in der vorgegebenen Zeit nicht schaffe, dann läuft halt die Schleife weiter und wenn sie dann wieder an der Tastenabfrage ankommt und die Griffel immer noch die Tasten quälen beginnt der Abfragezyklus von Neuem. Im Gegenteil, wenn ich bei der Abfrage der Gleichzeitgkeit die Zeit groß wähle, dann kann ich nach Ablauf der Zeit auch noch eine Abfrage machen Taste 1 oder 2 gedrückt und somit mit 2 Tasten recht einfach 3 Aktionen realisieren. Allerdings würde ich das nur machen, wenn: a) die Ports ausgehen b) ich keinen 3. Taster unterbringen kann c) ich im Nachgang feststelle, das ich eigentlich 3 Taster brauche und das nicht mehr ändern kann. Bei dem Projekt des TO würde ich lieber einen zusätzlichen Taster vorsehen, denn nichts ist nerviger als Fingerakrobatik.
Zeno schrieb: > Ich sehe das etwas anders, denn bei einer > Userinteraktion bestimme sowieso ich wann es weiter geht. Ist bei mir in der Regel nicht so. Alle anderen Tasks der Mainloop sollen auch während einer Eingabe natürlich weiter laufen. Z.B. wenn ich bei einer Schaltuhr eine Schaltzeit ändere, soll die aktuelle Uhrzeitanzeige weiter laufen. Oder eine Temperaturregelung muß weiter arbeiten, damit nichts überhitzt. Daß eine Eingabe alles andere anhält, sieht nicht nur sehr unprofessionell aus, sondern geht nur bei sehr einfachen Anwendungen.
@Antonowan225, falls Du Ports übrig hast, könntest Du das Problem über ein single Gatter ODER Logik lösen, deren Ausgang auf einen dritten MSP430 Port geführt wird, sofern Deine Taster gegen Masse schalten. Da werden jetzt die Softwerker gleich schimpfen, aber wenn es nur um ein einzelnes Tasten-Pärchen geht, wäre das eine Möglichkeit. Du musst halt Zusatz-HW einsetzen. Den Vorteil der SW-Komplexität Reduzierung erkaufst Du Dir mit mehr Aufwand im Layout und mit zusätzlichen Teile-Kosten. Markus
Peter D. schrieb: > Gleichzeitig geht mit get_key_common() > > Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung" ehrlich gesagt überfordert mich da =) Zeno schrieb: > Hier mal ein Beispiel wo die Taster an Port 1.0 und 1.1 hängen > if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) > { > _delay_cyles(x); > if ((P1IN & BIT0)==BIT0 && (P1IN & BIT1)==BIT1) > { > //tue etwas > } > } if ((P1IN & T_OnOff)==0x02 && (P2IN & T_Step)== 0x02) { _delay_cyles(); if ((P1IN & T_OnOff)==0x02 && (P1IN & T_Step)== 0x02) { } } so würde das ja in meinem konkreten Anwednungsfall aussehen. Die Frage: woher weiß welchen Wert ich für x bei delay eingeben muss? Hängt das von der CPU ab?
Antonowan225 schrieb: > woher weiß welchen Wert ich für x bei delay eingeben muss? Hängt das von > der CPU ab? Das hängt vor allem von der Taktfrequenz ab.
Peter D. schrieb: > .B. wenn ich bei einer Schaltuhr eine Schaltzeit ändere, soll die > aktuelle Uhrzeitanzeige weiter laufen. Oder eine Temperaturregelung muß > weiter arbeiten, damit nichts überhitzt. > > Daß eine Eingabe alles andere anhält, sieht nicht nur sehr > unprofessionell aus, sondern geht nur bei sehr einfachen Anwendungen. Kommt eben darauf an was man macht. Bei meiner Wetterstation z.B. ist es egal ob die Sensordaten mal nicht ausgelesen werden. Bei der Anwendung des TO dürfte es auch wurscht sein.
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.