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
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
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...
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:> 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.
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.>> GeorgDietrich 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
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.
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.