Ich will ein String z.B "99|11|01|00" auf jede Stelle zwischen den "|"
aufbröseln. Dieses versuche ich mit dem Code (s.unten), die Ausgabe auf
UART ist jedoch nur : Stelle 1:99
PS. Das -----Jippie---- wird auf der UART ausgegeben!
Warum kommt Stelle 2.4 nicht zum Vorschein?
Wahrscheinlich weil dein printf() nicht an der erwarteten Stelle
ausgibt. Das erste Ergebnis gibtst du mit usart_write() aus, die
Nachfolger mit printf(). An der Benutzung des strtok() sehe ich auf den
oberflächlichen Blick nix kritisches
(http://www.elook.org/programming/c/strtok.html)
Krapao schrieb:> Das erste Ergebnis gibtst du mit usart_write() aus, die Nachfolger mit> printf().
Das wird es wohl gewesen sein. Der Rest ist in Ordnung.
Yalu X. schrieb:> Krapao schrieb:>> Das erste Ergebnis gibtst du mit usart_write() aus, die Nachfolger mit>> printf().>> Das wird es wohl gewesen sein. Der Rest ist in Ordnung.
Einfach zu unkonzentriert ... und kopiert ... sorry für die doofe,
unnützige Frage! Habe es zwar noch nicht ausprobiert, aber das wird's
sein.
Matthias Lipinsky schrieb:> Ich hab sowas ähnliches letztens auf Arbeit programmiert. Auf das> Problem hier würde ich das etwa so machen:>> [c]>> //-----------------------------------------------> uint8_t sString[] = "99|54|34|55";> uint8_t au8Value[4];>> void parse void ( uint8_t* sChar, uint8_t* sValue, uint8_t u8Len )> {> uint8_t u8State = 0;> uint8_t u8StateLast = 255;> uint8_t u8Cnt = 0;> //-----------------------------------------------------------
Danke, das kann ich gut gebrauchen.
Ich bin gerade dabei...
Ich versuch gerade mein Code abzuändern damit ich die gesendeten
Stringstücke in ein Char- oder Int-Array packe.
Aber das klappt noch nicht. Siehst Du da irgend ein Bock drin?
Leider bin ich zu doof um dein Code komplett zu verstehen, da tu ich
mich dann immer schwer damit den einfach zu verwenden, auch wenn er
klappen würde...
Markus P. schrieb:> usart_write("--Stelle 1: %s--\n\r",pToken);> ReceiveSerial[1] = atoi(pToken);> usart_write_char(ReceiveSerial[1]);
Ich kenn zwar deine FUnktionen nicht, aber ich denke nicht, dass du hier
usart_write_char benutzen willst.
Du hast an dieser Stelle keine Character mehr (und auch keine Strings),
sondern bereits Zahlen!
Ergo wirst du eine Funktion benutzen wollen, die auch eine Zahl ausgeben
kann. Zb so was:
1
voidusart_write_int(intnumber)
2
{
3
charbuffer[10];
4
itoa(number,buffer,10);
5
uart_write(buffer);
6
}
PS: du tust dir unter UMständen leichter, wenn du es dir zur Regel
machst, dass du den Datentyp char ausschliesslich und nur für Character
benutzt. Also alles was mit Texten (aka. Strings) bzw. Einzelzeichen wie
sie in Texten vorkommen reservierst.
Wenn du einen kleinen Integer meinst, also eine Variable die Zahlen
speichert, so wie in 5 Äpfel oder 28 Grad Celsius, dann benutzt du
ausschliesslich uint8_t, int8_t (oder uint16_t oder int16_t): Dann
erinnert dich der Datentyp immer daran, womitr du es zu tun hast: Mit
Zeichen ('a', 'b', c' aber auch '0', '1', ...) oder mit kleinen Zahlen
(5, 8, 7). Es hilft auch, wenn du Variablen danach benennst, wozu sie
dienen, welchen Wert sie enthalten. ReceiveSerial ist da nicht sehr
hilfreich. Der Name erzählt dir nichts.
PS: strtok ist hier ziemlich kompliziert einzusetzen. Matthias hat dir
schon gezeigt, wie das einfacher geht. Es ist nicht immer die einfachste
Variante einen String erst in Einzelteile aufzusplitten und dann mit den
Einzelteilen etwas zu machen. In deinem Fall, wenn es sich nur um Zahlen
handelt, die aus dem kompletten String extrahierst und in ein Array
ablegst, ist es einfacher, wenn man den String einfach ein Zeichen nach
dem nächsten durchgeht und entscheidet was mit diesem Zeichen zu machen
ist.
Entweder es ist ein digit (also '0' bis '9'), dann gehört es zur gerade
geparsten Zahl dazu. Das ist aber leicht zu bewerkstelligen. Denn wie
wird aus der Zahl 64 und einer daran anzuhängenden 3 die Zahl 643?
Simpel. 64 * 10 macht 640 (damit hast du die ganze Zahl um 1 Stelle nach
links 'geschoben' und dann kannst du einfach die 3 dazuaddieren. Du
kriegst dann 643. Und wenn daran dann noch eine 8 drann soll, dann geht
das wieder nach dem gleichen Muster: 643*10 macht 6430, und da dann
noch die 8 dazuaddiert macht 6438. Schau dir nochmal Matthias Code an,
ob du die Operation dort findest.
Und dann kann in deinem Eingabestring noch das Zeichen | vorkommen. Das
ist aber leicht. Das schaltet einfach nur weiter in welches Arrayelement
die nächsten digits reinkommen.
>Leider bin ich zu doof um dein Code komplett zu verstehen, da tu ich>mich dann immer schwer damit den einfach zu verwenden, auch wenn er>klappen würde...
Versuche doch einfach meinen COde nachzuvollziehen. Du kannst ja hier
nachfragen.
Karl Heinz hat Dir ja schon paar Tipps gegeben.
Hi,
ich habe mir jetzt noch einmal deinen Code (Lippy) angeguckt und da ist
mir auch einiges klar geworden. Zumindest verstehe ich den Code wenn man
folgenden Dreher beseitigt:
Vorher:
1
case1:
2
u8StateLast=u8State;// <----
3
sValue++;
4
if(++u8Cnt==u8Len)return;
5
break;
Nachher:
1
case1:
2
u8State=u8StateLast;// <----
3
sValue++;
4
if(++u8Cnt==u8Len)return;
5
break;
Ist doch Richtig oder? Doch so ganz klappt es dann auch noch nicht.
Ausgabe von "12|34|56|78" ist:
12
4
6
8
Bei folgendem Code:
1
voidusart_write_int(intdata)
2
{
3
charBufferchar[10];
4
5
itoa(data,Bufferchar,10);
6
usart_write_str(Bufferchar);
7
usart_write_str("\r\n");
8
9
}
Und das in der USART-Abfrage:
1
2
if(usart_status.usart_ready)
3
{
4
5
if(!strcmp(usart_rx_buffer,"99|11|01|00"))
6
{
7
usart_write("----Jipppieee----");
8
}
9
10
11
memset(au8Value,0,sizeof(au8Value));
12
parse(usart_rx_buffer,au8Value,4);
13
14
15
// in au8Value sollten jetzt die Ziffern stehen.
16
17
usart_write_int(au8Value[0]);
18
usart_write_int(au8Value[1]);
19
usart_write_int(au8Value[2]);
20
usart_write_int(au8Value[3]);
21
22
23
usart_status.usart_ready=0;
24
25
}
Da mein "usart_rx_buffer" so deklariert ist (kein unsigned):
1
#define BUFFER_SIZE 50
2
charusart_rx_buffer[BUFFER_SIZE];
bekomme ich noch die Warnung:
main.c:1428: warning: pointer targets in passing argument 1 of 'parse'
differ in signedness.
Das kann doch eigentlich damit nichts zu tun haben, oder?
Stehe gerade bissel auffen Schlauch. Irgendwie jetzt einen zu viel in
der Case1:, finde den Bock nicht...
Markus P. schrieb:> Ausgabe von "12|34|56|78" ist:> 12> 4> 6> 8
Verständlich, wenn man sich den Code durchdenkt. Der läuft in case 0:
auf ein "|", dann wird der State = 1, Zeichenpointer wird erhöht, zeigt
nun auf die erste Ziffer, läuft im nächsten Durchgang aber erstmal in
den case 1: Block und erhöht danach wieder den Zeichenpointer, also wird
erst ab der zweitem Ziffer erfasst.
Würde das sChar++ an's Ende des Case 0: Blocks stellen.
Das find' ich unschön:
> switch ( u8State )> {> case 0:> if ( u8StateLast != u8State )
Unter case 0: muss u8State = 0 sein, sonst wär' man nicht dort, also
kann man gleich
if ( u8StateLast != 0 )
bzw.
if ( u8StateLast )
schreiben.
Wo kommt eigentlich der String her?
Anderes Programm (per UART) oder Mensch?
Grund: Wenn der String von einem anderen Programm kommt, kann man davon
ausgehen, dass ernicht fehlerhaft ist. Bei einer menschlichen Eingabe
muss man mehr Aufwand treiben um Fehler abzufangen.
Annahme: anderes Programm
So gesehen sehe ich nämlich den Vorteil der State-Machine da drinnen
noch nicht.
Der String darf dabei nicht leer sein und darf auch nicht mit einem |
aufhören (sonst ist die als Rückmeldung gelieferte Anzahl geparster
Argumente um 1 zu hoch). Bei einem Programm-generierten String ist das
kein Problem, bei einer menschlichen Eingabe ist das nicht akzeptabel.
>Ist doch Richtig oder?
Nein. War schon richtig, aber
>Doch so ganz klappt es dann auch noch nicht. Ausgabe von "12|34|56|78" ist:>12>4>6>8
Oh. Ja, ich seh es. Karl Heinz hat recht. Die State Maschine bringt hier
nix. Das ist zu einfach ;-)
Versuch mal das.
Ein Leerstring, bzw ein Enden mit | sollte kein Thema sein.
EDIT:
>Unter case 0: muss u8State = 0 sein, sonst wär' man nicht dort, also>kann man gleich>if ( u8StateLast != 0 )>bzw.>if ( u8StateLast )>schreiben.
Das ist schon richtig. Gilt aber nur für case 0. Die von mir gewählte
Schreibweise gilt für jeden case. So kann ich einfach CTRL+C/V machen.
Ohne die Konstante da anpassen zu müssen.
Beitrag "Re: Programm bzw. Ablaeufe steuern"
Matthias Lipinsky schrieb:> Das ist schon richtig. Gilt aber nur für case 0. Die von mir gewählte> Schreibweise gilt für jeden case. So kann ich einfach CTRL+C/V machen.
Da sparst ja bei 2 States enorm an Zeit :D
Eventuell im Code noch sValue mit 0 initialisieren ?
>Da sparst ja bei 2 States enorm an Zeit :D
Ja ;-) Aber wie gesagt, das Bsp war von ner Programmierung auf Arbeit.
DOrt war das PRoblem etwas größer, und die Schrittkette macht dort Sinn.
Deshalb hatte ich die hier einfach gelassen. Aber nicht nötig.
>Eventuell im Code noch sValue mit 0 initialisieren ?
So recht..?
Danke euch, jetzt sind mir auch die Zeiger wieder ein bissel näher
gekommen! Da tue ich mich immer noch schwer mit..
Was ich nur gemerkt habe ist dass void parse void (... Bei mir ein
Fehker auslöst. Ich habe nirgends was zum Thema gefunden. Void parse(...
wird richtig compiliert!
Und warum muss man hier denn nicht mit dem Zeiger arbeiten?
//-- weiter -------------------------------
sChar++;
>Was ich nur gemerkt habe ist dass void parse void (... Bei mir ein>Fehker auslöst.
Ja. Das ist mir noch nicht aufgefallen. Was hab ich denn da für einen
Mist getippt. So muss es heissen:
1
voidparse(...
2
{
3
..
>Und warum muss man hier denn nicht mit dem Zeiger arbeiten?> sChar++;
Tut man doch. Man schiebt den Zeiger ein Element weiter. Würde man
*sChar schreiben, würde man auf den Zeiger (als da wo der hinzeigt)
zugreifen.
main.c:1417: warning: pointer targets in passing argument 1 of 'parse' differ in signedness
Liegt ja an den:
1
#define BUFFER_SIZE 50
2
charusart_rx_buffer[BUFFER_SIZE];
wenn ich das nur Ändere zieht das einen Rattenschwanz hinter sich...
@ Karl-Heinz
>Wo kommt eigentlich der String her?>Anderes Programm (per UART) oder Mensch?
Das kommt vom anderen Programm (VB-Oberfläche)
Vielleicht könntest Du mir auch noch dieses Erklären:
1
//-- Trennzeichen ? -----------------------
2
if(*sChar=='|')
3
{
4
*++sValue=0;
5
if(++u8Cnt==u8Len)return;
6
}
Was passiert da mit dem: *++sValue = 0;
Also wenn das Trennzeichen kommt dann wird der Zeiger um Einen erhöht,
also eine Positon weiter und gleichzeitig auf Null geschriebn ?
Das verstehe ich nicht.
Vielleicht hilft einer...
>Was passiert da mit dem: *++sValue = 0;>Also wenn das Trennzeichen kommt dann wird der Zeiger um Einen erhöht,>also eine Positon weiter und gleichzeitig auf Null geschriebn ?>Das verstehe ich nicht.>Vielleicht hilft einer...
Jein. Gleichzeitig findet garnix statt. Zuerst wird das ++sValue
bearbeitet. Also der Zeiger namens sValue um ein Element
weitergeschoben. Anschließend folgt die Zuweisung *sValue = 0; Also wird
der Zeiger dereferenziert (auf den/die Speicher/zellen zugegriffen, wo
er hinzeigt) und da eine Null reingeschrieben.
>Einzig noch die Fehlermeldung
Das ist keine Fehlermeldung, sondern eine Warnung. Diese besagt, das der
Zeiger, den die Funktion parse als erstes Element erwartet ( ein:
uint8_t*, also ein Zeiger auf uint8_t), du aber beim Aufruf einen Zeiger
auf ein char mit gibst. Ich glaube das ging im Compiler einzustellen,
aber char ist wohl vorzeichenbehaftet (signedness).
Kleiner Tip. Wenn ich Strings darstellen will, deklariere ich die immer
so:
1
uint8_tsString[]...
Selbst für einen Puffer von Daten nehme ich meistens uint8_t, sofern
diese irgendwie Byteorientiert vorliegen.
Soweit klappt das jetzt.
Doch habe ich einige Probleme wenn ich die au8Value-Variable an eine ISR
übergebe die größer als [0] ist
1
memset(au8Value,0,sizeof(au8Value));
2
parse(usart_rx_buffer,au8Value,4);
3
4
5
// in au8Value sollten jetzt die Ziffern stehen.
6
7
usart_write_int(au8Value[0]);
8
usart_write_int(au8Value[1]);
9
usart_write_int(au8Value[2]);
10
usart_write_int(au8Value[3]);
11
12
u8_Uebergabe=au8Value[0];
Bei au8Value[0] funktioniert die Übergabe am die ISR einwandfrei. Wenn
ich jedoch [1],[2] oder[3] nehme bleibt der yC hängen. Warum auch immer.
Die Ausgaben auf die USART sind alle Gleich...
Hier hab ich die main's.
Stand ist jetzt das der Triac, der in der ISR gezündet wird, einwandfrei
funktioniert wenn ich die
1
u8_Uebergabe=au8Value[0];
verwende.
Sobald ich aber
u8_Uebergabe = au8Value[1];
oder
u8_Uebergabe = au8Value[2];
oder
u8_Uebergabe = au8Value[3];
nehme funktioniert das Ganze evtl ein mal und dann hängt sich der yC
auf. Zu mindest geht dann auch nichts mehr über die USART.
Ich weiss nicht wo er da hängen könnte?
Vielleicht sieht es einer???