Hi,
ich hab ein kleines Problem damit, meine µC-Applikation zu schreiben.
Also, es scheitert nicht an der Programmierung an sich, sondern an der
Art der Lösung. Ich habe die Einzelteile, also z.B. Treiber für Display,
Tastatur usw. schon geschrieben, sie funktionieren auch, soweit ich das
Austesten konnte.
Das Problem besteht nun darin, dass ich es nicht schaffe, die Teile so
zusammen zu pfriemeln, dass sich eine gescheite Applikation ergibt.
Konkret scheitert es eigentlich schon am Ansatz :(
Vom Gefühl her würde ich sagen, dass es am besten ist, wenn ich das
Programm so schreibe, dass an keiner Stelle auf irgendwas gewartet,
sondern nur geprüft wird, ob etwas an der entsprechenden Stelle gemacht
werden muss -> State-Machine?
Diesen Ansatz (ohne State-Machine) habe ich nun versucht zu
implementieren, d.h. in der Main-Schleife laufen zwei Sachen. Erstens
eine Auswertung von empfangenen DCF77-Daten (die Daten selbst lese ich
in einem Interrupt aus -> funktioniert). Das zweite ist eine
Menü-Ausgabe.
Die Menü-Ausgabe ist etwas spezieller, weil dort momentan irgendwie
alles abläuft, deswegen erklär ich das mal genauer:
Die Menü-Funktion prüft, ob eine der vier Navigationstasten gedrückt
wurde. In Abhängigkeit davon wird ein Pointer auf ein Menü-Element
gesetzt.
Das Menü-Element hat folgenden Aufbau:
1
typedefstructm_item{
2
structm_item*Up;
3
structm_item*Down;
4
structm_item*Left;
5
structm_item*Right;
6
void(code*fpPtr)(void);
7
}_stMenu;
Die ersten vier Einträge zeigen jeweils auf den
oberen/unteren/linken/rechten Knoten des Menüs, bzw. auf NULL(nicht 0),
wenn's keinen direkten Nachbarn mehr gibt. Die Menü-Struktur wird über
ein entsprechendes Array der Menü-Elemente realisiert.
Der fünfte Eintrag ist ein Funktionspointer. Die entsprechende Funktion
wird bei jedem Aufruf der Menü-Funktion aufgerufen, unabhängig davon, ob
eine der Richtungstasten gedrückt wird.
Zusätzlich kann die Abfrage der Navigations-Tasten in der Menü-Funktion
durch ein globales Flag gesperrt werden, um die Navigationstasten für
die aufgerufenen Funktion freizumachen.
Die aufgerufenen Funktionen übernehmen alles, von der Display-Anzeige
über die Tastatur-Eingaben, bis hin zu IO-Aufgaben.
So, und ich glaube mit dem Ansatz hab ich mir n Ei gelegt. Erstens
gibt's irgendwie Kuddelmuddel, zweitens gefällt es mir vom Gefühl her
nicht, und dritten tut's eh nicht :(
Die Frage wär jetzt, wie realisiert man sowas richtig? Und zwar nicht
auf ein spezielles Problem bezogen, sondern allgemein.
Hierzu mal meine Überlegungen. Ich denke, ich brauch definitiv ne
State-Machine. Punkt.
Wie bau ich die denn nun auf? Eine Variable für alle Zustände, oder für
jeden Part (Tastatur, LCD, usw.) eine eigene Variable?
Wenn ich nur eine Variable verwende, gibts ja irgendwie wieder ein
Durcheinander, weil dann m.E. die Eingabe nicht sauber von der Ausgabe
getrennt ist.
Also eher der Ansatz von voneinander unabhängigen State-Variablen. Und
wie realisiert man dann sowas? Wie sieht das Grundgerüst aus? Hat mir
vielleicht jemand Pseudocode?
Oder ist der Ansatz auch murks?
Ich hoffe, ich konnte alle relevanten Infos liefern :)
Vielen Dank schonmal
Michael
Menus implementier ich meist ähnlich, und hab dort fast alles innerhalb
meiner menu-structs definiert:
1
#define CODE_LEFT 0
2
#define CODE_RIGHT 1
3
#define CODE_PRESS 2
4
#define CODE_IDLE 3
5
#define FAST_IDLE 4
6
#define CODE_ENTER 5
7
#define CODE_LEAVE 6
8
#define CODE_UPDATE 7
9
10
#define EVENT_ENTER 1
11
#define EVENT_LEAVE 2
12
#define EVENT_UPDATE 3
13
14
#define SHORT_IDLE_SECONDS 5
15
#define LONG_IDLE_SECONDS 30
16
17
typedefvoid(*display_func)(uint8_t);
18
19
structmenu_entry{
20
constprog_char*text;
21
display_funcdisplay;
22
constvoid*left;
23
constvoid*right;
24
constvoid*press;
25
constvoid*idle;
26
27
uint8_tflags;
28
};
Je nach gesetztem "CODE_XXX" Flag sind die Void-Pointer Verweise auf den
nächsten eintrag, oder Funktionspointer, die aufgerufen werden.
die display_func wird jde nach CODE_ENTER,CODE_LEAVE,CODE_UPDATE
aufgerufen (Mit EVENT_XXX) als Parameter, und kann z.B. im "Enter" einen
Wert aus dem EEPROM auslesen, im update darstellen, und beim Leave
wieder ins eeprom zurückspeichern. Die left/right-Funktionen dienen dann
zum einstellen des Wertes.
Beispiel um eine Uhrzeit einzustellen:
> Die aufgerufenen Funktionen übernehmen alles,> von der Display-Anzeige über die Tastatur-Eingaben,> bis hin zu IO-Aufgaben.
Konsequenz daraus ist: Solange eine der Menüfunktionen läuft, ist alles
andere tot. Ist das vielleicht das Problem?
Hallo,
sorry für die späte Antwort.
@Ernst:
Danke, ich werd mir deinen Code mal durchlesen.
@Tuppes:
> Konsequenz daraus ist: Solange eine der Menüfunktionen läuft, ist alles> andere tot. Ist das vielleicht das Problem?
Nein, es ist eben nicht alles andere tot, die Funktionen sind extra so
geschrieben, dass nix stehenbleibt. Aber irgendwie wird alles dort
gemacht, und das fühlt sich eben nicht richtig an. Ich bin der Meinung,
dass sich das sauberer trennen lassen muss, nur fehlt mir dazu der
Lösungsansatz.
Michael