Hallo,
ich brauch mal ein Gedankenanstoß.
Ich benutz die Uart von ATMegas gern um Programme einzustellen und zum
debuggen.
Bisher ist es aber recht umständlich oder nicht flexible. zb ein Byte
für den Kommand und dann ein Byte oder 2 (als int) für den Wert.
Zb. 5 (PWM) 100(Wert).
Im Programm sieht es dann so aus:
1
...
2
Uart_prog=5;
3
Uart_var=100;
4
...
5
switch(Uart_prog)
6
{
7
case...
8
9
case5:
10
ORC0A=Uart_var;
11
break;
12
13
case...
14
}
Hat einer eine elegantere Lösung, meine Lösung ist etwas.. primitiv und
unhandlich?
Ist eigentlich normal mit Switch/Case.
Man kann das ganze mit einem Array aus Structs anlegen. In einem Struct
steht dein UART_PROG und ein Funktionszeiger. Diese Funktion verarbeitet
dann deine UART_Var. Kommen nun Bytes an, so durchsucht der Handler alle
Structs im Array bis er das Struct mit dem gleichen UART_PROG findet und
führt dessen Funktion(szeiger) mit UART_VAR aus.
Am Programmbeginn müssen einmal alle Structs erzeugt und mit den
korrekten Funktionszeigen befüllt und ins Array aufgenommen werden.
Also eine Art Objektorientierter Ansatz.
gruß cyblord
Vielen Dank für deine Antwort.
Ich werde mir die Idee mal anschauen, aber glaub allzu anders als meine
Switch/Case ist das auch nicht. Hat man vorteile bei größeren Listen in
sachen Übersicht oder Speicherverbrauch?
Hab bisher noch nicht so mit Zeigern gearbeitet, meist übergeb ich
Variable Structs als Zeiger in andere Unterprogramme.
Peter schrieb:
Hat man vorteile bei größeren Listen in
> sachen Übersicht oder Speicherverbrauch?
Ich mache das meist auch mit einem Array aus Strukturen. Von der
Übersicht her finde ichs ganz angenehm, da ich nicht mitten im Code nach
den Befehlen suchen muss, sondern ganz am Anfang der Sourcedatei. Die
Auswertung erfolgt dann in einer for-Schleife, also eher kurzer Code.
Bezüglich Speicherverbrauch kann ich keine Aussage machen.
> Hab bisher noch nicht so mit Zeigern gearbeitet, meist übergeb ich> Variable Structs als Zeiger in andere Unterprogramme.
Einfach mal im Internet suchen oder in einem C-Buch nachlesen.
Stichwort: Funktionszeiger
Peter schrieb:> Vielen Dank für deine Antwort.> Ich werde mir die Idee mal anschauen, aber glaub allzu anders als meine> Switch/Case ist das auch nicht. Hat man vorteile bei größeren Listen in> sachen Übersicht oder Speicherverbrauch?
Übersicht: ja, weil die relevanten Informationen mehr oder weniger an
einer Stelle gesammelt beisammen bleiben
Speicherverbrauch: eher nicht, weil die Strukturierung in ein immer
gleiches Daten-Schema fast zwangsläufig zuätzliche
Strukturierungselemente benötigt und zum anderen nicht so optimal auf
individuelle Probleme eingehen kann.
> Hab bisher noch nicht so mit Zeigern gearbeitet, meist übergeb ich> Variable Structs als Zeiger in andere Unterprogramme.
Alles halb so wild
FAQ - Funktionszeiger
Peter schrieb:> Sieht wirklich Übersichtlicher aus als mit der Switch Case variante.> Vielen Dank, an die FAQ hatte ich gar nimmer gedacht..
Bevor du loslegst:
Bei mir hat es sich immer bewährt, wenn ich mir vorher mal kurz
aufschreibe, wie ich im Endergebnis dann meine 'Daten' eingeben möchte.
Und von dort fange ich dann an, das Pferd aufzuzäumen.
Ich könnte mir zb vorstellen, dass deine 'Parameter Auswertungs
Beschreibung' (ein furchtbares Wort) zb so aussieht
1
{ 0x01, 1, SetToByte, &Seconds },
2
{ 0x02, 1, SetToByte, &Minutes },
3
{ 0x03, 1, SetToByte, &Hours },
4
{ 0x04, 1, SetToPrescaler, &TCCR1A },
5
{ 0x05, 2, SetToWord, &OCR1A },
6
7
^
8
| in welche Variable soll der Wert
9
^
10
| welche Funktion macht das (wegen Byte, Word, ...)
11
^
12
| wieviele Datenbytes kommen noch von der UART
13
^
14
| Wert des Kommandobytes von der UART
Ich sag jetzt nicht, dass das die einzig mögliche Art und Weise ist. Zb
ist es fraglich, ob man die Anzahl der Bytes von der UART explizit
anführen muss oder nicht, oder ob das nicht die aufgerufene Funktion
wissen sollte. Da steht vieles offen.
Aber so fange ich normalerweise an. Ich überlege mir, wie so eine
Beschreibung beispielsweise aussehen könnte, so dass da alles drinnen
ist, was ich haben möchte.
1
{ 0x02, 1, SetToByte, &Minutes },
Wenn das Kommando 0x02 kommt, dann kommt da noch 1 Datenbyte hinten
nach, welches in die Variable Minutes bugsiert werden soll und genau
dafür ist die Funktion SetToByte zuständig.
Wobei: wenn ich es mir so recht überlege. Für die 3 oder 4 verschiedenen
Funktionen die es da gibt, da lohnt sich ein Funktionspointer eigentlich
gar nicht. Ein Aktions-Typ, der entsprechend ausgewertet wird, tuts
eigentlich auch. Spart pro Kommando schon wieder 1 Byte ein.
Und dann gehts erst mit Code los - angefangen bei der
Strukturdefinition.
Denk dir was aus - implementiere es - sieh nach wo dich die Idee
hinführt. Und wenn sich nach ein paar Stunden rausstellt "äääääää, war
nicht so prickelnd", dann merk dir was das eigentliche Problem in diesem
Ansatz war, und probier was anderes.
Letzten Endes ist das genau das, was wir alle getan haben um heute vorab
schätzen zu können: Die Idee ist gut - die Idee ist nicht so gut.
Macht man das ein paar mal, dann entwickelt sich auch ein Bauchgefühl,
ob eine Idee tragfähig ist oder nicht.
Danke Buchegger für den Ablauf.
Mir gehts nur um mich etwas Weiterzubilden, ich prorgammier schon eine
ganze Weile und fand die Switch Case immer etwas Primitiv.
Ich wollte mir eine kleine Shell aufbauen die relativ flexible ist.
Zb das ich mal schnell mit einem Bluetooth vom Tablet oder Handy aus ein
System vorort umkonfigurieren kann oder Prüfdaten ablesen kann.
Sprich ich hab nachher ein klein Parser vom ASCII nach Binär und das
wollt ich danach in den Funktionspointer schicken.
Je nach Anwendung benutz ich direkt Binärdaten oder ebent ASCII.
Mit dem Funktionspionter kommt ich wieder ein Stück weiter und schreib
etwas sauberen Code.
Ist es einglich Sinnvoll sich die Variablen in einem Struct zu packen
und die in den Funktionen zu übergeben?
Zb im Main setz ich mir ein Struct stc_sys System;
und wenn ich zb Uhr_akt(&System); aufruf um die Uhrzeit zu
aktualisieren.
So hätte ich die Uhrzeit dann in jeder Funktion zur Verfügung über den
Pointer auf dem Struct vom System.
Gibt es da sinnvollere Programmablauftechniken?
Ich weiß ist sehr Oberflächlich und Allgemein gefragt.
Peter schrieb:> Ich weiß ist sehr Oberflächlich und Allgemein gefragt.
und daher schwierig zu beantworten.
Meine Antwort wäre: Ja, doch. Kann sinnvoll sein. Wenns nicht zu viele
sind. Eine Struct mit 200 Member ist wahrscheinlich nicht mehr sinnvoll.
Es hängt eben auch immer vom konkreten Programm ab.
Danke euch beiden. Dann war meine Idee von einer sinnvollen
Hauptspeicherstelle gar nicht so falsch.
Ich weiß das viele Details wichtig sind, wollte nur mal horchen obs
grundsätzlich Sinnvoll ist.
Deine Routine hab ich bisher noch gar nicht gesehen, Falk.. ich dachte
ich hätte alle Post zu UART gelesen..
Es ist ähnlich wie bei mir, nur nicht ganz so raffiniert und
Übersichtlich geschrieben. Besonders die Unterteilung in extra Funktion
hatte ich nicht. In meiner wurden nur Variable umgesetzt.
Besten Dank für den ganzen Input und ich hatte schon befürchtet ich werd
in der Luft zerfetzt wegen meiner Frage.. lach
Die Sachen werden mir sicher sehr weiter Helfen, ich muss sie mal in
ruhe alle Durchspielen und mit rumprobieren.
Falks Switch Version gefällt mir gut von der Übersicht her und scheint
für kleine Dinge optimal zu sein und die Pointer sache scheint mir für
größere Projekte ideal zu sein, rein vom Bauchgefühl her.
Nun werd ich meine Erfahrung damit sammeln.