Hi Allerseits, ich habe mich mal etwas durchgeklickt und nichts passendes zu meiner Problemstellung gefunden, daher dieser Thread. Es ist eine "banale" Aufgabe, allerdings bin ich ein absoluter Anfänger, muss jedoch morgen im laufe des Tages folgende Projektarbeit abgeben. Ich habe mich nun 'ne woche damit beschäftigt und kam einfach nicht aufs Ergbnis, ja ich weiß kaum zu glauben, aber wie gesagt Anfänger =/ Der Mikrokontroller (STM32F...) (MK) hat eine Taste und diese soll eine Fernbedienung simulieren. Mit dieser Taste soll Start/ Stopp und Pause umgesetzt werden. Um die Funktionalität zu überprüfen will ich zunächst die Funktionen mit LEDs zu Testzwecken verbinden. Ein Funktion habe ich hinbekommen, aber die zweite kriege ich nicht korrekt drauf. Ich bin mir sicher ich habe mindestens 2 Denkfehler, komme aber nicht auf die Lösung. 1.) Die Zeitmessung hat so keinen Sinn meiner Ansicht nach (wurde aber von meinem Betruer so empfohlen) Weil sobald i = 1 dann wird ja die blaue LED direkt auf leuchten gesetzt 2.) die Zeitmessung ist ja nocht nicht einmal fertig und es wird schon in die set_blaueTaste funktion gegangen, deshalb wird immer die blaue LED zum leuchten gebracht. 3.) Es fehlt mindestens ein Befehl, mit diesem ich auch wirklich das Drücken des Knofes ermitteln kann Folgendes habe ich mir gedacht: Fallunterscheidung durch Zeitmessung. Wenn Knopf maximal 1sekunde lang gedrückt dann Start/ Stopp wenn Knopf mehr als eine Sekunde gedrückt dann Pause bzw. Fortsetzen Dazu habe ich folgendes gecoded: while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) { //Zustand: schalter aus, knopf nicht gedrückt // wartet bis Knopf gedürckt } //Knopf wird gedrückt i wird 1 i++; //hier aktuelle uhrzeit Systickcount ausgeben tic = HAL_GetTick(); if (i >= 2) { i = 0; } //Hier ist die void Funktion in einer separaten Datei (siehe unten) set_blaueTaste(i); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) { // Hier ist der Knopf im gedrückten Zustand // bis i seinen wert ändert } // hier die zweite uhrzeit notieren toc = HAL_GetTick(); // Hier DifferenzMessung der Zeit: Wie viel Zeit ist vergangen bis der Knopf gedrückt und los gelassen wurde uint32_t a = toc - tic; Hier gehts weiter mit der obigen Funktion set_blaueTaste void set_blaueTaste(uint8_t push) { // Wenn i == 1 - > Taste gedrückt if (push == 1){ // Fallunterscheidung wenn Taste länger als 20ms gedrückt, dann LED rot if((toc-tic) > 20){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET); //Wenn Taste kürzer als 20 ms gedrückt dann LED blau } else if((toc-tic) < 20){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET); } } // Wenn Taste erneut gedrückt dann schalte LED aus else if(push == 0){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } // Zur Sicherheit default, falls was passiert einfach alles ausschalten else{ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } Wäre echt super wenn mir jemand Helfen würde, bin mega verzweifelt und komme einfach nicht auf die Lösung. Schon 'mal im Voraus vielen Dank für eure Hilfe. LG Schustermann
Hallo Andy, also Zeit messen ist schon mal richtig, du musst aber die Zeit zwischen gedrückt und losgelassen messen. Also beim Drücken Tick's speichern und beim Loslassen die Differenz berechnen. Dann entscheiden: <100ms hat wohl nur geprellt -> tu nix <1s -> kurz gedrückt sonst >1s -> lang gedrückt Wenn du die Tastenabfrage jetzt noch nicht blockierend hin bekommst dann kannst du auch während die Taste noch gedrückt ist erkennen das sie Lang gedrückt wird und schon reagieren bevor der Nutzer die Taste wieder los lässt. Sascha
Erst einmal danke für eure Antworten. Danke Sascha! Ja so stell ich mir das vor aber ich stelle mich - auf gut deutsch gesagt - einfach zu blöd an. Mein Verständnis ist, dass die Zeitmessung direkt mit i=1 anfängt und zwar sobald auf den Knopf gedrückt wird, wird i=0 zu i=1 und die Abfrage ist doch mit while(readPin(...)==1){} dann endet die messsequenz mit toc und trotzdem passt es nicht Hab ich das falsch interpreitert, Knopfdruckzeit ist mit "readPIN(...)"? Offensichtlich checke ich nicht wie ich drücken und loslassen coden kann, wenn die while(readPin(...)==1) nicht korrekt sein soll irgedwie passt es auch nicht, denn so lange es (while) =1 ist kann doch toc auch nicht gemssen werden? Daher bin ich mir sicher, dass ich ein Denkfehler habe -.- das ist doch zum Mäusemelken Ich habe mir mal einen anderen Plan ausgedacht der aber auch nicht funktioniert hat, stattdessen leuchtet die rote LED die Funktion set_blaueTaste() habe ich aufgeteilt, damit in der if-abfrage die richtige Handlung abgearbeitet werden kann while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) { //Zustand: schalter aus, knopf nicht gedrückt // warten auf Knopfdruck } i++; //Zurücksetzen wenn zweimal gedrückt if (i >= 2) { i = 0; } //hier aktuelle StartUhrzeit Systickcount ausgeben und in tic speichern tic = HAL_GetTick(); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) { //hier Knopf gedrückt //bspw. Start und Pause } // hier die zweite uhrzeit (EndUhrzeit) ausgeben und in toc speichern toc = HAL_GetTick(); ZeitDifferenz der End-Startzeit in Variabl a gespeichert uint32_t a = toc - tic; // Wenn Zeitdifferenz kleiner als 1200ms if(a < 1200) { set_blaueTaste(i); } // Wenn Zeitdifferenz größergleich 1200ms else if (a >= 1200) { set_blaueTaste1(i); } else { // Für den Fall der Fälle alle LEDs aus HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET); } void set_blaueTaste(uint8_t push) { // Wenn gedrückt i==1 if (push == 1){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET); } //Wenn taste wieder gedrückt dann alle LEDs aus else if(push == 0) { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } // Default Notfalls alle LEDs aus else{ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } } -------- void set_blaueTaste1(uint8_t push) { // Wenn gedrückt i==1 if (push == 1){ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET); } //Wenn taste wieder gedrückt dann alle LEDs aus else if(push == 0) { HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } // Default Notfalls alle LEDs aus else{ HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); } }
:
Bearbeitet durch User
Blockierende Programmierung ist generell schwer zu durchschauen und fehlerträchtig. Es hat schon seinen Sinn, warum ich alles im Timerinterrupt mache und das Main nur die Ereignisbits abzufragen braucht.
naja, tatsächlich ist es im interrupt-request-handler drin, nicht in der main. Oder habe ich dich missverstanden?
Andy H. schrieb: > naja, tatsächlich ist es im interrupt-request-handler drin, nicht in der > main. Wie soll jemand in den Schnipselchen durchsehen? Hängt ein compilierbares C-File an.
Ach, so meinst du das. Hab dann mal alle relevanten Dateien angefügt. Wesentlicher code ist in den ersten 4 Dateien drin. Im Wesentlich ist es schon der gesamte code, mehr ist wirklich nicht drin. Hätte lieber den Ordner hochgeladen, aber ich konnte nur einzelne dateien hochladen. ich denke, dass das hauptproblem an dieser Stelle liegt //hier aktuelle StartUhrzeit Systickcount ausgeben und in tic speichern tic = HAL_GetTick(); while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) { //hier Knopf gedrückt //bspw. Start und Pause } // hier die zweite uhrzeit (EndUhrzeit) ausgeben und in toc speichern toc = HAL_GetTick();
:
Bearbeitet durch User
Andy H. schrieb: > Hätte lieber den Ordner hochgeladen, aber ich konnte nur einzelne > dateien hochladen. Man darf auch ein Zip hochladen.
Eine Bitte habe ich: Wenn du Code in deinen Posts hast, setz ihn doch in die passenden Tags wie über dem Postingformular beschrieben. Macht das Ganze viel lesbarer!
1 | //hier aktuelle StartUhrzeit Systickcount ausgeben und in tic speichern
|
2 | |
3 | tic = HAL_GetTick(); |
4 | |
5 | while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) |
6 | |
7 | {
|
8 | //hier Knopf gedrückt
|
9 | //bspw. Start und Pause
|
10 | |
11 | } // hier die zweite uhrzeit (EndUhrzeit) ausgeben und in toc speichern |
12 | |
13 | toc = HAL_GetTick(); |
Beitrag #6596962 wurde von einem Moderator gelöscht.
@Peter danke für den Hinweis, den nehme ich doch gerne an. Anbei die Zip Datei =)
Puh, das ist ja ein riesen Brocken. Und haufenweise Code, der mit dem Problem nicht das geringste tun hat. Um da durchzusteigen, müßte man erstmal den ganzen überflüssigen Ballast rauslöschen. Ansonsten ist das die Stecknadel im Heuhaufen suchen. Andy H. schrieb: > //hier aktuelle StartUhrzeit Systickcount ausgeben und in tic > speichern > > tic = HAL_GetTick(); Wozu soll das gut sein? Man weiß doch selber ganz genau, wie man den Timerinterrupt konfiguruiert hat, d.h. in welchem Zeitintervall er aufgerufen wird.
Man was macht ihr ein Aufwand. Das geht mit 5 Zeilen ;) in den Falle public Zeit as integer public i as integer = 0 sub Taste_gedrückt if i = 1 and aktuelle_zeit - Zeit > 200 then ' 200 = Zeitwert der gewartet werden soll ' Zeitfenster abgelaufen :) i = 0 else ' was machen wenn 2 Druck erfolgt i = 3 end if if i = 0 then i = 1 zeit = aktuelle_zeit ' ausführen was bei Druck 1 passieren soll end if if i = 3 then i= 0 End sub Und fertig ist das ganze ;) Und da ihr kein Basic mögt, muss der TO das nur noch in seine Sprache umrechnen ;)
Ne das sieht nur so aus, das sind voreinstellungen vom System. Alles was ich gemacht habe ist quasi das was ich bereits zu beginn geschrieben habe, alles andere kannst du ignorieren. Mein Code besteht gerade mal aus 20 - 40 Zeilen.... es geht nicht um den interrupt wann er es ausführen soll sondern viel mehr dass während eines Arbeitsvorganges die zeit gemessen werden soll, und das konkret über den Button wie lange wird auf den button gedrückt, start mit tic (es wird gedrückt) ende bei toc (es wird los gelassen) toc - tic = wie lange der Knopf gedrückt wurde und dann die Fallunterscheidung wenn toc -tic > 100ms dann mache dass wenn toc - toc <= 100ms dann mach jenes das Prinzip ist wirklich sehr banal die umsetzung anscheinend nicht so sehr
Andy H. schrieb: > void TIM3_IRQHandler(void) > ... > while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) Ganz böses Foul. Blockieren im Interrupt macht die Sache nur umso schlimmer. So wird das nix. Schau Dir mein Beispiel an. Der Port wir einmal im Interrupt eingelesen und dann ein Zähler hochgezählt oder rückgesetzt.
:
Bearbeitet durch User
@Schlaumaier ja das denke ich auch. Hab ich das denn nicht so in etwa wie du gemacht? nur dass ich das separiert habe die if-Abfragen Naja "Foul" hin oder her, vielleicht kann mir jemand kommunizieren, wie man es konkret besser macht, denn ich bin im moment am Ende mit meinem Latein. Wäre jedenfalls Super Danke euch soweit schon mal
Andy H. schrieb: > Hab ich das denn nicht so in etwa wie du gemacht? Die Frage ist die Aufgabenstellung selbst. Wie lautet die genau. ??? In meinen Code bedeutet das folgendes. DRÜCKT der User innerhalb Zeit x (200 bei mir) die selbe Taste noch 1 x gilt das als "2. Funktion". Anders muss der Code aussehen (und etwas schweren) wenn du feststellen willst WIE LANGE der User die Taste drückt. Beide Formen der Mehrfachbelegung sind Standard. Mein Code z.b. wird für die Aufnahme-Funktion meines LG-DVD-Recorder benutzt. 1 x Drücken = Aufnahme, innerhalb von 5 Sek nochmal drücken 10 min, nochmal 20 min u.s.w. Bei meinen uralten Pager musste ich die Taste gedrückt halten, nach einigen Sekunden schaltete dann sich ein Menü ein, Taste weiter festgehalten und das Menü sprang immer weiter . Ist halt wie gesagt eine Frage was du wirklich willst. Die Grundlage : Die Zeitabfrage, brauchst du aber immer.
@schlaumaier ok, das klingt doch schon mal ganz gut, ich würde mal behaupten, dass es bei mit sogar einfacher ist oder nicht wesentlich mehr als das was du gemacht hast. ich will einfach mit dem SELBEN Knopf: Start/Stopp und Paus bedienen also quasi zweimal das Gleiche. Als Ersatz habe ich zunächst LEDs angebunden, um zu testen dass es geht Ungefähr so: i=0; alles ist aus mit while i == 0 aber wenn gedrückt wird dann i=1 zeitgleich wird die erste Zeit aufgenommen (tic) Pin wird während des drückens und erst nach drücken des Knopfes auf 1 gesetzt - also wenn losgelassen wird - danach wird die zweite zeit augenommen(toc) und zum schluss Zeitdifferen = toc-tic und mit dieser Zeitdifferenz soll die if-Abfrage gebildet werden wenn 5sekunden gedrückt dann start, wenn 5-10 sekunden gedrückt dann pause wirklich sehr simpel Im Grunde ist es zweimal das Gleiche nur auf jeweils einen anderen Zeitbereich unterteilt aber ich kapier noch nicht was fehlt oder was ich anders machen muss also konkret:
1 | while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 0) |
2 | |
3 | {
|
4 | //Zustand: schalter aus, knopf nicht gedrückt
|
5 | // warten auf Knopfdruck
|
6 | }
|
7 | |
8 | i++; |
9 | |
10 | //Zurücksetzen wenn zweimal gedrückt
|
11 | |
12 | if (i >= 2) |
13 | {
|
14 | i = 0; |
15 | }
|
16 | |
17 | //hier aktuelle StartUhrzeit Systickcount ausgeben und in tic
|
18 | speichern
|
19 | |
20 | tic = HAL_GetTick(); |
21 | |
22 | while (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0) == 1) |
23 | |
24 | {
|
25 | //hier Knopf gedrückt
|
26 | //bspw. Start und Pause
|
27 | |
28 | } // hier die zweite uhrzeit (EndUhrzeit) ausgeben und in toc |
29 | speichern
|
30 | |
31 | toc = HAL_GetTick(); |
32 | |
33 | ZeitDifferenz der End-Startzeit in Variabl a gespeichert |
34 | |
35 | uint32_t a = toc - tic; |
36 | |
37 | // Wenn Zeitdifferenz kleiner als 1200ms
|
38 | |
39 | if(a < 1200) |
40 | {
|
41 | set_blaueTaste(i); |
42 | }
|
43 | |
44 | // Wenn Zeitdifferenz größergleich 1200ms
|
45 | |
46 | else if (a >= 1200) |
47 | {
|
48 | set_blaueTaste1(i); |
49 | }
|
50 | |
51 | else
|
52 | {
|
53 | // Für den Fall der Fälle alle LEDs aus
|
54 | |
55 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); |
56 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); |
57 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); |
58 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_8,GPIO_PIN_RESET); |
59 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_9,GPIO_PIN_RESET); |
60 | }
|
61 | |
62 | void set_blaueTaste(uint8_t push) |
63 | {
|
64 | // Wenn gedrückt i==1
|
65 | |
66 | if (push == 1){ |
67 | |
68 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); |
69 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_SET); |
70 | }
|
71 | |
72 | //Wenn taste wieder gedrückt dann alle LEDs aus
|
73 | |
74 | else if(push == 0) |
75 | {
|
76 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); |
77 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); |
78 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); |
79 | }
|
80 | |
81 | // Default Notfalls alle LEDs aus
|
82 | |
83 | else{ |
84 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); |
85 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); |
86 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); |
87 | }
|
88 | }
|
89 | |
90 | --------
|
91 | |
92 | |
93 | void set_blaueTaste1(uint8_t push) |
94 | {
|
95 | // Wenn gedrückt i==1
|
96 | |
97 | if (push == 1){ |
98 | |
99 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_SET); |
100 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_SET); |
101 | }
|
102 | |
103 | //Wenn taste wieder gedrückt dann alle LEDs aus
|
104 | |
105 | else if(push == 0) |
106 | {
|
107 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); |
108 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); |
109 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); |
110 | }
|
111 | |
112 | // Default Notfalls alle LEDs aus
|
113 | |
114 | else{ |
115 | HAL_GPIO_WritePin(GPIOA,GPIO_PIN_0,GPIO_PIN_RESET); |
116 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_6,GPIO_PIN_RESET); |
117 | HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,GPIO_PIN_RESET); |
118 | }
|
119 | }
|
Andy H. schrieb: > ich will einfach mit dem SELBEN Knopf: > Start/Stopp und > Paus > bedienen Dazu brauchst du meine Routine UND EIN STATUS. Status hat folgende Zustände. "Läuft" o. "Läuft nicht". privat status as string = "läuft nicht" Sub taste_gedrückt if Status "läuft nicht" dann Status = "läuft" ' mach was du willst else if i = 1 and aktuelle_zeit - Zeit > 200 then ' 200 = Zeitwert der gewartet werden soll ' i = 0 Status = "läuft" ' gerät läuft weiter else ' was machen wenn 2 Druck erfolgt ' Stop befehl senden status = "läuft nicht" i = 3 end if if i = 0 then i = 1 zeit = aktuelle_zeit ' ausführen was bei Druck 1 passieren soll ' laufen lassen ' status = "läuft" end if if i = 3 then i= 0 end sub So in etwas. Ist der Status = "läuft nicht" wird beim 1 Druck auf die Taste, der Status geändert auf "läuft" und das Gerät gestartet. Beim nächsten Druck auf die Taste nach einiger Zeit wird das Gerät in den Pause Modus versetzt. Beim 2. Druck auf die Taste innerhalb Zeit X wird das Gerät vom Pause Modus in den Modus gestoppt versetzt und Status ist "läuft nicht" musst du halt ausknobbeln ;) Aber ohne einen Status als Gobale Variable wird das nix.
Nachtrag: Das ist absolut kein Optimierter Code. In echten Basic würde ich mit Case Arbeiten, aber ich weiß nicht ob das System von dir Case kann. If Then Zeug kann jedes Programmiersystem.
Schlaumaier schrieb: > Die Grundlage : Die Zeitabfrage, brauchst du aber immer. Die genaue Zeit muß man nicht wissen. Einfacher ist es im Timerinterrupt eine Variable zählen zu lassen und ist ein bestimmter Wert erreicht, das Bit für Langdruck zu setzen. Das Main kann dann bequem die beiden Bits für kurz oder lang auswerten.
Peter D. schrieb: > Die genaue Zeit muß man nicht wissen. > Einfacher ist es im Timerinterrupt eine Variable zählen zu lassen und > ist ein bestimmter Wert erreicht, das Bit für Langdruck zu setzen. > Das Main kann dann bequem die beiden Bits für kurz oder lang auswerten. Dann brauch ich aber ein Timer ;) Bei mein Arduino würde ich mit Millis arbeiten. Was die Sache einfacher macht. Alte_millis merken, und mit neuen Millis vergleichen. Nur ne lausige Variable, nix Timer ;) Bloss ich muss zugeben das ich sein MC nicht kenne, und nicht weiß ob der Compiler Millis + Case kann. Wenn der so Spielereien nicht kann gebe ich dir Recht. Dann muss man sich mit Timerinterrupt herum schlagen.
Schlaumaier schrieb: > Dann brauch ich aber ein Timer ;) Nö, sondern einen Timerinterrupt, der das Abtastintervall festlegt. Der Trick ist, ich zähle nur, wenn die Taste gedrückt ist. Damit vermeide ich die tödliche Blockierung.
Andy H. schrieb: > wenn 5sekunden gedrückt dann start, > > wenn 5-10 sekunden gedrückt dann pause > > wirklich sehr simpel Was soll diese zeitliche Staffelung?! Du hast doch nur zwei Zustände, Start und Stop. Eine "Auswahl" brauchts da ja nich... Bei Zustand "Start", hat die Taste die Funktion nach xSekunden "Stop". Bei Zustand "Stop/Pause", hat die Taste die Funktion nach xSekunden "Start".
@Peter: also ich habe mir mal dein bsp angesehen, aber ich finde es schon sehr unübersichtlich zumindest für einen ungeübten. Allerdings hapert es eher bei der umsetzung, aber vielleicht fällt mir noch was dazu ein. @Schlaumaier: Es ist ein von STM32 Ich bin mir gar nicht so sicher ob, diese Art von Bibliotheken in diesem MK bekannt sind, auch wenn es absoluter c standard ist. Aber wie gesagt, bin auch absoluter rookie @Teo: Funktion1: Start/Stopp ist eine Funktion Funktion2: Pause Deshalb ist eine Fallunterscheidung mittels Zeitmessung sinnvoll oder Durch Zählen nötig, wie Peter es geschrieben hat. Aber ich verstehe immer noch nicht warum mein code nicht funktioniert, also warum das nicht so funktionnieren kann, denn es sieht für mich plausibel aus Ich denke ich werde eine Funktion einfach auslagern auf einen anderen Knopf, ist zwar am Ziel vorbei, aber ich werde das nicht mehr so schnell hinkriegen. Mir raucht der Kopf...Danke für eure unterstützung. Falls jemand doch noch innerhalb meines Codes eine Lösung parat hat, würde ich mich freuen, ich bin mir sicher, dass es trivialer ist, als gedacht. VG Andy
Peter D. schrieb: > Blockierende Programmierung ist generell schwer zu durchschauen und > fehlerträchtig. Es kommt auf die Anwendung an, ich würde sie nicht grundsätlich verteufeln. Meine Steuerung eines Heizelementes lässt jede Sekunde die LED blitzen (ohne delay) um ihr Leben zu signalisieren und pollt eine Taste. Wenn ich den Knopf drücke, blockiere ich und ermittele, ob dieser kurz, eine Sekunde oder drei Sekunden gedrückt wurde - da der µC nichts anderes zu tun hat, arbeite ich blockierend. Dass während der Taste die LED nicht blitzt, wird kein Benutzer beanstanden. Wenn die Steuerung dann aktiv ist, wird in der Hauptschleife über gesetzte Timer die Heizung gepulst und die zwei Tasten werden gepollt. Die Starttaste weise ich direkt ab, wenn mein Flag "aktiv" gesetzt ist. Die Stop-Taste ist blockierend, wird nach 30ms erneut abgefragt - hat gepfurzt oder war wirklich gedrückt, der theoretisch mögliche Zeitverzug von 30ms ist für die Gesamtfunktion unkritisch. Aufpassen muß man erst, wenn es zeitkritisch wird: In meiner Lötstation kann ich mir nicht erlauben, mal eben für 3 Sekunden die Temperaturreglung zu blockieren, dann ist die Lötspitze tot. Da kann ich entweder aufwendig Zeiten zählen oder ganz simpel bei Erkennen einer Taste den Heizstrom abschalten. Ich finde blockierende Abfragen und Pollen von Tasten nicht pauschal böse, man muß wissen, was man tut.
Andy H. schrieb: > @Schlaumaier: Es ist ein von STM32 > Ich bin mir gar nicht so sicher ob, diese Art von Bibliotheken in diesem > MK bekannt sind, auch wenn es absoluter c standard ist. Der Schlaumeier hat sich schon zu Recht so genannt. Der postet Basic um schlau auszuschauen, ist in Wirklichkeit aber unschlau. Das ganze ist wieder mal eine Zustandsmaschine. Es gibt folgende Zustände: keineTasteGedrueckt TasteGedruecktBis1Sekunde TasteGedrücktUeber1Sekunde Das ganze wird in eine Schleife gepackt. Ich schreib das in Pseudocode
1 | bool TasteGedrueck() { |
2 | // Taste abfragen und true wenn gedrueck zurückgeben. |
3 | } |
4 | |
5 | zustand = keineTasteGedrueck |
6 | zeit = SysTick() |
7 | |
8 | while true { |
9 | if TasteGedrueck() |
10 | if (zustand == keineTasteGedrueck) // Taste wurde soeben gedrückt |
11 | zeit = SysTick() |
12 | |
13 | if (sysTick() - zeit < 1) |
14 | zustand = TasteGedruecktBis1Sekunde |
15 | if (sysTick() - zeit > 1) |
16 | zustand = TasteGedruecktUeber1Sekunde |
17 | else |
18 | zustand = keineTasteGedrueck |
19 | |
20 | // LED leuchten lassen nach Zustand, kann man aber auch |
21 | // überall da machen, wo sich der Zustand aendert. |
22 | if zustand == keineTasteGedrueckt) |
23 | LEDAus() |
24 | if (zustand == Taste.... |
25 | } |
Achtung! sysTick() liefert wohl keine Sekunden zurück, daher ist die Abfrage ob eine Sekunde rum ist, eher sowas: if (sysTick() - zeit > 10000 ...
Manfred schrieb: > Es kommt auf die Anwendung an, ich würde sie nicht grundsätlich > verteufeln. Man kann sich natürlich für jede Anwendung immer wieder neu die Mühe machen, eine Tastenabfrage mit all ihren Seiteneffekten irgendwie da hinein zu verbasteln. Enorm zeit- und fehlersparender ist es allerdings, einmal eine universelle Tastenabfrage zu implementieren, die nicht in die Anwendung hinein verwebt werden muß, sondern völlig getrennt ihre Aufgabe erledigt. Die Trennung, die Abfrageroutine liefert Ereignisbits, die Anwendung fragt die Ereignisbits ab, macht dann wieder alles sehr übersichtlich. Man muß sich nur erstmal auf die Trennung von Aufgaben einlassen und nicht alles als großen monolithischen Block ansehen. Teile und herrsche.
:
Bearbeitet durch User
Andy H. schrieb: > @Peter: also ich habe mir mal dein bsp angesehen, aber ich finde es > schon sehr unübersichtlich zumindest für einen ungeübten. Die Routinen sind doch sehr klein und übersichtlich. Jede Teilaufgabe hat ihre eigene Routine. Hier noch eine Erklärung dazu: https://www.compuphase.com/electronics/debouncing.htm Andy H. schrieb: > Allerdings hapert es eher bei der umsetzung, aber vielleicht fällt mir > noch was dazu ein. Der Hauptunterschied ist eigentlich nur die Syntax und die Initialisierung des Timerinterrupts. Der Rest ist plain C.
Nick M. schrieb: > Das ganze ist wieder mal eine Zustandsmaschine. > Das ganze wird in eine Schleife gepackt. > > Ich schreib das in Pseudocode Genau das selbe habe ich auch gesagt und getan. Ergo sind wir beide Schlaumeier. ;) Ich habe nur kein Bock einen Schüler die Hausaufgaben zu machen. Ich gebe Hilfestellung und ein Schubs in die richtige Richtung. Genau das selbe was ich bei Lösungen zu einen Problem brauche. Ein Codeschnipsel der mir die Richtung anzeigt. Den Rest sollte er selbst machen.
Schlaumaier schrieb: > Genau das selbe habe ich auch gesagt und getan. Dann lies mal deinen unleserrlichen Spaghettisalat. Das selbsterklärende i kann 1, 2 oder 3 sein. Wenn es 3 ist, dann wird es wieder 0. Und der Zustand als String gespeichert. Muss man dazu Basic-Programmierer sein?
Peter D. schrieb: > Manfred schrieb: >> Es kommt auf die Anwendung an, ich würde sie nicht grundsätlich >> verteufeln. > > Man kann sich natürlich für jede Anwendung immer wieder neu die Mühe > machen, eine Tastenabfrage mit all ihren Seiteneffekten irgendwie da > hinein zu verbasteln. > Enorm zeit- und fehlersparender ist es allerdings, einmal eine > universelle Tastenabfrage zu implementieren, die nicht in die Anwendung > hinein verwebt werden muß, sondern völlig getrennt ihre Aufgabe > erledigt. > Die Trennung, die Abfrageroutine liefert Ereignisbits, die Anwendung > fragt die Ereignisbits ab, macht dann wieder alles sehr übersichtlich. > Man muß sich nur erstmal auf die Trennung von Aufgaben einlassen und > nicht alles als großen monolithischen Block ansehen. Teile und herrsche. Kann ich nur unterschreiben. Und für die Auswertung dann mit state-machines arbeiten und nicht in unendlich verschachtelten if- und while-Konstrukten verlieren. Garry
Jooo moin allerseits!
nun das Problem habe ich gelöst, dank der Hilfestellung meines
Betreuers, der dann doch noch die Zeit gefunden hat mir zu antworten.
Dank den ganzen Einschränkungen (ob sinnvoll oder nicht) saufen sie alle
vor arbeit ab , da alles komplizierter geworden ist, um 'ne "billige"
info zu vermitteln.
An alle herzlichen Dank für eure Hilfestellung.
ÄÄÄÄND SE OSKA GOS TUUU....
@Nick.M
...und (fast) genau so wirds gemacht.
Das wort fast, weil die boolean Abfrage nicht unbedingt sein musste
Sehr gut wie du es "trocken" beschrieben und auf den Punkt gebracht
hast:
> "Das ganze ist wieder mal eine Zustandsmaschine."
Ja Absolut.
übrigens war das stichwort "basic" sehr hilfreich und "spaghettisalat"
passend =)
Sicherliche würden die anderen Codes auf funktionieren.
@Schlaumaier
Danke für dein Code, dieser hat zwar seinen gewissen scharm, aber leider
beherrsche ich basic nicht, vielleicht kommt das noch ;)
@Peter
Zeitunabhängig ist auch ne gute Sache, aber da hapert es mir noch etwas
an der praxis. Das mit der Zeitmessung schien mir die einfachere
variante
An alle vielen Dank für eure comments!
Dann habt mal alle einen schicken Tag!
VG
Andy
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.