hallo zusammen, ich beschäftige mich momentan mit der seriellen schnittstelle. daten senden und empfangen bekomme ich auch schon hin (siehe code). was ich nun machen möchte ist, dass ich einen string von bestimmter größe empfange und diesen nachher bytweise weiterverarbeite. dazu möchte ich auch nur einen bestimmten buffer reservieren!(was ich im moment wohl mit dem unsigned string bufer(100] mache) danach möchte ich an meine bytes, sprich in jedem byte stecken infos. in der theorie bin ich der meinung, dass ich meinen string speicher, un dann byte für byte über einen pointer darauf zugreife. was ich mit einer switch case anweisung lösung machen könnte. allerdings hänge ich im moment noch bei der verwirklichung dieser geschichte. vllt. bin ich allerdings auch auf dem holzweg. muß ich evtl auch einen rx_counter einsetzen, um die größe zu überprüfen? und wäre die lösung getchar() besser, also zuerst das abholen der daten und dann das ganze weiter verarbeiten??
>unsigned string gibbet net! Dein String (unsigned char string[100]) muß global deklariert sein, weil man sonst nur in der ISR darauf zugreifen kann. In der ISR macht man dann nichts anderes als string[rx_counter++] = UDR; "rx_counter" ist die Index-Variable, die die neue Schreibposition in deinem Empfangspuffer und den belegten Platz im Puffer anzeigt. >//hier meine switch (help) >// case 1.... anweisung sollte man eher nicht in die ISR packen, ausser wenn das Programm nichts anderes machen soll (macht es zwar momentan nicht, aber schöner ist es, das ganze Zeug gleich in die main-while-Schleife zu packen. Sonst liegst du übrigens richtig... PS: Deine Shift-Taste scheint kaputt zu sein :-}
Hi Oli, vielleicht kannst Du mal Dein Lösungsansatz posten. Ich hab auch ne Switch-Case Anweisung mit der ich Strings auswerte, allerdings funktioniert das momentan auch nicht so gut. Evtl. hilft Dir auch http://www.cplusplus.com/ref/cstring/ weiter, da sind gute Beispiele bzgl. String- Be-/Verarbeitung.
Interessant wäre, wie die Strings aussehen; es muß ja Regeln zu deren Entstehung und Verarbeitung geben.
die strings sind binär codiert, d.h. byte für byte wird gesendet. im ersten byte steht die länge des strings und um welchen aufruf es sich handelt. in den nachfolgenden bytes stehen dann die informationen für den entsprechenden aufruf. ich bin unter anderem dabei, den code zu schreiben. wenn ich den hab, werde ich ihn auf jeden fall posten. aber vielen dank mal für den link und an den wm-rahul!
>ersten byte steht die länge des strings
Das ist doch schon mal eine wichtige Information:
In der ISR muß unterschieden, ob es sich um das "Startbyte" oder ein
anderes handelt. Das kann man i.d.R. dadurch, dass der Puffer-Pointer
noch auf das erste Element zeigt. Dann decodiert man die String-Länge
und merkt sie sich. Bei jedem eintreffenden Byte wird der Puffer-Pointer
um eins erhöht und mit der String-Soll-Länge verglichen. Ist die
Soll-Länge erreicht, wird ein Flag gesetzt, das das Hauptprogramm dazu
bringt, den String auszuwerten. Wenn das Hauptprogramm mit der
Bearbeitung fertig ist, wird der Pointer wieder zurückgesetzt. Dabei muß
man eigentlich nur beachten, dass während der Bearbeitung kein neuer
String eintreffen darf. Sonst muß man mit mehreren Puffern und Pointern
arbeiten...
Es würde ja reichen, wenn Du ein einzelnes Charakter über den UART an den µC schickst. Dann brauchst Du nur eine einzelne "char" variable, würdest das Zeichen speichern und in der Switch Anweisung abfragen.
so, hier mal die ersten überlegungen dazu. allerdings ist das ganze noch nicht ausgereift und auch noch nicht zu gebrauchen. wenngleich beim compillieren schon keine fehler mehr auftauchen, was aber nichts zu bedeuten hat. es sind auf jeden fall noch fehler drinnen, aber ich wollte das jetzt doch mal posten. bisher habe ich niczht viel drinnen, sprich ich möchte meine stringlänge vergleichen ist=soll. die länge kann allerdings variiern, deshalb <= wenn diese überschritten wird, gibts später nen fehler.(jetzt noch net) in meiner switch case werden die fälle bei meinem ersten byte untersucht. und dann auf lcd ausgegeben. allerdings sind die einzelnen fälle in bite 5-7 und die länge in 0-4 somit stimmt das auch noch nicht überein. allerdings ist das jetzt mal mein lösungsansatz, wie martin darum gebeten hatte.
>das ganze noch nicht ausgereift und auch noch nicht zu gebrauchen. Stimmt! Handelt es sich bei deinem Compiler wirklich um den avr-gcc? help(0) ruft doch eigentlich eine Funktion mit dem Namen "help" und dem Parameter "0" auf (zumindest wäre das in meinen Augen C-Standard). Könntest du vielleicht mal das Protokoll bzw. dessen Aufbau posten? >allerdings ist das jetzt mal mein lösungsansatz, wie martin darum >gebeten hatte. Ehrlich gesagt ist das eigentlich nur Mist...(meine subjektive Meinung) Übrigens finde ich es sehr anstrengend nur Kleinbuchstaben lesen zu müssen.
Ich versteh nichit ganz: >if(pstring == help(0)) Wieso sollte pstring Zeiger mit help(0) identisch sein? >case 001: help(0) == 0b001; help(0) wird ja dann wieder mit gleichem Inhalt überschrieben. Was bezweckst Du überhaupt mit der if- und Switch- Abfrage?
>>case 001: help(0) == 0b001;
Da wird nichts überschrieben, sondern ein Vergleich durchgeführt.
> Könntest du vielleicht mal das Protokoll bzw. dessen Aufbau posten?
Rahul hat recht.
Da sollte man mal loslegen.
Die Frage die sich mir stellt:
Wie ist das mit dem Protokoll? Hat man dir das aufs
Auge gedrückt, oder ist da noch Spielraum? Wenn das
noch änderbar ist, dann hätte ich da schon einige
Ideen, wie man das ganze wesentlich simpler hinkriegt
als mit deinen variabel langen Kommandos. Wenn das
Protokoll allerdings von einem externen Gerät stammt,
dann musst du das wohl so nehmen wies ist.
Dreh und Angelpunkt ist dann meistens zunächst mal einen
kompletten Datensatz aus dem Protokoll rauszuholen. Das
ermöglichen eigentlich so ziemlich alle Protokolle indem
sie ein spezielles Zeichen haben, welches das Ende eines
Datensatzes (also Kommando + Argumente) anzeigt. Wenns
sowas nicht gibt, wird die Sache meist haarig, da dir
ein einziger Übertragunsfehler an der richtigen Stelle
alles lahmlegt, bzw. es dann nicht mehr so einfach ist
die Synchronisierung zwischen Sender und Empfänger
auf Protokollebene herzustellen, wenn sich der Empfänger
in eine laufende Übertragung einklinkt.
Wie sähe denn ein geeignetes Protokoll aus? Wenn man nur ein paar Fälle zu überprüfen hätte, könnte man das auch ja so machen: while( 1 ) { buffer = uart_getc(); switch (buffer) { case 'F': uart_puts("Führe Frequenzmessung durch... "); //result = frequenzmessung(); //itoa(result, asciresult, 10); //uart_puts("Frequenz beträgt: "); uart_puts(asciresult); uart_puts(" kHz"); break; case 'A': uart_puts("Führe AD Wandlungen durch... "); ACSR |= (1 << ACIE); // Interrupt Freigeben für Analog Komparator break; case 'D': uart_puts("D wurde gedrückt\n"); break; case 'S': uart_puts("S wurde gedrückt\n"); break; } }
Oh sorry, falsch gepostet war ne Codeleiche, aber so ähnlich stelle ich mir das vor. Vorher natürlich den buffer als char anlegen. uart_putc() sendet ein Zeichen vom Uart uart_getc() empfängt ein Zeichen
@ Rahul: War ein Lösungsvorschlag wie man String/Zeichen empfangen und dann auswerten kann. Ok das Beispiel ist ein wenig aus dem Zusammenhang. Warum muss man die Länge des Befehls wissen? Das kommt ja stark auf das verwendete Protokoll und auf die Befehle die empfangen werden an. Wie und was in der Auswertung geschieht ist ja egal.
Also mein Compiler ist AVR GCC. > Ehrlich gesagt ist das eigentlich nur Mist...(meine subjektive Meinung) Hm, ist zwar hart, aber stimmt. Der String kommt von men externen Prog., ist also fest. Das Protokoll sieht vor, dass für case1 ein 4 byte großer String belegt ist, case2 - 23bytes, case3 - 4bytes, case4 - 23 bytes, case5 - 23 bytes, case6 - 15 bytes. Was ich will, ist, als erstes byte0 zu prüfen. Danach möchte ich erst mit den nächsten bytes weiter machen. werde erst mal schauen, dass ich dass auf Vordermann bringe, bevor ich das wieder poste.
Wenn es nur darum geht, auf einzelne Bytes zu reagieren, reicht die einfache Auswertung, wie du sie beschrieben hast. Es gibt aber auch Protokolle, die aus mehr als nur einem Zeichen bestehen (z.B. VISCA von Sony, Protocol 2000 von Kramer-Electronics). Bei VISCA werden maximal 16 Bytes übertragen und mit einem 0xFF das Ende markiert. Olis Protokoll sieht so aus, dass das erste Byte die Gesamtlänge und einen bestimmten Befehl enthält, der mit den nachfolgenden Bytes seine Parameter geliefert bekommt. Da hat dann je nach Befehl das einzelne Byte im Puffer eine andere Bedeutung. Parser arbeiten auch so - schliesslich ist es egal, ob der "Text" von der seriellen Schnittstelle oder aus einer Textdatei stammt. Zu deinem Beispiel: Wenn du jetzt auch noch einen ADC verwenden würdest und dieser mehr als nur einen Kanal besitzt, würdest du zu dessen Auswahl vermutlich zwei Bytes schicken: z.B "A0" für ADC-Messung, Kanal 0 oder "A1" für ADC-Messung, Kanal 1 usw. Mit dem ersten empfangenen Byte erkennst du, welche Messung durchgeführt werden soll. Mit dem drauffolgenden dann den Kanal. Wenn man die Länge eines Datenrahmens weiß (z.B. 4 Bytes beim Protocol 2000), kann man die UART-RXC-ISR ganz alleine ihren Job machen lassen, indem sie die Zeichen in einen Puffer schreibt. Sind nun alle 4 Zeichen eingetroffen, wird ein Flag gesetzt, dass dem Hauptprogramm einen vollständig empfangenen Datenrahmen signalisiert. Startbytes kann man auch über ein bestimmtes Muster erkennen bzw. sollten über ein bestimtes Muster erkennbar sein - notfalls als Hardware-Handshake.
>Das Protokoll sieht vor, dass für case1 ein 4 byte großer String belegt >ist,
case2 - 23bytes, case3 - 4bytes, case4 - 23 bytes, case5 - 23 bytes, >case6 - 15
bytes.
Jetzt wäre interessant, wie das byte 0 aussieht - also welche Funktionen
die einzelnen Bits haben.
Vielleicht könntest du auch einen Beispiel-Datenrahmen posten.
Das vorhergehende Posting wendet sich überwiegend an Martin...
Als Bsp: byte0: 0xCE = 11001110 bedeutet case 6, da bit 5-7 110 haben, die Länge ergibt sich aus den bites 0-4 1110 --> dies addiert ergibt den Wert von 14 Array-Elementen.
unsigend char buffer[32]; // maximal 32 Datenbytes unsigned char buffer_pointer = 0; // aktuelle Schreibposition für den Buffer unsigned char buffer_length = 0; // Anzahl der Zeichen im Puffer abhängig vom byte0 unsigend char Event=0; // Ereignis-Flag ISR(irgendwas mit RXC) { buffer[buffer_pointer] = UDR; if (buffer_pointer == 0) buffer_length = buffer[buff_pointer] & 0x1F; if (++buffer_pointer >= buffer_length) Event = 1; } void main(void) { . . . while(1) { while(!Event); switch (buffer[0] >> 5) // verschieben der 3 obersten Bits nach ganz unten { case 1 : { // bearbeite 4 Byte; break; } case 2 : { // bearbeite 23 Byte; break; } case 3 : { // bearbeite 4 Byte; break; } case 4 : { // bearbeite 23 Byte; break; } case 5 : { // bearbeite 23 Byte; break; } case 6 : { // bearbeite 15 Byte; break; } default:; } buff_pointer = 0; } } // Fertich...
Mir fiel noch auf, dass das System überbestimmt ist: Je nach Fall scheint die Anzahl der Bytes ja festgelegt zu sein, weswegen eigentlich keine Länge mit übertragen werden müsste...
In den 14: Ist da das Kommando schon mit drinnen oder ist das die Anzahl der noch folgenden Bytes? Egal. Notfalls musst du die Längenauswertung anpassen. Ich würde das in etwa so machen:
1 | volatile unsigned char Record[30]; // da passt dann auch das längste Kommando rein |
2 | unsigned char RecordIndex; |
3 | unsigned char RecordLen; |
4 | volatile unsigned char RecordReceived; |
5 | |
6 | |
7 | SIGNAL( SIG_UART_RECV ) // SIGNAL nehm ich nur weil du das auch genommen hast. |
8 | // Ev. Compiler mal auf die aktuelle Version upgraden
|
9 | {
|
10 | unsigned char c = UDR; |
11 | |
12 | if( RecordIndex == 0 ) { // war das erste Byte. Daraus mal die Länge des |
13 | // Datensatzes holen
|
14 | RecordReceived = FALSE; |
15 | RecordLen = c & 0x0F; |
16 | c = c >> 4; // Das Kommandonibbel nach unten schieben |
17 | // Sont hat man bei der Auswertung immer die
|
18 | // Längenangabe mit drinnen
|
19 | }
|
20 | |
21 | Record[RecordIndex++] = c; |
22 | |
23 | if( RecordIndex == RecordLen ) { |
24 | RecordIndex = 0; |
25 | RecordReceived = TRUE; |
26 | }
|
27 | }
|
28 | |
29 | |
30 | int main() |
31 | {
|
32 | |
33 | ....
|
34 | |
35 | |
36 | while( 1 ) { |
37 | |
38 | if( RecordReceived ) { |
39 | RecordReceived = FALSE; |
40 | |
41 | switch( Record[0] ) { |
42 | |
43 | case 0x01: |
44 | // Kommando 1 abarbeiten
|
45 | // In Record[1] bis Record[n] steht alles weitere
|
46 | break; |
47 | |
48 | case 0x02: |
49 | // Kommando 2 abarbeiten
|
50 | // In Record[1] bis Record[n] steht alles weitere
|
51 | break; |
52 | |
53 | }
|
54 | }
|
55 | }
|
56 | }
|
@Karl-Heinz: Die Länge besteht aus 5 Bits, weil sonst keine 23 Bytes übertragen werden könnten.
Da bin ich verdammt noch mal wirklich auf dem Holzweg gewesen. Aber ist ja auch noch kein Meister vom Himmel gefallen.
>Aber ist ja auch noch kein Meister vom Himmel gefallen.
Aber zumindest die Treppe...
> Karl-Heinz: Die Länge besteht aus 5 Bits, weil sonst keine > 23 Bytes übertragen werden könnten. Ja, ja, hast ja recht. > die Länge ergibt sich aus den bites 0-4 1110 Ich setz mich jetzt hin und schreib Hundert mal: 0 bis 4, das sind 5 Bits, nicht 4! #include <stdio.h> int main() { int i; for( i = 0; i < 100; ++i ) printf( "0 bis 4, das sind 5 Bits, nicht 4!\n" ); return 0; } :-)
>> die Länge ergibt sich aus den bites 0-4 1110 > ... ich hab die erste 0 vergessen, was allerdings doch noch unter Flüchtiggkeitsfehler gehen dürfte, da weiter oben: >>0xCE = 11001110 steht. ;-)
@ Rahul: Jo danke für die Erklärung! @ Rahul & Karl Heinz: Sagt mal ist das Zufall dass Ihr beide die gleiche Lösung gepostet habt? Oder gibts da nicht so viele Möglichkeiten das Problem zu lösen?
>Oder gibts da nicht so viele Möglichkeiten das Problem zu lösen?
Karl-Heinz sitzt mir gegenüber....
Nee, Quatsch.
Das ist ja eben das Schöne am Programmieren: Es gibt ein paar
Standard-Elemente, die man munter miteinander kombinieren kann. Da ist
die Wahrscheinlichkeit recht hoch, dass zwei Leute zum gleichen Ergebnis
kommen.
Man könnte die Sache vielleicht auch anders lösen. Mir (und Karl-Heinz)
fiel aber scheinbar nichts besseres ein.
Seh ich auch so. Auch in der Programmierung gibt es Standardelemente, so wie es im Maschinenbau auch Standardelemente gibt. Mit der Zeit hat jeder Programmierer einen Haufen derartiger Bausteine parat und abrufbereit im Kopf. Sowohl Dinge die sich bewährt haben als auch Dinge die sich nicht bewährt haben. Das ist meines Erachtens auch einer der wesentlichen Unterschiede zwischen einem Frischling und einem alten Hasen (nicht abwertend gemeint). Einem alten Hasen ist fast jede Situation schon mal untergekommen und wenn schon nicht genau dieselbe Situation dann doch etwas ähnliches. Ein alter Hase hat für so manche Problemstellung 2, 3 Lösungsmöglichkeiten parat, während ein Frischling noch darüber grübelt, was denn eigentlich das Problem ist. Aber erzähl das mal den Firmen, wenn du über 40 bist. Die sehen nur, dass sie um dein Gehalt 2 Frischlinge einstellen können. Dass du dafür mindestens 3 mal so schnell arbeiten kannst wie ein Frischling ignorieren sie.
Da muss ich dir zustimmen. Ich denke, dass ein erfahrener Progger schon längst viel weiter mit dem Projekt wäre, als ich das im Moment bin. Auf der anderen Seite muss ich auch froh sein, dass man mir die Chance überhaupt gibt, in diesem Bereich Erfahrungen zu sammeln, was heute auch nicht mehr selbstverständlich ist. Aber das ist nen anderes Thema für ein anderes Topic. Mein Problem ist ein anderes: void buffer_stop(void) { unsigned int x; unsigned char y; int w = 5; int z = 10; if(pbuffer == 2) //2 byte auswerten { y = buffer_stop; y = buffer[pbuffer] & 0x0F; //bits die ausgewertet werden sollen, eingrenzen } x = y/w - z; // x=x - z; //hier sprintf() } Leider wird meine Berechnung nicht durchgeführt und auf dem lcd ausgegeben. Da ist doch bestimmt wieder nen ganz simpler Fehler drinnen.
>Leider wird meine Berechnung nicht durchgeführt und auf dem lcd >ausgegeben. Die hier? >x = y/w - z; Dein Codefragment sollte so funktionieren (syntaktische scheint es richtig zu sein). Vielleicht solltest du mal ein paar Worte zum Problem niederschreiben. Und am besten auch mehr Code (das komplette Programm!) zur Verfügung stellen. >Da ist doch bestimmt wieder nen ganz simpler Fehler drinnen. versuch's mal mit "volatile" kann ich dazu nur sagen. ;-)
Beim compilieren bringt er mir folgende Meldung: ../uart.c: In function `buffer_stop': ../uart.c:120: warning: 'y' might be used uninitialized in this function was für mich aber nicht verständlich ist, da initialisiert. wenn ich die Formel umbaue, sprich: void buffer_stop(void) { unsigned int y; unsigned char x; int z = 50; if(pbuffer == 2) { //y = buffer_stop; x = buffer[pbuffer] & 0x0F; } y = 5*x+z; sprintf(x,"0x%02x %02i %02i ",buffer[2],buffer_stop, buffer[24], buffer); lcd_clrscr(); lcd_puts(x); } bringt er mir für x komische Felder auf dem Display und für y wird das ganze Display ausgemahlt! Warnmeldung hier: ../uart.c: In function `buffer_stop': ../uart.c:120: warning: 'x' might be used uninitialized in this function
Dass irgendwelche Variablen genauso heissen, wie einige Funktionen, stört dich nicht?
> ../uart.c: In function `buffer_stop': > ../uart.c:120: warning: 'y' might be used uninitialized in this function Ich geh mal davon aus, dass sich das auf deine ursprüngliche gepostete Version bezieht:
1 | void buffer_stop(void) |
2 | {
|
3 | unsigned int x; |
4 | unsigned char y; |
5 | int w = 5; |
6 | int z = 10; |
7 | |
8 | |
9 | if(pbuffer == 2) //2 byte auswerten |
10 | {
|
11 | y = buffer_stop; |
12 | y = buffer[pbuffer] & 0x0F; //bits die ausgewertet werden |
13 | sollen, eingrenzen |
14 | }
|
15 | |
16 | x = y/w - z; |
17 | // x=x - z;
|
18 | |
19 | //hier sprintf()
|
20 | }
|
Beantworte doch mal schnell eine Frage: Welchen Wert hat denn y, wenn pbuffer nicht den Wert 2 hat? Selbiges hier
1 | void buffer_stop(void) |
2 | {
|
3 | unsigned int y; |
4 | unsigned char x; |
5 | int z = 50; |
6 | |
7 | |
8 | if(pbuffer == 2) |
9 | {
|
10 | //y = buffer_stop;
|
11 | x = buffer[pbuffer] & 0x0F; |
12 | }
|
13 | |
14 | y = 5*x+z; |
15 | |
16 | |
17 | sprintf(x,"0x%02x %02i %02i ",buffer[2],buffer_stop, buffer[24], |
18 | buffer); |
19 | lcd_clrscr(); |
20 | lcd_puts(x); |
21 | }
|
> ../uart.c: In function `buffer_stop': > ../uart.c:120: warning: 'x' might be used uninitialized in this function Welchen Wert hat den x, wenn pbuffer nicht 2 ist? > bringt er mir für x komische Felder auf dem Display und für y wird das > ganze Display ausgemahlt! Sorry. Aber dieser Satz ergibt keinen Sinn. Ausserdem: Die Funktion heisst 'buffer_stop. D.h. du kannst hier sprintf(x,"0x%02x %02i %02i ",buffer[2],buffer_stop, buffer[24], *********** keine Variable haben, die den gleichen Namen hat. Nun ja, technisch gesehen kannst du schon, nur passiert hier was völlig anderes als du glaubst. Ausserdem: unsigned char x; das heist: x hat Platz für genau 1 Zeichen! Nicht mehr! Wie bitte soll die komplette Ausgabe von sprintf, die ja sicherlich länger als 1 Zeichen ist, denn in x hineinpassen? Was du brauchst ist ein char-Feld. Strings werden in C in char Felder abgespeichert und es obliegt deiner Verantwortung als Programmierer, dass dieses Array auch gross genug ist, sodass der String auch hineinpasst. sprintf(x,"0x%02x %02i %02i ", Das sind 2 Zeichen für die erste Hex Zahl, 1 für das erste Leerzeichen, 2 Zeichen für die nächste Zahl, wieder 1 Leerzeichen, nochmal 2 Zeichen und noch 1 Leerzeichen. Dazu kommt dann noch 1 Zeichen, das für Strings obligatorisch ist, nämlich das abschliessende '\0' Zeichen, dass jeden String abschliesst. Wir haben also: 2 + 1 + 2 + 1 + 2 + 1 + 1 = 10 Zeichen. Also muss x ein Array mit einer Mindestlänge von 10 sein: char x[10]; Bei solchen Sachen ist es aber gut, dass etwas größer zu machen. Irgendwann veränderst du nämlich die Formatierung und mit der neuen Formatierung passen die 10 dann nicht mehr -> du hast wieder den gleichen Fehler. Also, die Devise heist: nicht kleckern, klotzen! char x[20];
Habs jetzt erst gesehen. Du benutzt x für 2 verschiedene Sachen. Einmal hier x = buffer[pbuffer] & 0x0F; und y = 5*x+z; Da wird x offensichtlich als Zwischenspeicher für irgend eine Auswertung benutzt. Und hier: sprintf( x, Da wird x benutzt um das Stringergebnis vom sprintf aufzunehmen. Die Ausführung oben bezieht sich nur auf letztere Verwendung. Da aber eine Variable nicht gleichzeitig in Array und kein Array sein kann, ist es wohl am einfachsten, du nimmst für letztere Verwendung eine neue Variable, die dann ein Array sein muss. Sag mal: Hat dein Compiler da gar nichts dazu gesagt? Einen unsigned char als erstes Argument an sprintf zu verwenden, dass sollte eigentlich jeder Wald und Wiesen C Compiler als Fehler markieren.
>Welchen Wert hat denn y, wenn pbuffer nicht den Wert 2 hat?
Ist das nicht so, dass wenn ich die Variable nicht deklariere,
automatisch der Wert 0 zugeordnet wird?
nunja, wenn ich char x[20]; einbaue, was ich ja auch verstehe, dann
möchte das mein compiler nicht machen:
../uart.c:127: error: incompatible types in assignment
../uart.c:130: error: invalid operands to binary *
es muß auch unsigned char x[20] heissen >Ist das nicht so, dass wenn ich die Variable nicht deklariere, >automatisch der Wert 0 zugeordnet wird? Du programmierst in C und nicht im Basic...(Nein, in der Variablen steht irgendwas drin!)
> sprintf(x,"0x%02x %02i %02i ", > > Das sind 2 Zeichen für die erste Hex Zahl, 1 für das erste Siehst du: Die ersten beiden Zeichen, nämlich das "0x" hab ich jetzt auch übersehen. Also wäre 10 schon zuwenig gewesen, die Minimallänge ist 12, nicht 10. Mit den 20 wäre ich auf der sicheren Seite gewesen. Das nennt man auch 'defensiv programmieren'. Sich selbst Spielraum für kleine Fehler zu lassen, so dass sich die nicht gleich verheerend auswirken.
> es muß auch unsigned char x[20] heissen
Nein. Muss es nicht.
Das Problem hab ich zu spät gesehen.
Er hat 2 verschiedene Verwendungen für x. Einmal
um einen tatsächlichen Wert zwischenzuspeichern.
Einmal um einen String aufzunehmen.
Scroll nochmal ein bischen hoch. Um 11:56 hab
ich dazu was geschrieben.
> Ist das nicht so, dass wenn ich die Variable nicht deklariere, > automatisch der Wert 0 zugeordnet wird? Denk logisch. Dann würde der Compiler wohl kaum sagen, dass die Variable uninitialisiert ist. Lokale Variablen werden nicht automatisch auf 0 initialisert. Globale Variablen schon. Du solltest dir etwas Literatur zulegen.
> ../uart.c: In function `buffer_stop': > ../uart.c:120: warning: 'y' might be used uninitialized in this function > was für mich aber nicht verständlich ist, da initialisiert. Regel römisch Eins: Ia Der Compiler hat immer Recht! Ib Wenn er einmal nicht Recht hat (was vorkommt), tritt automatisch Regel Ia in Kraft Regel Ib folgt sofort daraus, dass du nicht mit deinem Compiler diskutieren kannst. Wenn er sagt, etwas ist so, dann ist es so. Selbst wenn es falsch ist. Es gibt nichts was du kurzfristig dagagen tun kannst. Langfristig kannst du natürlich auf ein Update hoffen oder einen anderen Compiler nehmen.
ok, wieder was dazu gelernt! nun muss ich dieses neu erlangte Wissen nur noch umsetzen...!
>nun muss ich dieses neu erlangte Wissen nur noch umsetzen...!
... und dir noch ein C-Buch kaufen.
>nur mal langsam, das habe ich!
auch gelesen (und verstanden)?
würde ich sonst hier fragen stellen, wenn ich alles verstanden hätte?!
Dann kann dein Buch nicht gerade das gelbe vom Ei sein. Das, worum es in diesem Thread geht, ist ausnahmslos Grundlagenwissen.
ja, nun hab ich des auch gerafft! in diesem sinne merci mal!
Also zum Thema serielle Protokolle: Ich hab glaub ich die letzten 5 Jahre nix anderes gemacht... Ein serielles Protokoll sollte eine Start- und ein Stopzeichen haben, z.B. 0x5a für Start und 0xFF für Stop. Ein einfaches Protokoll zwischen nur 2 Teilnehmern könnte z.B. sein Byte 0 Startzeichen 0x5A Byte 1 Kommando (255 Kommandos möglich) Byte 2 Anzahl Datenbytes Byte 3...x Datenbytes Byte x+1 Checksumme (z.B. Summation aller Bytes, um es einfach zu machen) Byte x+2 Stopzeichen 0xFF also z.B. 0x5A 0x01 0x00 0x23 0x7D 0xFF --> Kommando 0x01 mit den Daten 0x00 0x23 empfangen wird das Protokoll über den Empfangsinterupt und in einem Ringbuffer gespeichert. Im Main Loop wird eine State Machine aufgerufen, die das Protokoll abarbeitet: state waitstartsign: if (neues zeichen im ringbuffer && zeichen=0x5a) timeoutstarten(); state=waitcmdsign; state waitcmd: if ( timeout ) state = waitstartsign; if (neues zeichen im ringbuffer && gültiges Kommando) state = waitdatalen; usw... wenn das Stopzeichen empfangen wurde, wird die checksumme überprüft und das Protokoll der nächst höheren Softwareschicht übergeben (kopiert). So mal ganz grob beschrieben wie es in der Industrie gemacht wird.
Hallo, nun brauche ich doch noch mal eure Hilfe. Ich möchte gerne Daten aus dem String speichern, damit ich die später weiter verarbeiten kann. Die länge vom String kann unterschiedlich sein. Wie komme ich die bytes nun abgespeichert? Die die max. Länge der Variable kann 23 sein. So wie ich das in meinem Kode gemacht habe, ist das nicht richtig und ich habe auch das Problem, dass ich nicht weiss, wie ich das ganze einfach machen kann?! Die Bytes möchte ich ab der vierten Stelle des Strings speichern. void kg_daten(void) //kg daten empfangen { unsigned int i; unsigned int a,b,c,d,e,f,g,h,u,j,t,l,m,n,o,p,q,r,s; for(i = 0; i <buffer_lengh; i++) { kgbuffer[i]=buffer[i+4]; if(pbuffer>=3) { kgbuffer[4] = a; kgbuffer[5] = b; kgbuffer[6] = c; kgbuffer[7] = d; kgbuffer[8] = e; kgbuffer[9] = f; kgbuffer[10] = g; kgbuffer[11] = h; kgbuffer[12] = u; kgbuffer[13] = j; kgbuffer[14] = t; kgbuffer[15] = l; kgbuffer[16] = m; kgbuffer[17] = n; kgbuffer[18] = o; kgbuffer[19] = p; kgbuffer[20] = q; kgbuffer[21] = r; kgbuffer[22] = s; kgbuffer[23] = t; } }
Sorry. Aber aus dem bisher Geschilderten werde ich nicht schlau. Die Code-Analyse des geposteten Abschnitts bringt mich auch nicht weiter.
Also ich hbae einen String der unterschiedlich lang ist. Ab dem vierten byte möchte ich die Daten byte für byte speichern, wenn vorhanden. In der for Schleife möchte ich i hochzählen lassen und vergleiche i mit der Stringlänge. Bei kgbuffer[i] = buffer[i+4]; weise ich die Werte vom buffer, wo der String ist zu i+4 bedeutet, dass ich das vierte byte haben möchte. Mein Problem ist, dass ich nun die bytes von 5,6,....,22,23 abseichern möchte. Und wenn der string nur 7 byte gross ist, dann soll er nur bis 7 speichern. Ich habe auch schon überlegt, ein dynamischen Speicher zu benutzen, was aber in meinen Augen keinen Sinn macht, da ich 23 Byte maximal brauche und diesen einfach festsetze. Somit möchte ich einfach die empfangenen bytes speichern.
> Also ich hbae einen String der unterschiedlich lang ist. Ein einzelnes Ding kann nicht "unterschiedlich" sein. > Ab dem vierten byte möchte ich die Daten byte für byte speichern, wenn > vorhanden. In der for Schleife möchte ich i hochzählen lassen und > vergleiche i mit der Stringlänge. > Bei kgbuffer[i] = buffer[i+4]; weise ich die Werte vom buffer, wo der > String ist zu i+4 bedeutet, dass ich das vierte byte haben möchte. Mein > Problem ist, dass ich nun die bytes von 5,6,....,22,23 abseichern > möchte. Und wenn der string nur 7 byte gross ist, dann soll er nur bis > 7 speichern. Das machst du doch eigentlich schon mit der for-Schleife und dem kgbuffer[i] = buffer[i+4];. Wozu ist jetzt der Rest da? Was ist pbuffer? Warum versuchst du, die gerade aus buffer nach kgbuffer kopirten Werte danach gleich wieder zu überschreiben?
Ich hab dich immer noch nicht. Was ist kgbuffer? Welchen Zweck erfüllt der? > Also ich hbae einen String der unterschiedlich lang ist. OK. Ein String. Also '\0' terminiert? In welchem Array ist dieser String gespeichert? Ist der in buffer? > Ab dem vierten byte möchte ich die Daten byte für byte speichern, > wenn vorhanden Wo möchtest du die speichern? In kgbuffer? Auf wen bezieht sich das 'vierte Byte'. Auf das Original, also buffer, oder auf das Ziel, also kgbuffer? In deinem Code da oben kommen viele variablen a, b, c, d, etc vor. Was hat es mit denen auf sich? Bis jetzt versteh ich eigentlich nur, dass du möchtest: for( i = 0; i < buffer_length; ++i ) kgbuffer[i] = buffer[i+4]; wenn der String in buffer tatsächlich 0-terminiert ist, dann könnte man das einfacher schreiben als: strcpy( kgbuffer, buffer + 4 ); Aber ich komm ums Verrecken nicht drauf, was du mit a, b, c, d, etc. vor hast. Ev. würde ein kleines Schaubild weiterhelfen.
Die ganzen Variablen habe ich benutzt, um vom String byte für byte abzuspeichern. Von dort aus möchte ich dann jedes byte weiter verarbeiten. Aber wahrscheinlich geht das ganze eben viel einfacher. Leider komme ich im Moment nicht drauf, wie! String --> ab Byte 4 speichern: buffer[4] = a; buffer[5] = b; ... Mit diesen Variablen bezwecke ich, dass dann meine bytes drinnen sind. Kgbuffer belege ich mit buffer[i+4],und dort möchte ich die daten dann speichern. String is \o terminiert und wird in buffer abgespeichert.
Ich würde dir ja gerne helfen. Aber ich kann einfach nicht erraten, was dein Ziel sein soll und wie die Dinge zusammenhängen. Ich kann dir nur raten, mal dir ein Schaubild, aus dem ersichtlich ist, wie die Teile zusammenhängen und in welcher Reihenfolge welche Aktion gemacht werden soll. Das hier: > Die ganzen Variablen habe ich benutzt, um vom String byte für byte > abzuspeichern. Von dort aus möchte ich dann jedes byte weiter > verarbeiten. klingt jetzt eher wieder danach, als ob deine Bytes aus dem Buffer kommen und eigentlich auf die Variablen verteilt werden sollen. Das hier ist dein ursprünglicher Buffer buffer +---+---+---+---+---+---+---+- ... -+---+---+ | | | | | | | | | | | +---+---+---+---+---+---+---+- ... -+---+---+ Wieviele bytes darin belegt sind, steht in buffer_length Jetzt hast du noch einen 2. ten Buffer, nämlich kgbuffer kgbuffer +---+---+---+---+---+---+---+---+---+- ... -+---+---+ | | | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+- ... -+---+---+ Und nu? Wenn ich richtig rausgelesen habe, dann willst du von buffer, ab dem 4.ten Element, alles was noch dahinter im Buffer steht in kgbuffer ablegen. Also so: buffer +---+---+---+---+---+---+---+- ... -+---+---+ | | | | | o | o | o | | | | +---+---+---+---+-|-+-|-+-|-+- ... -+---+---+ | | | | kgbuffer | | | | +---------------+ | | | | +---------------+ | | | | +---------------+ | | | | +---------------+ | | | | .......... +-|-+-|-+-|-+-|-+---+---+---+---+---+- ... -+---+---+ | v | v | v | v | | | | | | | | | +---+---+---+---+---+---+---+---+---+- ... -+---+---+ > Mit diesen Variablen bezwecke ich, dass dann meine bytes drinnen sind Als gelernter Österreicher, sage ich da nur: No, na. Dieser Satz ist extrem nichtssagend. Dein Hauptproblem dürfte sein, dass du dir selbst nicht wirklich erklären kannst, was du eigentlich erreichen möchtest. Geschweige denn uns. Mal dir ein Bild. Füge Pfeile ein welche Aktion in welcher Reihenfolge passieren soll, welcher Wert wann wohin kopiert werden soll. Das hilft die Gedanken zu ordnen.
Genau so wie du es mit dem buffern gezeichnet hast meine ich das auch. Und genau so möchte ich meine Variablen dann abspeichern. Byte für byte in die unterschiedlichen Variablen. Wobei kgbuffer nicht unbedingt nötig ist, da ich eigentlich auch über buffer direkt darauf zugreifen könnte. meine überlegungen sind: void kg_daten(void) { unsigned int i = 0; unsigned char kg; for(i = 4; i <buffer_lengh; i++) { kg = buffer[i]; } if(kg > pbuffer) { lcd_clrscr(); lcd_puts("No Data"); } } nun funktioniert es.
> nun funktioniert es.
Wenn du das sagst.
Das Fragment das du gepostet hast, ist ziemlich
sinnfrei.
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.