Forum: Mikrocontroller und Digitale Elektronik C String in 2 Strings


von Matze (Gast)


Lesenswert?

Hi,

ich habe genau dasselbe Problem wie du, ich bekomme Daten über den UART
die folgt aussehen:
0x70;0x11

möchte diese in 2 Strings teilen und zuweisen, also dann:
code1=0x70;
code2=0x11;

und diese dann grad weiterverwenden, z.B.

i2c_start(code1)  //i2c_start(0x70);
usw.

Ein Beispiel mit meinen Werten wäre natürlich sehr hilfreich:-)
auch zum nachvollziehen.

danke im vorraus

Matze

von ... .. (docean) Benutzerseite


Lesenswert?

Steht das ; immer an der selben Stelleß

Wenn ja dann..

string1[0]=input[0];
string1[1]=input[1];
[...]

string2[0]=input[4];
string2[1]=input[5];
[...]

dann noch atoi und schon hast du deine werte

von sven (Gast)


Lesenswert?

Wo werden denn Hex-Werte als "Klartext" über die UART übertragen? Hast 
Du die PC-seitige Software selber geschrieben?

von Maxxie (Gast)


Lesenswert?

strtok() suchst du.

Separiert Zeichengetrennte-Listen (z.B. wie in CSV) in einzelne Token 
also Elemente der Liste.

von Matze (Gast)


Lesenswert?

Im moment übertrage ich meinen "Code" über ein Hyperterminal

dort gebe ich ein: "0x70;0x11"

Das Programm zum senden des Codes wird noch erstellt!! Wollte aber 
zuerts dass C-Prog laufen lassen, dass ich weiß es funzt.

zu ... ... :(name?)

das heisst ich muss es Byteweise zuweisen

code[0]=adress[0];  //hier steht "0"  ??
code[1]=adress[1];  //hier steht "x"  ??
[...]

das verstehe ich, aber wie mache ich jetz aus adress[0] & adress[1]
eine var: char Adresse;  //wo drin steht "0x70" ??

Danke für eure Bemühungen, ich steh noch am Anfang mit dem Bearbeiten 
von Strings.....möcht es aber lernen:-)

von Karl H. (kbuchegg)


Lesenswert?

Matze schrieb:

> das heisst ich muss es Byteweise zuweisen

Kannst du machen.
Wenn sichergestellt ist, dass die dich interessierenden Daten immer an 
der gleichen Stelle stehen.
Da letztendlich ja das Senden von einem Programm übernommen wird, kann 
man wohl davon ausgehen, dass dem immer so ist.

Ein String wird in C ja ganz einfach in einem Array gespeichert. Also 
kannst du ganz normal über Arrayindizierung auf die Daten zugreifen.

> code[0]=adress[0];  //hier steht "0"  ??
> code[1]=adress[1];  //hier steht "x"  ??
> [...]
>
> das verstehe ich, aber wie mache ich jetz aus adress[0] & adress[1]
> eine var: char Adresse;  //wo drin steht "0x70" ??

Indem du dir aus dem 'String' den zugehörigen numerischen Wert 
berechnest.
atoi eignet sich in deinem Fall nicht, da du dein String Hex Zahlen 
repräsentiert. atoi geht nur für Dezimalzahlen.

Aber es ist nicht weiter schwer, sich eine Umwandlungsfunktion zu bauen, 
die einen 2 stelligen Hex-Wert-String in einen tatsächlichen Hex-Wert 
umwandelt.

von Peter (Gast)


Lesenswert?

das verstehe ich, aber wie mache ich jetz aus adress[0] & adress[1]
eine var: char Adresse;  //wo drin steht "0x70" ??

Was soll denn eine char Adresse sein? Es gibt ein char dort steht 
einzeichen drin. Das zeichen kann als Hex ( 0x70 ) oder als char 
dargestellt werden ('A') aber es ist immer ein char. eine Adresse ist 
wenn du char* verwendest - das willst du aber hier vermutlich nicht.

Wenn ich es richtig verstanden habe willst du aus einem String 0x71;0x11 
2 Chars mit einer Hex to int umwandlung machen.

char c1 = (string[2]-'0') << 8 + (string[3]-'0');
char c2 = (string[7]-'0') << 8 + (string[8]-'0');

(ist jetzt aber nicht getestet, soll nur das Prinzip zeigen!)

von Karl H. (kbuchegg)


Lesenswert?

Aber es ist nicht weiter schwer, sich eine Umwandlungsfunktion zu bauen,
die einen 2 stelligen Hex-Wert-String in einen tatsächlichen Hex-Wert
umwandelt.

Alles fängt damit an, dass man sich eine Funktion baut, die ein
einzelnes Hex-Digit in seinen binären Counter-Part umwandelt.
1
unsigned char HexDigit( char digit )
2
{
3
  if( digit >= '0' && digit <= '9' )
4
    return digit - '0';
5
6
  if( digit >= 'A' && digit <= 'F' )
7
    return digit + 10 - 'A';
8
9
  if( digit >= 'a' && digit <= 'f' )
10
    return digit + 10 - 'a';
11
12
  return '0';   // Fehler
13
}


Mit dieser Funktion bewaffnet, wandelt man dann 2 stellige 'Zahlen'
1
unsigned char HexNumber( char digit1, char digit2 )
2
{
3
  return HexDigit( digit1 ) * 16 + HexDigit( digit2 );
4
}

und benutzt die dann zb
1
  unsigned char addrNum =  HexNumber( adress[2], adess[3] );

Ab jetzt steht dem Aufwand Tür und Tor offen:
Das ganze umwandeln in eine Funktion, die einen String annimmt.
Dann soll die Funktion im String den Präfix "0x" erkennen und 
entscheiden, ob es sich um eine Hex-Zahl oder eine Dezimal-Zahl handelt 
und die jeweils richtige Umwandlung dafür hernehmen, etc. etc.

Wenn du aber nur Funktionalität brauchst, die eine 2-stellige Hex-Zahl 
von der Stringform in eine tatsächliche Zahl wandelt UND die Ziffern 
konstant im String immer an der gleichen Stelle stehen, dann bist du mit 
obigem schon gut dabei.

von Matze (Gast)


Lesenswert?

ok viell sollte ich mal einen kurzen Quellcode von mir reinsetzen:-)

bin grad etwas durcheinander:-)
aber schon mak tausend Dank dass die Hilfe hier so schnell geht und es 
Leute gibt die einem versuchen zu Helfen:-)

Quellcode::

   i2c_start(0x70);       // setze
   i2c_write(0xFF);        // schreibe
   i2c_stop();

   i2c_start(0x71);        // setze
   ret = i2c_readNak();
   i2c_stop();             // stoppe

hier möchte ich die Hexadressen die schreibe, Variabel machen, so dass 
jede adresse und Daten schreiben kann die ich vom PC zum µC sende.
d.h.
Ich möchte bei i2c_start das 0x70 variabel und i2c_write variabel 
machen.

wenn ich also sende(der code sieht immer gleich aus!!)
0xFA;0x4F

soll 0xFA in i2c_start geschrieben werden und
     0x4F in i2c_write geschrieben werden.

von Karl H. (kbuchegg)


Lesenswert?

Matze schrieb:

> wenn ich also sende(der code sieht immer gleich aus!!)
> 0xFA;0x4F
> soll 0xFA in i2c_start geschrieben werden und
>      0x4F in i2c_write geschrieben werden.

Du empfängst diesen String in einer String Variable

char Command[20];   <- da baut die die Empfangsroutine den String rein
                       wobei sichergestellt ist, dass der String immer
                       dem Muster 0xaa;0xbb genügt

                       Das ist eine wichtige Einschränkung!
                       Auch sollte der String auf Gültigkeit geprüft
                       werden!

                       Da der String aber immer gleich aussieht, weißt
                       du auch, wo die Hex-Ziffern im String sind:


   i2c_start( HexNumber( Command[2], Command[3] ) );       // setze
   i2c_write( HexNumber( Command[7], Command[8] ) );       // schreibe
   i2c_stop();


Wie gesagt: Wenn das von einem menschlichen Benutzer eingegeben werden 
muss, würde ich nicht so naiv annehmen, dass der String den Aufbauregeln 
entspricht. Da dein String aber von einem Programm erzeugt wird, kann 
man im Sender sicherstellen, dass dem so ist.

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:

>
1
>   return '0';   // Fehler
2
>

moep ;-)

von Karl H. (kbuchegg)


Lesenswert?

Peter Stegemann schrieb:
> Karl heinz Buchegger schrieb:
>
>>
1
>>   return '0';   // Fehler
2
>>
>
> moep ;-)

Danke für den Bugreport :-)

    return 0;

Wobei es im Fehlerfall sowieso fraglich ist, wie dann reagiert werden 
soll.

von Matze (Gast)


Lesenswert?

ok, so hatte ich mir es vorgestellt:-)

danke schön.

aber muss ich "HexNumber" nicht irgendwie deklarieren oder is das ne 
Funktion?? Brauch ich dann ev. ne Headerdatei dafür??

warum return 0; ??? und wo? am Ende meines Progs??

von Karl H. (kbuchegg)


Lesenswert?

Matze schrieb:
> ok, so hatte ich mir es vorgestellt:-)
>
> danke schön.
>
> aber muss ich "HexNumber" nicht irgendwie deklarieren oder is das ne
> Funktion?? Brauch ich dann ev. ne Headerdatei dafür??

Ähm. Das ist jetzt aber nicht dein Ernst.
Wenn dir diese Fragestellung Kopfzerbrechen macht, dann bist du noch 
nicht soweit um Produktionscode zu schreiben.

Oder hast du diese hier
Beitrag "Re: C String in 2 Strings"
nicht gesehen?

>
> warum return 0; ??? und wo? am Ende meines Progs??

Nein.
Am Ende der Funktion. Vergleich doch mal, was ich in der 'Urversion' im 
Fehlerfall für einen return in der Funktion HexDigit hatte.

von Matze (Gast)


Lesenswert?

ok danke!

Ne sorry die Frage war etwas voreilig, hab dann deine Antwort gesehen 
mit der Funktion. Und sorry, klar is es ne Funktion!!! War etwas 
zerstreut geradeeben.

Dann geb ich es mal kurz wieder ob ich die Funktion richtig verstanden 
hab.


unsigned char HexDigit( char digit )
{
  if( digit >= '0' && digit <= '9' )  wenn digit >=0 und <=9 dann gib 
mir
    return digit - '0';               digit -0 zurück!

  if( digit >= 'A' && digit <= 'F' )  wenn digit>=A und <=F ist gib mir
    return digit + 10 - 'A';          digit +10 - A zurück

  if( digit >= 'a' && digit <= 'f' )  dasselbe mit Kleinbuchstaben!
    return digit + 10 - 'a';

  return '0';   // Fehler
}

Nun noch:::

unsigned char HexNumber( char digit1, char digit2 ) /funktion mit 
parameter
{
  return HexDigit( digit1 ) * 16 + HexDigit( digit2 );
}
 eine frage noch!! Was wird hier gemacht? und warum?

von Karl H. (kbuchegg)


Lesenswert?

Matze schrieb:

>  eine frage noch!! Was wird hier gemacht? und warum?

HexDigit wandelt einen Character aus dem üblichen 'Hex-Vorrat' in sein 
numerisches Äquivalent. Ich empfehle das Studium einer ASCII Tabelle, in 
der für jedes Zeichen sein Code angegeben ist.
Und dann muss man nur noch wissen, dass man in C mit char genausogut 
rechnen kann. Wenn du '0' im C-Source Code hinschreibst, dann setzt der 
Compiler gleich mal den ASCII Code dafür ein.

Wenn ein char '5' enthält, dann steht da nicht wirklich '5' drinnen, 
sondern der entsprechende ASCII Code: 0x35
Und wenn man von 0x35 dann noch 0x30 (= der ASCII Code für '0') abzieht, 
bliebt 5 übrig.
Und so ergibt dann '5' - '0' das Ergebnis 5


HexNumber fügt die numerischen Äquivelente der einzelnen Digits zu einer 
Zahl zusammen.

Bleiben wir einfach mal im Dezimalsystem:
Wenn du 2 Zehner und 5 Einer hast, dann entspricht das der Zahl:
    2 * 10 + 5 = 25

Im Hex-System (oder in jedem andren Zahlensystem) ist das nicht anders. 
Nur ist hier die Basis des Zahlensystems nicht 10 sondern 16 (daher auch 
Hexadezimalsystem: System zur Basis 16)

von vlad (Gast)


Lesenswert?

mal ne ganz blöde frage:
warum den Code als HexText und nicht einfach als Binärdaten übertragen? 
da spart man sich den quatsch und schneller geht die Übertragung auch.

Wenn unbedingt hexText sein muss, dann lass doch wenigstens das '0x' und 
das ';' weg, dann parst sich das ganze einfacher:
ein char -> ein nibble

berechnung des Nibblewerts:
value = inputchar - '0'; // asciiwerte 0-9 in binär werte
if(value>9)
  value = inputchar - 'A' + 10;  // restliche werte

von Matze (Gast)


Lesenswert?

Ah ok,

super Erklärung!!! Jetzt hab ich verstanden!!
Es ist also eine Umrechnung sozusagen, dass man das erhält was man 
eingibt und nicht dass was der µC draus macht!! Also z.B. von 5 zu 0x35 
zu 5!!

habs grad mal ausprobiert und funktioniert super!!

danke an alle die geholfen haben und especially thanks to Karl heinz 
Buchegger!!!  Hast mir echt weitergeholfen!!
Jetzt muss ich es nur noch verinnerlichen, damit ich es nicht immer 
nachlesen muss;-)

MfG
Matze

von sven (Gast)


Lesenswert?

Womit die Frage, warum du die Daten nicht einfach binär überträgst, 
immer noch nicht geklärt ist.

von Karl H. (kbuchegg)


Lesenswert?

sven schrieb:
> Womit die Frage, warum du die Daten nicht einfach binär überträgst,
> immer noch nicht geklärt ist.

Aus einem seiner ersten Postings

> Im moment übertrage ich meinen "Code" über ein Hyperterminal
>
> dort gebe ich ein: "0x70;0x11"
>
> Das Programm zum senden des Codes wird noch erstellt!! Wollte aber
> zuerts dass C-Prog laufen lassen, dass ich weiß es funzt.

-> zum Testen ist ASCII gut genug.


@Matze
Vorsicht: Natürlich haben die Leute recht. Im Endausbau könnte man die 
Übertragung direkt binär durchführen, wenn ASCII ein Zeitproblem 
darstellt. Aber dann gut überlegen, wie du die Synchronisierung auf 
Adressbyte und Datenbyte hinkriegst.

von Matze (Gast)


Lesenswert?

Also ich finde die lösung mit dem ASCII ganz gut, Zeit ist kein Problem.
Kann es mal kurz erläutern:
Ich schicke einen Code 0x70;0x11
dieser wird per i2c gesendet
dadurch wird ein i2c Baustein angesprochen der mit den entsprechenden 
Ausgang(0x11) schaltet, dadurch wird ein relais geschaltet!
Das Relais schaltet wiederum einen Motor,LED,oder sonstiges.

Dann wird ein Test mit Multimeter oder visuell geschaut ob der Motor,LED 
geht und die Verbindung in Ordnung ist!
dann wird der "Test" beendet, kurz gewartet und die nächste 
LED,Motor,... geschaltet bis ich alle Komponenten die ich dran haben 
möchte getestet sind!

Ob ich nun 2s länger warten muss oder nicht, ist für diesen Zweck 
erstmal egal!! da ich die wartezeit in meinem "sendeprogramm" am PC 
einstelle.
Prinzip:

sende
warte
teste
warte
sende
warte
.
.
.



Klar ich könnte es auch binär machen, aber ich wollte mal etwas Neues 
probieren:-) Das hat ja auch ganz gut geklappt und was gelernt hab ich 
dabei auch.
Ich werde den Code, sobald er endgültige Form hat mal posten, sodass 
auch andere an dem Beispiel teilhaben können....

Mfg

von P. S. (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:

> Wobei es im Fehlerfall sowieso fraglich ist, wie dann reagiert werden
> soll.

Das ist die zentrale Frage beim Programmieren ueberhaupt ;-)

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
Noch kein Account? Hier anmelden.