hallo zusammen,
bin fast am verzweifeln, probiere schon seid 2 tagen an meinem problem
herum.
bekomme die char seriell aus dem ringpuffer, möchte sie dann aber als
string á 4 byte groß speichern. habe dafür schonmal das forum
durchsucht, aber noch keine passende lösung für mein problem
gefunden.möchte das es auch nur ein gültiger string wird wenn es
mindestens 4 byte groß ist, ansonsten schon verworfen wird. vom prinzip
ist mir das schon klar, aber ich weiß nicht wie ich es softwaremässig
umsetzen soll. meine programmiererfahrung ist leider auch relativ
gering.
geht das so das ich die 4 byte aus dem ringpuffer hole und dann wieder
in einen anderen buffer schreibe, und sie dort als kompletten string
heraus hole?
>bekomme die char seriell aus dem ringpuffer,
Welchem Ringpuffer?
>möchte das es auch nur ein gültiger string wird wenn es>mindestens 4 byte groß ist, ansonsten schon verworfen wird. vom prinzip>ist mir das schon klar, ...
Wohl eher nicht. Was soll wann und warum gültig sein, oder verworfen
werden?
Prinzipiell ist ein 4-Zeichen-String in C ein char-Array mit fünf
Werten: Den vier Zeichen, abschliessend eine Null. Also legts du dir
soch eine Array mit
char myString[5];
myString[5] = 0;
an, und füllst es dann mit den einzelnen Zeichen.
Oliver
> möchte das es auch nur ein gültiger string wird wenn es> mindestens 4 byte groß ist, ansonsten schon verworfen wird.
Wie erkennst du, dass es weniger Zeichen sind?
Wie sieht dein Protokoll aus?
Hast du ein Timeout?
den ringpuffer habe ich nicht mit hoch geladen, der ist in dewr uart.c
enthalten.
ich möchte die Zeichen von:
zeichen = ser_getc();
in ein char-array schreiben lassen, dabei soll das array 4 zeichen
enthalten. mit welcher routine könnte ich das machen?
timeout gibt es nicht, ich erhalten die daten über die rs232
schnittstelle (uart)
Du hast
http://www.mikrocontroller.net/articles/FAQ#Wie_funktioniert_String-Verarbeitung_in_C.3F
immer noch nicht gelesen oder nicht verstanden.
In C ist ein eine Variable, die einen String enthält immer ein
char-Array. Du hast kein char-Array. Sowohl zeichen als auch muster sind
bei dir einzelne char. Die wiederrum, werden mit einem gewöhnlichen ==
verglichen. Die str... Funktionen gelten nur für Strings!
Rene schrieb:
> den ringpuffer habe ich nicht mit hoch geladen, der ist in dewr uart.c> enthalten.> ich möchte die Zeichen von:>> zeichen = ser_getc();>> in ein char-array schreiben lassen, dabei soll das array 4 zeichen> enthalten. mit welcher routine könnte ich das machen?>> timeout gibt es nicht, ich erhalten die daten über die rs232> schnittstelle (uart)
Und wie entscheidest du dann, wann etwas verworfen werden soll?
empfang[0]=empfang[1];// aus "abcd" mal "bcdx" machen
27
empfang[1]=empfang[2];// wobei x das empfangene Zeichen ist
28
empfang[2]=empfang[3];
29
empfang[3]=zeichen;
30
31
32
if(strcmp(empfang,"toFF")==0)
33
PORTB=0xff;
34
elseif(strcmp(empfang,"to55")==0
35
PORTB=0x55;
36
}
37
}
38
39
return0;
40
}
Die Abfrage auf UCSRA &= (1<<UDRE) kommt mir allerdings seltsam vor.
Wenn deine UART Routinen wirklich einen Ringbuffer enthalten, muss es
eine andere Möglichkeit geben, um rauszufinden ob ein Zeichen
eingetroffen ist. UDRE wird dir da nicht weiterhelfen, weil die UART
Routinen sich das Zeichen bereits geschnappt haben, wenn der Ringbuffer
über Interrupt angekoppelt ist. Wovon ich eigentlich ausgehe, sonst
macht ein Ringbuffer keinen Sinn
Hallo nochmal,
danke erstmal für die Hilfe. Karlheinz ich habe mir das gestern
durchgelesen, nur hatte ich mich ein bisschen unklar ausgedrück. Habe
das Beispiel mal eingepflegt und auch mal probiert. Es funzt immer noch
nicht, die uart.c habe ich nun mal mit darangehangen. Kann da bitte
nochmal einer drüber schauen!? char habe ich mit 4 byte definiert. Ich
benutze für die Eingabe HTerm als Terminalprogramm.
> Es funzt immer noch> nicht
Dachte ich mir schon.
Der Test ob etwas im Ringbuffer vorliegt, ergibt so wie du ihn hast nie
wahr. Dein Hauptprogramm wird nie an den UART Registern ablesen können,
dass ein Zeichen eingetroffen ist.
Allerdings ist die ser_get eine wartende Funktion, dh. die wartet
sowieso, bis ein Zeichen vorliegt.
Mal davon abgesehen, dass das "&=" hier völlig fehl am Platz ist,
funktioniert das so sowieso nicht.
Wenn du ein "wenn Zeichen vorhanden" haben willst, musst du das auf der
Ebene "Ringpuffer" machen, nicht auf der Ebene "Hardware". Z.B. indem du
rbuffcnt auswertest, oder (sauberer) deinen Ringpuffer um eine
entsprechende Abfragefunktion erweiterst.
in uart_init() ist .... sagen wir mal .... gewagt!
Was, bitte, geht das die uart_init an, wann und wo ich global die
Interrupts freigeben will. Gar nichts!
Vielleicht muss ich nach der uart_init auch noch ein paar Timer
konfigurieren. Super, wenn ich dort mal einen Interrupt freigebe, und
der fängt dann sofort zu feuern an.
Das globale sei() nach den Initialisierungen ist Sache des
Hauptprogramms und wird erst vor der Hauptschleife gemacht!
1
intmain()
2
{
3
unsignedcharzeichen;
4
unsignedcharempfang[4];
5
6
7
PORTB=0xff;
8
DDRB=0xff;
9
10
uart_ini();
11
12
sei();
13
14
while(1)
15
{
16
...
17
}
18
}
(und aus der uart_init fliegt es raus)
Bei dir macht das im Moment keinen Unterschied. Genausogut könnte ich
sagen: Es macht auch keinen Unterschied ob ich bei der Tür rausgehe oder
durchs Fenster springe. Ich wohn ja eh im Erdgeschoss. Nur irgendwann
ziehst du um, vielleicht in den 3. Stock. Und dann sind alte
Gewohnheiten kontraproduktiv, weil ....
Ich hab alles so eingebunden wie du mir empfohlen hast. Leider kommt in
meinem Terminal nicht das an was ich möchte (siehe JPG). Die
Endlosschleife wird abgearbeitet und zwar für jedem einzelnen char des
arrays den ich eingebe. Es wird nicht als Array betrachet. Aber warum
gibt es für den Array empfang den character "S" aus? krübel
Scheisse
Du hast wieder mal meine Vorgabe verändert (und ich hab sie im weiteren
dann wieder weiterkopiert, weil ich nicht mehr darauf geachtet habe)
Ich habe im Original nicht ohne Grund
1
intmain()
2
{
3
charempfang[]=" ";
geschrieben!
Du hast daraus
char empfang[4];
gemacht.
Erstens: Ist damit das Array um 1 Zeichen zu kurz.
Für einen String der Länge 4 brauchst du ein Array der Länge 5!
Zweitens ist mein String mit Leerzeichen initialisiert und hat am Ende
automatisch das für einen String notwendige '\0', was dein String nicht
hat.
Lass doch den Compiler die Zeichen zählen! Der macht das zuverlässiger
als du! Ich geb ihm eine Initialisierung mit 4 Leerzeichen vor, der
Compiler zählt sie und allokiert automatisch ein Array mit der richtigen
Größe und macht als Zugabe auch noch das obligate '\0' am Ende mit rein.
Ich geb dir nicht ohne Grund den Link in die FAQ. Dort ist jeder 3.
Satz: "Achte drauf, dass deine Arrays gross genug sind; beachte das
abschliessende '\0' Zeichen; stell sicher, dass deine Arrays gross genug
sind; wenn du Längen zählen musst, achte drauf, dass am Ende eines
Strings immer noch ein '\0' Zeichen steht; wenn du Strings
zusammenbaust, bedenke das abschliessende '\0' Zeichen" Der ganze
Artikel wimmelt nur so vor solchen Warnungen.
Mehr Sorgfalt!
Hallo Karl Heinz,
Sry wegen meiner Nachlässigkeit. Wollte dir danken für deine Hilfe! Das
Proggi läuft jetzt. ich werd auch noch den aktuellen Quelltext
reinstellen. bin bloß leider ne zu Hause zur Zeit.
Mfg Rene
karl heinz, ich musste die for schleife noch rein machen. sonst funzt es
nicht! danke hat mir echt weiter geholfen! hab mir auch die artikel alle
nochmals durchgelesen :)
René schrieb:
> karl heinz, ich musste die for schleife noch rein machen. sonst funzt es> nicht! danke hat mir echt weiter geholfen! hab mir auch die artikel alle> nochmals durchgelesen :)
Wenn du da eine Schleife reinbaust, dann kannst du dir das komplizierte
Character-Shifting sparen.
1
...
2
for(inti=0;i<4;i++)
3
{
4
empfang[i]=ser_getc();
5
uart_putc(empfang[i]);
6
}
7
8
empfang[4]='\0';
9
10
uart_puts(" Kommando: '");
11
...
Das Character-Shifting war dazu gedacht, dass sich der Code aus einer
Eingabe
abto55jk
das Kommando "to55" rausfischen kann.
Aber auf lange Sicht ist das sowieso keine so gute Idee. Da wirst du dir
sowieso etwas bauen, was eine komplette Zeile vom Benutzer einliest und
diese dann nach Wörtern zerlegt, Argumente rausfischt, auf Plausibilität
prüft und die entsprechende Funktionalität ausführt. Schon alleine der
Umstand, dass momentan alle Kommandos 4 Zeichen lang sein müssen, ist ja
eine Annahme, die so nicht so schlau ist. Ausserdem wird dein Benutzer
rudimentär editieren könnnen müssen (zumindest Backspace sollte man bei
einem menschlichen Benutzer schon unterstützen) etc. etc.