Hallo Zusammen, ich habe gerade ein problem und hoffe, dass ich bei euch eine Lösung finden könnte. und Zwar ich arbeite momentan auf ein Projekt, bei dem ich eine Kommunikation per Rs232 zwischen ein messgerät und ein computer aufbauen soll. Während der ausführung des Programms sollte das Messgerät bei Abfrage eines Parameters (Tastatur eingabe) den Wert des abgefragten Parameters ausgeben. Mein Problem jetzt besteht darin, dass die parameter von unterschiedlichen Typen (float, int, char, uzw...)sind und ich weiß nicht wie ich die über eine Variable (auf dem beigefügten programm heißt diese variable "value") auf die rs232 schicken bzw. auslesen kann. wie könnte ich die variable "value" definieren damit sie, je nachdem was gefragt wwird, alles parametertypen schickt bzw ausließt. PS: das ist nur ein beispielprogramm um meine Frage ein bischen zu verdeutlichen. #include <stdlib.h> #include <stdio.h> #include <time.h> #define VALEUR_PAIN 2.55 #define VALEUR_CHOCOLATINE 3.90 #define VALEUR_BEURRE 5 union Boutique { float pain; int chocolatine; long beurre; } valeur; int main() { int value; char Command[20]; while(1) { fgets(Command, sizeof(Command), stdin); if (0 == strcmp(Command, "pain\n")) { valeur.pain = VALEUR_PAIN; value = valeur.pain; } else if (0 == strcmp(Command, "chocolatine\n")) { valeur.chocolatine = VALEUR_CHOCOLATINE; value = valeur.chocolatine; } else if (0 == strcmp(Command, "beurre\n")) { valeur.beurre = VALEUR_BEURRE; value = valeur.beurre; } else { printf("invalid\n"); } printf("%i\n", value); } return 0; }
> wie könnte ich die variable "value" definieren damit sie,je nachdem > was gefragt wwird, alles parametertypen schickt bzw ausließt. Die einfachste Variante: die nimmst einen Typ, der alle Bereiche abdeckt. In deinem Fall böte sich ein float oder double an[1]. Notfalls ein String. Alternativ nimmst du einen zusammengesetzten Typ[2], der zusätzlich ein Feld enthält, das Auskunft über den Typ gibt. In deiner Ausgaberoutine fragst du den Typ ab und behandelst den Wert entsprechend. [1] evtl wird bei int/long gerundet - aufpassen. [2]
1 | struct tval { int typ; union { float f; int i; char c; } val; }; |
Kommunikation via RS232 geht doch i.d.R über Zeichen bzw. Zeichenketten die von einem Endezeichen begrenzt werden, letztendlich also Zeichenarrays (Strings). Wo liegt da jetzt das Problem? Du kannst doch jeden Deiner Datentypen problemlos in einen String konvertieren bzw. zurückkonvertieren. Du muß Dir jetzt eigentlich nur ein geeignetes Protokoll einfallen welches es ermöglicht die Daten zu unterscheiden. Dazu könnte man den eigentlichen Daten Präfix von einer definierten Anzahl von Zeichen voran stellen. Im einfachsten Fall ein 1 Zeichen, z.B. F für float, I für Integer usw.. Wie gesagt das können auch mehr Zeichen sein. Beim Senden mußt Du die Zeichen halt nur als Präfix einfügen und beim Empfang genau die Anzahl der als Präfix verwendeten Zeichen separieren. Je nach Präfix kannst Du dann die Folgedaten weiter verarbeiten und die Zeichenkette in einen Float oder was auch immer zurück verwandeln. Das Messgerät - ist das was Fertiges oder eine Eigenkonstruktion. Bei ersterem kannst Du davon ausgehen, das da einfache Zeichenketten übertragen werden.
> Das Messgerät - ist das was Fertiges oder eine Eigenkonstruktion. Bei > ersterem kannst Du davon ausgehen, das da einfache Zeichenketten > übertragen werden. Das Messgerät ist ein fertiges.
> struct tval { int typ; union { float f; int i; char c; } val; };
bis hier komme ich klar. Danke.
Aber ich ich noch nicht verstehe ich halt die main-Funktion. also wie es
dort weiter gehen sollte
Siehe Serialisierung. Die Variante mit "union" ist in C implementation-defined und damit unportabel; in C++ ganz verboten.
Zeig doch mal das RS232 Protokoll von deinem Multimeter.
Niklas G. schrieb: > Siehe Serialisierung. Die Variante mit "union" ist in C > implementation-defined und damit unportabel; in C++ ganz verboten. Kompletter Blödsinn. Lies den Artikel selbst nochmal. Union ansich ist weder implementation defined noch verboten. Nur gewisse Arten, wie darauf zugegriffen wird, sind es. So wie es hier verwendet werden soll, nämlich Zuweisung und Auslesen immer vom jeweils korrespondierenden Member, ist es vollkommen unproblematisch und wohldefiniert.
DPA schrieb: > Kompletter Blödsinn. Lies den Artikel selbst nochmal Klar, meine eigenen Artikel les ich immer gerne! Der gezeigte Quelltext ist unproblematisch, sendet aber noch nichts an das Messgerät. Ich hatte den Verdacht, dass die gezeigte union dann noch zur "Konvertierung" genutzt werden soll. Ob man auf einer PC-Software nämlich sonst wirklich eine union braucht um die paar Bytes Speicher zu sparen, ist ohnehin fraglich.
Was gefällt dir an den gezeigten Ideen nicht?
>> struct tval { int typ; union { float f; int i; char c; } val; }; > bis hier komme ich klar. Danke. > Aber ich ich noch nicht verstehe ich halt die main-Funktion. also wie es > dort weiter gehen sollte
1 | struct tval { int typ; union { float f; int i; char c; } val; }; |
2 | #define TVAL_FLOAT 0
|
3 | #define TVAL_INT 1
|
4 | #define TVAL_CHAR 2
|
5 | |
6 | static void tval_print(struct tval *tv) |
7 | {
|
8 | switch (tv->typ) { |
9 | case TVAL_FLOAT: printf("%f\n", tv->val.f); break; |
10 | case TVAL_INT: printf("%d\n", tv->val.i); break; |
11 | case TVAL_CHAR: printf("%c\n", tv->val.c); break; |
12 | default: printf("internal error 42\n"); |
13 | }
|
14 | }
|
15 | |
16 | int main() |
17 | {
|
18 | struct tval tval; |
19 | char Command[20]; |
20 | |
21 | while(1) |
22 | {
|
23 | fgets(Command, sizeof(Command), stdin); |
24 | |
25 | if (0 == strcmp(Command, "pain\n")) |
26 | {
|
27 | tval.typ = TVAL_FLOAT; |
28 | tval.val.f = VALEUR_PAIN; |
29 | }
|
30 | else if (0 == strcmp(Command, "chocolatine\n")) |
31 | {
|
32 | tval.typ = TVAL_FLOAT; |
33 | tval.val.f = VALEUR_CHOCOLATINE; |
34 | }
|
35 | else if (0 == strcmp(Command, "beurre\n")) |
36 | {
|
37 | tval.typ = TVAL_INT; |
38 | tval.val.i = VALEUR_BEURRE; |
39 | }
|
40 | else
|
41 | {
|
42 | printf("invalid\n"); |
43 | continue; |
44 | }
|
45 | tval_print(&tval); |
46 | }
|
47 | }
|
Aber irgendwie hab ich den Eindruck, dass das für deinen Fall unnötig kompliziert ist. Mit einem Typ, der alle Werte abdeckt (hier String):
1 | int main() |
2 | {
|
3 | char value[32]; |
4 | char Command[20]; |
5 | |
6 | while(1) |
7 | {
|
8 | fgets(Command, sizeof(Command), stdin); |
9 | |
10 | if (0 == strcmp(Command, "pain\n")) |
11 | {
|
12 | sprintf(value, "%.3fkg", VALEUR_PAIN); |
13 | }
|
14 | else if (0 == strcmp(Command, "chocolatine\n")) |
15 | {
|
16 | sprintf(value, "%f", VALEUR_CHOCOLATINE); |
17 | }
|
18 | else if (0 == strcmp(Command, "beurre\n")) |
19 | {
|
20 | sprintf(value, "%d", VALEUR_BEURRE); |
21 | }
|
22 | else
|
23 | {
|
24 | printf("invalid\n"); |
25 | continue; |
26 | }
|
27 | printf("Ok, value is %s\n", value); |
28 | }
|
29 | }
|
> Aber irgendwie hab ich den Eindruck, dass das für deinen Fall unnötig > kompliziert ist. > > Mit einem Typ, der alle Werte abdeckt (hier String): würde man das per Rs232 abfragen, das wüde das programm ganz anders aussehen oder? nehmen wir an wir hätten ein Gerät, das uns die gesuchte werte zurückgeben kann. die Nachricht sollte vllt aus 8 Databits, 1 Stopbits, ohne parity und Flow control bestehen. #define VALEUR_PAIN 0x20 #define VALEUR_CHOCOLATINE 0x21 #define VALEUR_BEURRE 0x22
Kaiser K. schrieb: > würde man das per Rs232 abfragen, das wüde das programm ganz anders > aussehen oder? > > nehmen wir an wir hätten ein Gerät, das uns die gesuchte werte > zurückgeben kann. Wir müßen es annehmen, du weißt es - immerhin steht das Gerät ja vor dir. Dazu wird es eine Doku geben, wie die RS232 Kommunikation abzulaufen hat. An die mußt du dich halten. Wie du die Daten in deinem Programm nutzt, ist dann deine Sache. Persönlich würde ich die Lösung mit union bevorzugen, da die Umwandlung von einer Zeichenkette in den entsprechenden Datentyp dann nur einmal geschehen muß, ebenso die Umwandlung von deinem Datentypen in eine Zeichenkette.
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.