Hallo C-Freunde,
ich habe ein Problem, möchte gerne ein Mikrocontroller-Netzteil bauen,
ich bin auch schon fast fertig, und nun möchte ich das Ding auch über
UART bedienen können.
Es kommt also ein String an der so aussieht:
"USET 12.00"
oder
"ISET 0.50"
so sieht das aus.
ich habe auch schon einen Code der mir den String aufteilt einmal in den
String Befehl[] (USET) und einmal in den String Wert[] (Zahl)
wenn man genauer hinsieht sieht man dass es *Befehl und *Wert heißt aber
ich kenn mich mit dem Zeigern nicht so aus. (ich habe das aus dem
Internet entdeckt)
....
(bis hierher klappts)
.....
nun bekomme ich es nicht hin, dass ich z.b. per SWITCH CASE Funktion
oder einfach mit IF den Befehl abfrage.
und die Zahl müsste noch umgewandelt werden in float
anbei ein Codeausschnitt
Martin 567 schrieb:
> ich habe auch schon einen Code der mir den String aufteilt einmal in den> String Befehl[] (USET) und einmal in den String Wert[] (Zahl)> wenn man genauer hinsieht sieht man dass es *Befehl und *Wert heißt aber> ich kenn mich mit dem Zeigern nicht so aus. (ich habe das aus dem> Internet entdeckt)
Genau hier liegt das Problem.
Programmieren kann man nicht lernen, indem man sich im 'Internet'
irgendwelche Codestückchen zusammensucht.
Du brauchst Literatur oder wenigstens ein C-Tutorial!
Zur Überbrückung, kannst du dir auch das wichtigste hier rauslesen
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F> nun bekomme ich es nicht hin, dass ich z.b. per SWITCH CASE Funktion> oder einfach mit IF den Befehl abfrage.
Das geht auch nicht bei Strings. switch-case kann man nur bei konstanten
Zahlen benutzen. strcmp ist hier dein Freund.
> und die Zahl müsste noch umgewandelt werden in float
strtod()
Du schreibst
if (befehl == "USET")
das geht in VisualBasic, wenn befehl ein String ist.
In C geht das nicht.
Vorschlag, Funktion schreiben, die Zeichen für Zeichen
den empf. Befehl mit einem Befehlsarray im Flash vergleicht und Dir
die Befehlsnummer (Stelle in dem Array) zurückgibt. Der
einfachheit-halber
legst Du dir noch ein ENUM an, was die Befehlsreihenfolge abbildet.
Mit der Befehlsnummer (enum) kannst du dann Deine switch-case abfrage
machen.
tip-geber schrieb:
> Du schreibst> if (befehl == "USET")> das geht in VisualBasic, wenn befehl ein String ist.> In C geht das nicht.> Vorschlag, Funktion schreiben, die Zeichen für Zeichen> den empf. Befehl mit einem Befehlsarray im Flash vergleicht und Dir> die Befehlsnummer (Stelle in dem Array) zurückgibt. Der> einfachheit-halber> legst Du dir noch ein ENUM an, was die Befehlsreihenfolge abbildet.> Mit der Befehlsnummer (enum) kannst du dann Deine switch-case abfrage> machen.
Was noch Komplizierteres als das ist dir jetzt auf die Schnelle nicht
eingefallen?
@ karl heinz Buchegger
was ist daran kompliziert, wenn man lieber 'ne selbstgeschriebene
Funktion benutzt, als fertige Stringfunktionen die der Compiler bietet.
Und zweitens ist es gleichzeitig noch eine schöne Übung.
kompliziert ist es aus Strings einen enum zu machen und den dann in
einen switch case zu stopfen, anstelle von
1
if(strcmp(befehl,"USET")==0){
2
// behandle den Befehl USET
3
}
4
5
elseif(strcmp(befehl,"ISET")==0){
6
// behandle den Befehl ISET
7
}
8
9
elseif(strcmp(befehl,"OUTPUT")==0){
10
// bahandle den Befehl OUTPUT
11
}
12
13
elseif(strcmp(befehl,"DISPLAY")==0){
14
// behandle den Befehl DISPLAY
15
}
16
17
else{
18
// Fehler, kein bekannter Befehl
19
}
wir reden hier von einer simplen Auswertung und nicht von einem
Cmopiler-Parser, bei dem der String viele zig-male mit Keywords
verglichen wird.
> wenn man lieber 'ne selbstgeschriebene> Funktion benutzt
Die Stringfunktionen in C gibt es ja auch nur deshalb, damit dann doch
wieder jeder sein eigenes Süppchen kocht. Wäre ja auch zu einfach, wenn
jeder andere C Programmierer den Code auf Anhieb lesen kann ohne erst
die 'Sonderfunktionen' zu analysieren und sich zu fragen warum in 3
Teufels Namen da eigene Varianten geschrieben wurden, anstatt die in C
vorgesehenen Funktionen zu verwenden. :-) Schreibst du dir eigentlich
einen Sinus auch selbst?
hallo
das mit strcmp hab ich vorher schon selbst probiert, da ich mir nicht
"alles" aus dem internet hole!
if( strcmp( befehl, "USET" ) == 0 ) {
// behandle den Befehl USET
}
genau wies da steht, aber anscheinend hängt es auch mit den zeiger
*Befehl und *Wert zusammen, aber ich bekomme nicht 0 raus sondern
irgendeinen wert wie 83 oder so
und der ist bei jeder eingabe der selbe.
hm.
ich probier morgen mal noch ein paar stringfunktionen durch
trotzdem danke
servus martin
Martin 567 schrieb:
> hallo>> das mit strcmp hab ich vorher schon selbst probiert, da ich mir nicht> "alles" aus dem internet hole!>> if( strcmp( befehl, "USET" ) == 0 ) {> // behandle den Befehl USET> }>> genau wies da steht, aber anscheinend hängt es auch mit den zeiger> *Befehl und *Wert zusammen, aber ich bekomme nicht 0 raus sondern> irgendeinen wert wie 83 oder so> und der ist bei jeder eingabe der selbe.
Dann hast du nicht richtig zerlegt :-)
Oder aber deine Ausgabe des Ergebnisses ist nicht richtig
(zb das hier: rprintf("befehl: %d",befehl); bringt mich auf diese
Idee)
Gross/Kleinschreibung hast du beachtet?
@ karl heinz Buchegger
mist, ich bekomme es nicht hin.
Wie geht das mit der Code-formatierung?
Einfach durch [c] und [\c] einfassen ?
Danke, schon mal im voraus.
tip-geber schrieb:
> @ karl heinz Buchegger>> mist, ich bekomme es nicht hin.> Wie geht das mit der Code-formatierung?> Einfach durch [c] und [\c] einfassen ?
Ganz genau
Karl heinz Buchegger schrieb:
> tip-geber schrieb:>> @ karl heinz Buchegger>>>> mist, ich bekomme es nicht hin.>> Wie geht das mit der Code-formatierung?>> Einfach durch [c] und [\c] einfassen ?>> Ganz genau
Tschuldigung der \ muss ein / sein
(Steht aber auch in der Box über dem Eingabefeld unter Formatierungen)
Neues Kommando?
Kein Problem:
Eine Behandlungsfunktion dafür geschrieben und ein neuer Eintrag ins
Array und schon wird die Funktion angesprungen, wenn das Kommando
erkannt wird.
Wenn schon afwändig, dann wenigstens so, dass sich in Zukunft eine
Zeitersparnis ergibt :-)
tut mir leid karl heinz, deine gedanken schnall i noch nicht.
was ist überhaut ein struct
werde mich mal noch ein bisschen schlauer machen müssen
da ich eigentlich schon ein ziemlicher anfänger bin und das geb ich auch
zu.
aba so insgesamt sieht es schon sehr vielversprechend aus
hm
danke dafür
Martin 567 schrieb:
> tut mir leid karl heinz, deine gedanken schnall i noch nicht.
LOL
> was ist überhaut ein struct
OK.
Vergiss es wieder.
Da liegen dann noch ein paar andere Feinheiten dahinter :-)
(Ein struct ist eine Struktur.
Daten die zusammen gehören, werden in einen gemeinsamen neuen Datentyp
gepackt.
zb ein Datum. Ein Datum besteht immer aus Tag, Monat, Jahr. Immer?
Immer! Spricht man von einem Datum dann ist das immer dieses Trippel.
Also ist es naheliegend mir für ein Datum eine Struktur zu bauen, die
genau das ausdrückt
1
structDate{
2
uint8_tday;
3
uint8_tmonth;
4
uint16_tyear;
5
};
Damit kann ich mir dann Funktionen bauen, die zb mit einem Datum
operieren
zb
oder ich habe eine 'Datenbank' in der Personen gespeichert sind, die zb
an einem bestimmten Tag ja Geburtstag haben. Was ist ein Geburtstag ...
datentypmässig. Genau ... es ist ein Datum
1
structPerson{
2
charfirstName[30];
3
charlastName[30];
4
structDatebirthDay;
5
};
Hab ich jetzt eine Person
1
structPersonBob;
und ist die richtig initialisiert, dann hat die natürlich auch
irgendwann Geburtstag. Will ich den ausgeben:
1
printDate(&Bob.birthday);
Ich hample hier also nicht mehr mit Tag/Monat/Jahr rum sondern betrachte
ein Datum als eine Einheit. Ein neuer Datentyp, der alles beinhaltet was
ein Datum ausmacht.
Und natürlich beinhaltet der Datentyp für Person alles was eine Person
ausmacht. Habe ich also ein struct Person Objekt, dann ist da alles mit
dabei: sein Vorname, Nachname und sein Geburtstag (als Tag/Monat/Jahr)
In dem Beispiel hab ich eine Struktur gebaut aus dem Kommandonamen und
der Funktion die dafür zuständig ist, dieses Kommando zu bearbeiten.
Ich habe mit LOL angefangen, weil dieser Aufbau natürlich für die 4
Kommandos um die es hier geht völliger Overkill ist. Und wenn tip-geber
ehrlich ist, ist auch seine Variante overkill. Denn um die strcmp kommt
er nicht herum, selbst dann nicht, wenn er sie in einer Funktion
GetBefehl() versteckt :-) Durch den vorgeschlagenen enum hat er einfach
nur ein zusätzliches Element ins Spiel gebracht, welches bei Änderungen
nachgezogen werden muss.
Ich sags nochmal ausdrücklich:
Vergiss das mit der struct wieder.
Mach eine ganz stinknormale if/else-if Kette die mit strcmp den
richtigen Zweig raussucht.
befehl=strtok(string,trennzeichen);//String beim Trennzeichen (LEER) zerteilen
5
6
rprintfCRLF();//Ausgabe...
7
rprintf("Befehl: ");
8
rprintfStr(befehl);
9
rprintfCRLF();
10
// naechsten Abschnitt erstellen
11
wert=strtok(NULL,trennzeichen);//hier muss NULL stehen???
12
rprintf("Wert: ");
13
rprintfStr(wert);
14
rprintfCRLF();
15
puffer=0;
16
17
strcat(befehl,"\0");
18
strcat(wert,"\0");
19
20
21
22
f=0;
23
for(g=0;g<20;g++)//string wird gelöscht
24
string[g]=0;
25
26
27
}
28
29
puffer=0;//Variable puffer für RS232 leeren
30
31
32
strvergleich=strcmp(befehl,"USET");
33
rprintf("strvergleich: %d",strvergleich);
Hyperterm:
--------------------------
Befehl: USET
Wert: 5.00
strvergleich: -85
--------------------------
aba das läuft nicht, ich wäre jemandem dankbar wenn er mir vll eine
einfache funktion zeigen könnte wo der String anständig getrennt wird,
da das anscheinden der Fehler ist.
danke martin!!!!
Mach mal folgendes
rprintfCRLF(); //Ausgabe...
rprintf("Befehl: &");
rprintfStr(befehl);
rprintf("&");
um zu sehen, ob sich im Befehlsstring noch Leerzeichen verstecken.
Die AUsgabe muss sein
Befehl: &USET&
Zwischen den & und dem Buchstaben daneben darf kein Leereum sein, auch
kein Zeilenumbruch.
und schmeiss die
strcat( befehl, "\0" );
strcat( wert, "\0" );
raus. Die Strings sind schon 0-terminiert.
Ähm
for(g=0;g<20;g++) //string wird gelöscht
string[g] = 0;
das ist zu früh.
Du darfst den String hier noch nicht löschen.
befehl und wert sind Pointer in diesen String! Der wird noch gebraucht!
Kein Wunder, dass dir kein strcmp funktioniert.
hallo
genaue Eingabe: USET 5.00 [ENTER]
--------Hyperterm---------
Befehl: &USET&
Wert: 5.00
------------------------
also keine leerzeichen versteckt oder?
ich weis es nicht mehr :)
kann es nicht sein dass es mit dem *befehl was zu tun hat, das ist ein
Zeiger oder, aber ich die hab i ehrlichgesagt noch nie ganz begriffen.
danke
Hallo
sodala...
hier ist die funktion "remote", die ich bei UART-Interrupt aufrufe.
[c]
float spannung=0, strom=0, umess=0, imess=0, upwm=0, power;
char puffer=0;
char string[20];
char *wert, *befehl;
const char trennzeichen[] = " ";
void remote(void) //Fernsteuerung über RS-232
{
string[f] = puffer;
f = f+1;
rprintfStr(string);
if(puffer == 13) //Wenn puffer = RETURN/ENTER
dann...
{
// initialisieren und ersten Abschnitt erstellen
befehl = strtok(string, trennzeichen); //String beim
Trennzeichen (LEER) zerteilen
rprintf("Befehl: ");
rprintfStr(befehl);
rprintfCRLF();
// naechsten Abschnitt erstellen
wert = strtok(NULL, trennzeichen); //hier muss NULL
stehen???
rprintf("Wert: ");
rprintfStr(wert);
rprintfCRLF();
puffer = 0;
if (strcmp(befehl, "USET") == 0) //Befehl 1
{
spannung = atof(wert);
rprintf("Spannung-Soll = ");
rprintfFloat(5, spannung);
voltage = spannung * 100.0;
da_load(1, voltage); //chipselect (CS): 1 = Spannung;
value = Analogwert in Millivolt mV
_delay_ms(50);
}
else if (strcmp(befehl, "ISET") == 0)
{
}
else if (strcmp(befehl, "OUTPUT") == 0)
{
}
else if (strcmp(befehl, "DISPLAY") == 0)
{
}
else if (strcmp(befehl, "UOUT?") == 0)
{
}
else if (strcmp(befehl, "IOUT?") == 0)
{
}
else if (strcmp(befehl, "POUT?") == 0)
{
}
f=0;
for(g=0;g<20;g++) //string wird gelöscht
string[g] = 0;
}
puffer = 0; //Variable puffer für RS232
leeren
}
[\c]
aber leider funktioniert die atof() funktion nicht wie gewollt, der
compiler bringt mir folgende fehlermeldung:
\libc.a(cmpsf2.o): In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_eq_sf.o):(.t
ext+0x0): first defined here
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr51\li
bc.a(cmpsf2.o): In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_lt_sf.o):(.t
ext+0x0): first defined here
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr51\li
bc.a(cmpsf2.o): In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_le_sf.o):(.t
ext+0x0): first defined here
komisch!!
die atof funktion ist ja dafür geegnet oder.
ich will den String Wert, der ja eine Kommazahl ist, in eine Float-zahl
umwandeln.
vll weis jemand was
danke
martin!!!
aber leider funktioniert die atof() funktion nicht wie gewollt, der
compiler bringt mir folgende fehlermeldung:
\libc.a(cmpsf2.o): In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_eq_sf.o):(.t
ext+0x0):
first defined here
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr51\li
bc.a(cmpsf2.o):
In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_lt_sf.o):(.t
ext+0x0):
first defined here
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/../../../../avr/lib/avr51\li
bc.a(cmpsf2.o):
In function `__lesf2':
c:/winavr-20090313/bin/../lib/gcc/avr/4.3.2/avr51\libgcc.a(_le_sf.o):(.t
ext+0x0):
first defined here
komisch!!
die atof funktion ist ja dafür geegnet oder.
ich will den String Wert, der ja eine Kommazahl ist, in eine Float-zahl
umwandeln.
vll weis jemand was
danke
martin!!!
ICH HABE LEIDER EIN WEITERES PROBLEM.
der string "wert" soll auch z.b. ON/OFF annehmen können.
also mache ich wieder folgendes:
1
elseif(strcmp(befehl,"OUTPUT")==0)//Befehl 3
2
{
3
4
if(strcmp(wert,"ON")==0)
5
{rprintf("scharf");
6
led_rt_on;//LED 'Spannung ein' leuchtet
7
writetext("*",1,1,0,u,2);//Spannung-aus-Anzeige im Display
8
u_ein;//Transistor ein
9
}
10
11
if(strcmp(wert,"OFF")==0)
12
{led_rt_off;//LED 'Spannung ein' leuchtet
13
writetext(" ",1,1,0,u,2);//Spannung-aus-Anzeige im Display
14
u_aus;//Transistor ein};
15
}
16
}
leider geht es nur wenn ich ins Hyperterminal schreibe "OUTPUT ON "
-> d.h. ich muss das LEERZEICHEN am schluss irgendwie weglöschen, hört
sich einfach an aber ich kanns nicht
bitte karl-heinz ich brauche dich ein letztes mal
danke!!!!!!!!!!
Was passiert alles, wenn ein Return reinkommt?
Nun, du hängst den Return genauso an den String an wie jedes andere
Zeichen und dann kommt er dir bei der Auswertung in die Quere :-)
Der erste Schritt besteht immer darin, dass man überprüft, ob das was
reinkommt auch dem entspricht was man erwartet. Dazu ist es sinnvoll,
wenn du Kontrollausdrucke machst. Aber du musst das richtig machen: Vor
und hinter den String kommt irgendein Sonderzeichen, dass normalerweise
nicht im Text vorkommen wird (wenn es vorkommt ist das auch kein
Beinbruch). Wichtig ist: Das du siehst, ob vor deinem Text ein
Leerzeichen, Tabulator oder sonst irgendein Zeichen sitzt, welches in
einem Leerraum ausartet. Den übersieht man nämlich sehr gerne, wenn man
nicht weiß, wo der Text anfängt. Dassselbe gilt auch für das Stringende:
Mach dir ein Sonderzeichen hin, so dass du siehst, ob hinter deinem Text
noch Leerzeichen, Tabulator oder, besonders gemein, Zeilenumbrüche
kommen. Das Begrenzungszeichen muss direkt an deinen Text anschliessen!
Wenn nicht, dann hat sich da ein nicht sichtbares Zeichen
eingeschmuggelt.
Das hier
1
rprintfStr(string);
ist ein netter Versuch. Aber dich interessieren eben auch die nicht
sichtbaren Zeichen
1
rprintfStr("&");
2
rprintfStr(string);
3
rprintfStr("&");
jetzt hast du dir eine Möglichkeit geschaffen, wie du auch solche
Zeichen sehen kannst.
Wenn die Ausgabe an dieser STelle lautet
&OUTPUT ON
&
dann hat sich da ein Zeilenvorschub eingeschlichen :-) Die Ausagbe muss
so aussehen
&OUTPUT ON&
Und ich denke genau das ist dein Problem.
Verändere das Zeichensammeln, so dass der \n (der Return) nicht im
String landet.
1
voidremote(void)
2
{
3
if(puffer!='\n'){// bei einem Return beginnt die Auswertung
4
// solange kein Return kommt, werden die Zeichen
5
// einfach nur gesammelt
6
7
string[f]=puffer;
8
f++;
9
return;
10
}
11
12
// Ein Return ist eingetroffen. Damit ist der String vollständig
13
string[f]='\0';// erst mal einen sauberen C-String daraus machen
14
15
rprintfStr("&");// zu Kontrollzwecken ausgeben
16
rprintfStr(string);
17
rprintfStr("&");
18
19
20
befehl=strtok(string," \t");// dann zerteilen
21
wert=strtok(NULL," \t");
22
23
if(strcmp(befehl,"USET")==0)
24
{
25
....
26
}
27
28
...
29
elseif(strcmp(befehl,"OUTPUT")==0)
30
{
31
if(strcmp(wert,"ON")==0)
32
{
33
rprintf("scharf");
34
led_rt_on;//LED 'Spannung ein' leuchtet
35
writetext("*",1,1,0,u,2);//Spannung-aus-Anzeige im Display
36
u_ein;//Transistor ein
37
}
38
39
if(strcmp(wert,"OFF")==0)
40
{
41
led_rt_off;//LED 'Spannung ein' leuchtet
42
writetext(" ",1,1,0,u,2);//Spannung-aus-Anzeige im Display