Forum: Mikrocontroller und Digitale Elektronik Moduswechsel durch gleichzeitiges Drücken beider Taster


von Antonowan225 (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Andre (Gast)


Lesenswert?

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.

von Andre (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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

von Torsten (Gast)


Lesenswert?

Schau mal hier: https://www.mikrocontroller.net/articles/Entprellung
Mit der Benutzung eines Timers habe ich durchweg gute Erfahrungen in 
dieser Sache gemacht.

von Wolfgang (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

Gleichzeitig geht mit get_key_common()

Beitrag "Universelle Tastenabfrage mit 2 Tastenerkennung"

von Jens P. (picler)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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?

von Antonowan225 (Gast)


Lesenswert?

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?

von Dietrich L. (dietrichl)


Lesenswert?

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.

von Georg (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

Mit anderen Worten: ich möchte eine Lösung mit einem Timer umgehen, also 
die ISR der Ports nutzen

von georg (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

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?

von Route_66 H. (route_66)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

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?

von Antonowan225 (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

[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]

von Antonowan225 (Gast)


Lesenswert?

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"

von Peter D. (peda)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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
von Antonowan225 (Gast)


Lesenswert?

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;
 }

von Antonowan225 (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Angehängte Dateien:

Lesenswert?

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;
  }
}

von leo (Gast)


Lesenswert?

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

von Antonowan225 (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

#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?

von Zeno (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

mir ist grade aufgefallen, das man in der ISR garkeine subroutine 
aufrufen kann =)

von Zeno (Gast)


Lesenswert?

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.

von Antonowan225 (Gast)


Lesenswert?

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?

von Antonowan225 (Gast)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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.

von Markus W. (dl8mby)


Lesenswert?

@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

von Antonowan225 (Gast)


Lesenswert?

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?

von Zeno (Gast)


Lesenswert?

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.

von Zeno (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.