ich bin novh relatine neu in C daher mal einen Frage.
Ich sende von einem Atmega8 daten zu einem anderen Atmega8 über die
uart,
die daten kommen auch an, mein Problem ist wie ich die daten
zusamensetze.
also wie ich den vergleich richtig mache leider funktioniert das nicht
so.
vielleicht kann mir von ihnen wer weiterhelfen
sensNr = inLx[0]*10 + inLx[1];
if ( sensNr == 1 )
{
}
........
if ( sensNr == 19 )
{
}
so ich habe nochmal etwas versucht,Die IF-Abfrage Funktioniert aber mit
der Ausgabe komme ich nicht weiter.
Es sollte eigendlich -1 bis -18 Ausgegeben werden ich erhalte aber nur
0.
vielleicht hat denn von ihnen jemand noch einen tipp .
Heiko schrieb:
Ich versteh das nicht. Das ist jetzt in 2 Monaten der dritte mit dem
mehr oder weniger gleichen Problem
> c = uart1_getc();>> if ( c & UART_NO_DATA )> {> //Keine Daten> //Mach was> }>> else> {
Soweit so gut. Mindestens 1 Zeichen ist da. 1 Zeichen ist garantiert,
aber keiner weiß ob es nur 1 Zeichen ist oder mehrere.
> inLx[ i ] = c;> i = 1;>> while( ( c = uart1_getc() ) != 60 && i < sizeof(inLx) )> {> inLx[ i++ ] = c;
Nein.
Ob du hier von uart1_getc() tatsächlich 1 Zeichen gekriegt hast oder
nicht, weißt du nicht. Hier kann uart1_getc() genauso UART_NO_DATA sein!
Es ist sogar anzunehmen, dass in der Mehrzahl der Fälle ein UART_NO_DATA
daherkommt, weil die Übertragung per UART für jedes Zeichen wesentlich
länger dauert, als die Verarbeitung eines Zeichens. Nur weil das
allererste Zeichen schon eingetroffen ist bedeutet das nicht, das ALLE
Zeichen schon da sind. Das ist wie 'berittener Bote' für einen Brief,
wobei jeder Reiter einen Buchstaben transportiert. Die Reiter brauchen
länger zum reiten als du zum Lesen.
Du musst nach JEDEM Aufruf von uart1_getc() die Frage stellen: Habe ich
ein Zeichen bekommen oder nicht? Und nicht nur beim ersten Aufruf!
Heiko schrieb:> Ist scheinbar beim kopieren hier verloren gegangen> Bei mir im code ist es drin
Dann zeig ihn doch mal her, den code. Den ganzen, bitte lesbar
formatiert, und wenn er mehr als 30 Zeilen umfasst, als Attachment. Und
bitte erst dann, wenn du das Teil sauber compilieren kannst (keine
Warnings mehr etc.).
Kurz und Gut -> Netiquette beachten.
Heiko schrieb:> nein nein> wenn ich mir den inLx ausgeben lasse sind alle zeichen da.
Aber nur, wenn du im Empfangscode vorher lange genug gewartet hast, bis
alles eingetroffen ist.
Korrekt ist dein Code deswegen trotzdem nicht.
> Mir gehts um die verarbeitung> der daten mit,>
1
>intmess=atoi(&inLx[2]);
2
>TWert[sensNr]=mess;
3
>
>> ich bekomme das Vorzeichen nicht angezeigt
Nur mal angenommen, der empfangene String stimmt tatsächlich.
Dann sieht er zb so aus.
"12+-58"
und du setzt atoi hier an
"12+-58"
^
+---- da ist inLx[2]
dh, du möchtest von atoi gerne haben, dass es den String "+-58"
auswertet. Das es da mit dem - nichts mehr anfangen kann, sollte jetzt
nicht wirklich verwundern. Was mich eher wundert ist, dass es da nicht
überhaupt verweigert hat.
Es ist immer eine gute Idee, wenn man Ärger mit einer Konvertierfunktion
hat, sich den String erst mal ausgeben zu lassen, den man konvertieren
lässt. Bei dir ist das dann eben entsprechendes:
uart_putc( '#' );
uart_puts( inLx );
uart_putc( '#' );
uart_puts( &inLx[2] );
uart_putc( '#' );
int mess = atoi( &inLx[2] );
TWert[sensNr ] = mess;
auf die Art kann man dann auch ganz einfach sehen, welchen String man
exakt an atoi verfüttert.
Hallo,
Lasse ich mir die Empfangenen Werte ausgeben sind sie Korrekt.
Mit der atoi zb.
int mess = atoi( &inLx[2] );
TWert[sensNr ] = mess;
denn in inLx[2] steht ja das vorzeichen drin,aber es kommt nur NULL als
Ausgabe.
mfg
1
//SENDER
2
charmsg[30];
3
uint8_ti;
4
uint8_tsens=5;
5
inttemp;
6
7
for(i=10;i<19;i++)
8
{
9
sprintf(msg,"%02d",sens);
10
uart_puts(msg);
11
12
temp=i;
13
temp*=-1;
14
sprintf(msg,"+%3d",temp);
15
uart_puts(msg);
16
uart_putc(60);
17
}
18
19
//EMPFÄNGER
20
charoutpuffer[20];
21
charinLx[32];
22
uint8_tsensNr=0;
23
uint8_ti;
24
signedintTWert[19];
25
26
uint16_tc;//Uart Peter Fleury
27
28
i=0;//Uart Peter Fleury
29
c=uart1_getc();
30
31
if(c&UART_NO_DATA)
32
{
33
//Keine Daten
34
//Mach was
35
}
36
37
else
38
{
39
inLx[i]=c;
40
i=1;
41
42
while((c=uart1_getc())!=60&&i<sizeof(inLx))
43
{
44
inLx[i++]=c;
45
}
46
inLx[i]='\0';
47
}
48
49
sensNr=(inLx[0]-'0')*10+(inLx[1]-'0');
50
51
//inLx[0] = sensNr Zehner zb.0
52
//inLx[1] = sensNr Einer zb.5 Währe für sensNr=5
53
//inLx[2] = Vorzeichen +oder -
54
//inLx[2] = Zehner
55
//inLx[4] = Einer
56
57
//Werte werden richtig dargestellt
58
uart_putc(inLx[0]);
59
uart_putc(inLx[1]);
60
uart_putc(inLx[2]);
61
uart_putc(inLx[3]);
62
uart_putc(inLx[4]);
63
64
65
//so bekomme ich nur Null als Ausgabe
66
intmess=atoi(&inLx[2]);
67
TWert[sensNr]=mess;
68
69
//so bekomme ich den Korregten wert als Ausgabe aber ohne Vorzeichen
Heiko schrieb:> Hallo,> Lasse ich mir die Empfangenen Werte ausgeben sind sie Korrekt.
Lass sie dir als Strings ausgeben!
Die können nicht korrekt sein. Nicht wenn du am Sender so wegschickst:
1
for(i=1;i<19;i++)
2
{
3
sens=i;
4
sprintf(msg,"%02d",sens);
5
uart_puts(msg);
6
7
temp=sens;
8
temp*=-1;
9
sprintf(msg,"+%3d",temp);
10
11
uart_putc(60);
12
}
Denn dein String, den du zu zerlegen versuchst, MUSS damit so
01+-01
aussehen.
Und wenn du atoi auf inLnx[2] ansetzt, dann ist das am '+' Zeichen und
nicht am '-'!
01+-01
^
|
|
| inLnx[2], das ist hier!
und gleich nach dem '+' kommt ein '-'. Und damit kann das keine
gültige Zahl mehr sein, die bei inLnx[2] beginnt. Denn keine Zahl
kann mit 2 hintereinanderstehenden Vorzeichen anfangen!
Stefan Ernst schrieb:> Das '+' steht auf der falschen Seite vom '%'.
Das war es.
Danke.
Karl Heinz Buchegger schrieb
> Du musst nach JEDEM Aufruf von uart1_getc() die Frage stellen: Habe ich> ein Zeichen bekommen oder nicht? Und nicht nur beim ersten Aufruf!
Wie müsste es denn richtig sein?.
Der EMPFÄNGER wird ja von der Mainloop Ständig aufgerufen.
mfg
Heiko schrieb:> Stefan Ernst schrieb:>> Das '+' steht auf der falschen Seite vom '%'.> Das war es.> Danke.>>> Karl Heinz Buchegger schrieb>> Du musst nach JEDEM Aufruf von uart1_getc() die Frage stellen: Habe ich>> ein Zeichen bekommen oder nicht? Und nicht nur beim ersten Aufruf!> Wie müsste es denn richtig sein?.
Wie schon gesagt:
Nach ausnahmslos JEDEM uart1_getc() muss eine Prüfung erfolgen, ob da
eventuell UART_NO_DATA geliefert wurde.
Auch hier:
while( ( c = uart1_getc() ) != 60 && i < sizeof(inLx) )
{
inLx[ i++ ] = c;
}
Du kannst dich nicht darauf verlassen, dass du hier ein Zeichen
bekommst.
Das Zeichen von uart1_getc() steht in c. Und damit musst du wieder Tests
machen, ehe feststeht, dass da ein Zeichen gekommen ist, welches du dann
auswerten kannst. Die while Schleife wird also anders aussehen müssen.
Sofern man nicht überhaupt die komplette Systematik ändert und nicht
aktiv auf das Eintreffen eines 60-er Bytes wartet:
Byte holen, sofern eines vorhanden ist
Ist eines vorhanden:
War es 60?
wenn ja, dann kann der String ausgewertet werden
wenn nein, dann wird das Zeichen an den String angehängt
Somit wartet die Funktion überhaupt nicht mehr, sondern holt sich ein
Zeichen von der UART (wenn eines da ist) und entscheidet, ob damit der
String vollständig geworden ist und ob es daher etwas (in Form der
Auswertung) zu tun gibt oder ob man das Zeichen einfach mal an den
String anhängt.
Tja. das ist halt immer das Problem mit Codeausschnitten. Man sieht so
schlecht, was noch alles schief gehen kann. Deine Code-Scnippets kann
ich auch x-verschiedene Arten kombinieren, die alle irgendwann in einem
Buffer Overflow münden.
Leider Funktioniert das Beispiel von P.Fleury bei mir nicht,
jedoch aber das Beispiel mit der While-Schleife.
Scheinbar bin ich nicht der einzige der damit seine Probleme hat,mit dem
Beispiel von P.Fleury
mfg
Heiko schrieb:> Leider Funktioniert das Beispiel von P.Fleury bei mir nicht,> jedoch aber das Beispiel mit der While-Schleife.
Tja. Wenn man die Fehlerabfrage weglässt, funktioniert alles immer
wunderbar. Bis man dann halt irgendwann mal drauf kommt, dass Daten
fehlen.
> Scheinbar bin ich nicht der einzige der damit seine Probleme hat,mit dem> Beispiel von P.Fleury
Och. Ich bitte dich. Bis jetzt hab ich noch kein 'Problem' mit der
Fleury Lib gesehen, welches nicht darauf zurückzuführen ist, dass der
Problemhaber nicht richtig programmieren kann.
Es ist nun mal ein Trugschluss, dass man nur fertige Libs nehmen muss
und alles wird gut.
Auf wie groß hast du eigentlich den Empfangsbuffer eingestellt?
Ist dir klar, dass du hier im Sender
1
for(i=1;i<19;i++)
2
{
3
sens=i;
4
sprintf(msg,"%02d",sens);
5
uart_puts(msg);
6
7
temp=sens;
8
temp*=-1;
9
sprintf(msg,"+%3d",temp);
10
11
uart_putc(60);
12
}
eine Menge Daten rauspustest, die auch mal zwischengespeichert werden
können müssen, wenn der Empfänger zu langsam mit der Abarbeitung ist. Zb
dadurch, dass er sich da mit atoi's und vor allen Dingen sprintf's
ausbremst?
>Auf wie groß hast du eigentlich den Empfangsbuffer eingestellt?
char inLx[100];
>Fleury Lib gesehen, welches nicht darauf zurückzuführen ist, dass der>Problemhaber nicht richtig programmieren kann.
Das mag schon stimmen
>Es ist nun mal ein Trugschluss, dass man nur fertige Libs nehmen muss>und alles wird gut.
Nein,Nein
Leider gibt es kein richtiges Beispiel wie mann es richtig Anwendet
Darum Fragte ich ja wie mann es richtig macht ,
leider klappt das bei mir nicht
Heiko schrieb:>>Auf wie groß hast du eigentlich den Empfangsbuffer eingestellt?> char inLx[100];
Nein.
Den von der Fleury UART-Lib.
Schau in die uart.h hinein. Da gibt es eine Einstellug für die
Buffergröße.
> Darum Fragte ich ja wie mann es richtig macht ,> leider klappt das bei mir nicht
Dann musst du endlich mal dein Programm zeigen und nicht immer nur
nichtssagende Ausschnitte. Und dazu sagen, was du eigentlich machen
willst, bzw. welche Überlegungen du zum Protokoll angestellt hast.
Ich nahme mal ein paar Dinge an.
Der Sender fordert mit einem Messagestring die Daten eines Sensors an.
Messagestrings werden grundsätzlich mit einem ';' abgeschlossen.
Dazu schickt er ein '?' gefolgt von der Sensornummer.
Will der eine µC also vom anderen die Daten des Sensors 15 haben, dann
schickt er den String "?15;". Will er die Daten vom Sensor 9 haben, dann
schickt er "?9;"
Der andere µC antwortet auf eine Anfrage, indem er einen Messagestring
zurückschickt, der mit einem '#' beginnt. Eine '#' Message besteht aus 2
Teilen: die Sensornummer und der Sensorwert. Beide Werte sind mit einem
',' veinander getrennt. Dieser µC kann also auf die Anforderung "?9;"
mit "#9,127" antworten, wenn der momentane Sensorwert des Sensors 9 sich
auf 127 beläuft. Die Sensornummer wird deswegen mit zurück geschickt,
damit die Gegenstelle immer eindeutig feststellen kann, zu welchem
Sensor ein bestimmter Wert gehört. Der jeweilige Empfänger bearbeitet
eine Message so schnell er kann. Es findet kein Handshake statt. Einige
Messages können zwischengespeichert werden, allerdings darf das auch
nicht missbraucht werden. Im Idealfall sendet der eine µC die
Anforderung für einen Sensorwert und wartet bis die Antwort eingetroffen
ist. Der µC darf auch in einem Rutsch die Sensorwerte für 5 oder 10
Sensoren abfragen, aus den Anworten kann er immer die eindeutige
ZUordnung machen, welcher Wert zu welchem Sensor gehört. Mehr aber
nicht, weil sonst Buffer-Overflows durch das fehlende Handshake drohen.
Der 'Empfänger' verfügt über diesen Code, der in regelmässigen
Zeitabständen aus der Hauptschleife heraus aufzurufen ist. Dabei gelten
die üblichen Gepflogenheiten, dass keine _delay_ms oder sonstige
Verzögerungen erlaubt sind.
Im folgenden sind beide Message-Funktionalitäten in einem Code
beisammen. Damit kann jeder der beiden µC beim jeweils anderen einen
Wert anfordern und mit der Antwort etwas anfangen.
1
...
2
charMessage[20];
3
uint8_tnextMsgChar;
4
5
//
6
// Bearbeitet ein Zeichen von der UART, wenn eines vorhanden ist
7
// Messages werden ausgewertet und gegebenenfalls eine Antwort
8
// generiert.
9
//
10
// Kommandos
11
// '?'<nr_s>';' Abfrage des Sensors <nr_s>
12
// '#'<nr_s>','<nr_w> Setzen des Sensorwertes <nr_s> auf den Wert <nr_w>
13
//
14
// Return:
15
// 0 kein Fehler
16
// 251 UART Frame Error
17
// 252 UART Overflow Error
18
// 253 UART Buffer Overfloe Error
19
// 254 illegal Command received
20
//
21
uint8_tprocessMessages()
22
{
23
charc=uart1_getc();
24
25
if(c&UART_NO_DATA)
26
return0;
27
28
if(c&UART_FRAME_ERROR)
29
return251;
30
31
if(c&UART_OVERRUN_ERROR)
32
return252;
33
34
if(c&UART_BUFFER_OVERFLOW)
35
return253;
36
37
/*
38
** Zeichen eingetroffen und kein Fehler
39
*/
40
41
// Message fertig?
42
if(c!=';'){
43
Message[nextMsgChar++]=c;
44
return0;
45
}
46
47
// eine Message ist fertig empfangen worden
48
// die jetzt auswerten
49
Message[nextMsgChar]='\0';// sicherheitshalber
50
nextMsgChar=0;
51
52
// Sensorabfrage
53
// Syntax: '?' sensorNr ';'
54
// Aktion: keine
55
// Antwort: '#' sensorNr ',' SensorWert ';'
56
// Spezial: Im Fehlerfall (ungültige Sensor Nummer) wird keine
57
// Antwort gesendet
58
//
59
if(Message[0]=='?'){
60
uint8_tsensorNr=atoi(&Message[1]);
61
if(sensorNr<sizeof(TWert)/sizeof(*TWert)){
62
charAnswer[10];
63
uart_putc('#');
64
uart_puts(itoa((int)sensorNr,Answer,10));
65
uart_putc(',');
66
uart_puts(itoa((int)TWert[sensorNr],Answer,10));
67
uart_putc(';');
68
}
69
}
70
71
// von der Gegenstelle ist ein Sensorwert gekommen
72
// Syntax: '#' sensorNr ',' sensorWert ';'
73
// Aktion: Sensorwert extrahieren und merken.
74
// Antwort: keine
75
// Spezial: Im Fehlerfall (ungültige Sensor Nummer) wird keine
Hallo,
In der Mainloop wird immer das getSensor(second) aufgerufen,(Im Timer
läuft eine Uhr mit). Bei jeder neuen Sekunde wird ein Messbefehl
gesendet zum Temperratur-Modul welches die Messung startet.
Anbei mal das Komplette Projekt vom sender
und vom Daten-Empfang.
Ich habe versucht Peters Beispiel umzusetzen aber da bekomme ich nur ein
Wert angezeigt.
>void getSensor(uint8_t ss, )
Gibt dir der Compiler dafür keine Warnung? Mach mal das Komma weg, die
Routine erwartet noch einen zweiten Parameter, ann sein daß da komische
Sachen passieren.
Und: Biste auch sicher daß deine Timer im Hintergrund kommt? Häng mal
als Herzschlagüberwachung ne LED in die ISR mit rein die alle Sekunde
oder so ein/ausgeschaltet wird, zB in der Form (LED hängt an PortC5,
diesen vorher noch auf Ausgang setzen) PORTC ^= (1 << PC5);