Hallo Leute ich habe folgendes Problem :
Ich möchte Daten von einer Steuerung über die serielle Schnittstelle
empfangen. Soweit kein Problem bei Trockenübungen am Pc.
hier meine Empfangsroutine:
1
voidusart_gets(char*Buffer,uint8_tMaxLen)
2
{
3
uint8_tNextChar;
4
uint8_tStringLen=0;
5
intwert=0;
6
NextChar=usart_getc();// Warte auf und empfange das nächste Zeichen
7
8
// Sammle solange Zeichen, bis:
9
// * entweder das String Ende Zeichen kam
10
// * oder das aufnehmende Array voll ist
11
while(NextChar!='\n'&&StringLen<MaxLen-1)
12
{
13
*Buffer++=NextChar;
14
15
ende=wert;
16
StringLen++;
17
NextChar=usart_getc();
18
}
19
20
// Noch ein '\0' anhängen um einen Standard
21
// C-String daraus zu machen
22
*Buffer='\0';
23
}
Er schreibt das daten[] Array solange mit den empfangenen Zeichen bis \n
kommt als Abschluss.
Jetzt hab ich das Problem das meine Steuerung kein Abschlusszeichen
sendet, es hört einfach nach dem letzten "Nutzzeichen" auf und wartet
dann auf den Bestätigungsstring.
Wie teile ich der Routine mit das die Datenübertragung zu ende ist und
die Routine verlassen werden soll?
Könnte das über ne definierte Zeit gehen? Wenn nix innerhalb einer
bestimmten Zeit kommt dann beende Schleife?
Wie schreib ich das???
Christian Hohmann schrieb:
> Jetzt hab ich das Problem das meine Steuerung kein Abschlusszeichen> sendet, es hört einfach nach dem letzten "Nutzzeichen" auf und wartet> dann auf den Bestätigungsstring.
Die Übertragung muß ein Protokoll haben, mit der das Ende eines
Datenpakets eindeutig bestimmt werden kann. Verbreitet sind 2 Methoden:
1. Endezeichen (darf dann nicht im Datenstrom vorkommen)
2. Das Paket enthält an einer festen Stelle eine Längenangabe, dann wird
ab da runtergezählt.
Hat Dein Sender kein Protokoll, sollte man dem Entwickler ordentlich
eins hinter die Löffel geben. Ein Timeout ist nur der absolut
allerletzte Notnagel, für die Leute, die nicht programmieren können.
Peter
oder macht deine steuerung nur bestimmte ausgaben ?
dann könnte man zB mit einem strncmp( , ) was machen
ansonst mal mit anderen programmen schauen ob nicht irgend ein zeichen
kommt
hterm glaube zeigt alles an auch \r\n und so
Ich verwende hterm und deswegen weis ich das kein weiteres Endzeichen
geschrieben wird.
Sieht hier jemand in dem String irgend ne Prüfsumme versteckt?
4D 41 0C 49 00 1C 07 2B 5A 75 73 74 61 6E 64 04 1A
Bei den ersten 2 Zeichenketten die es schickt sah es so aus als ob das
letzte zeichen eine Prüfsumme wär aber bei der sieht es nicht so aus
oder hab ich mich verrechnet? Was muss denn da raus kommen?
Bei den ersten wars so, wenn ich alles addiere komme ist das Ergebnis
das letzte Zeichen: 5261010100B5 B5 passt.
Aber wenn ich bis 255 zähle dann gehts doch bei 256 wieder bei 0 los
oder?
> Sieht hier jemand in dem String irgend ne Prüfsumme versteckt?Jeder kann sich seine eigene Prüsfumme ausdenken. Die deint nur zur
Sicherung des Protokolls.
Die XOR-Prüfsumme, die du meinst, ist die simpelste Art, ein Protokoll
zu sichern. Mir fallen aber auf Anhieb mindestens 10 andere Arten ein,
eine Prüfsumme zu bilden... :-o
Zuerst solltest du wissen, was die einzelnen Zeichen darstellen, dann
kannst du besser raten.
> Aber wenn ich bis 255 zähle dann gehts doch bei 256 wieder bei 0 los> oder?
Ja, wenn du dich im 8-Bit-Zahlenraum bewegst...
Ich weis was die Zahlen bedeuten:
4D410C49001C072B5A757374616E64041A bedeutet Z.Bsp.:MAI +Zustand
Das is teinfach nur die Menüstruktur, der Wert für Zustand wird erst
später gesendet.
Das Was ich immer als Quittierung senden muss stzt sich zusammen aus:
'4D'+'abhängig vom Kommando'+'01'+'01'+'00'+'Prüfsumme welche einfach
alle vorherigen Zeichen aufaddiert ist'.
Deswegen dacht ich das was die Steuerung schickt hat auch die Prüfsumme
hinten dran welche einfach nur aufaddiert ist.
Nur zur Information: mit einem selbstgeschriebenen Delphiprogramm läuft
das alles Problemlos, weil mir die Empfangsroutine den kompletten string
liefert, sie also weis wann der String zu Ende ist. Diese hab allerdings
nicht selbst geschrieben und weis auch nicht wie die das macht. Es
funktionierte einfach.
Aber hier muss ich das wahrscheinlich über einen Timeout lösen...
Der ARM7 benutzt auch einen Timeout hardwaremässig bei 3 Perioden ohne
Empfang, da Bytes für gewöhnlich schnell nacheinander gesendet werden.
Diese Lösung ist sehr wohl salonfähig und sollte über dem
Softwareprotokoll stehen.
Protokolle ohne Timeout lasse ich bei Zertifizerungen nicht durchgehen,
die gehen gleich wieder zum Kunden zurück zur Nachbearbeitung.
Ja. Ein Timeout als Notnagel, oder als Standardelement sind zwei paar
Schuhe. Mit 3 Byte Totzeit ist man nie dabei. Es lohnt sich dazu mal
eine Uebertragung von einem Windows PC aufm Scope anzuschauen. Wenn
Windows etwas anderes als wichtiger betrachtet macht es etwas anderes.
Ich hab leider die exakten Zahlen vergessen, glaube aber Aussetzer von
einigen 100ms sind zu erwarten. Das waeren dann bei 9600 Baud einige 100
Byte Totzeit. Ich setze die Totzeit auf eine Sekunde und drueber. Da
spielt die Antwortzeit des Devices auch noch rein.
Hi
>Da fällt mir ein, kann ich hier nicht irgend ne Abfrage reinbauen? Also>wenn kein Zeichen mehr kommt dann tu irgendwas?:uint8_t usart_getc(void)> {> while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar> ;> return UDR; // Zeichen aus UDR an Aufrufer >zurueckgeben> }
Bei jedem Zeichen einen Timer anschubsen. Bei Überlauf abbrechen.
Die Delphi-Komponenten für serielle Kommunikation, die ich kenne, haben
alle einen programmierbaren Timeout. Ist aber eigentlich schon in der
Windows-SDK verankert.
MfG Spess
Nochmal fürs verständnis, wenn ich den timer anschubse arbeitet er aber
das Programm weiter ab oder?? er wartet nicht bis der Timer dann
durchgelaufen ist.
Müsste ich dann irgendwie mit nem Interrupt lösen wenn er überläuft
oder?
In delphi habe ich die Komponente SerialNG benutzt.
Die Funktion ReadNextClusterAsString : String; liefert mir einfach den
kompletten String zurück und ich brauchte mich um nix weiter zu
kümmern...
>habe ich die Komponente SerialNG benutzt...
Unter windows hat man wenig Zugriff. Ich empfehle speziell fuer Delphi
TPApro, da es unter anderem auch den besten Upgrade ueber die diversen
Delphi und Windows Versionen gewaehrleitet.
http://sourceforge.net/projects/tpapro/
Hi
>Nochmal fürs verständnis, wenn ich den timer anschubse arbeitet er aber>das Programm weiter ab oder?? er wartet nicht bis der Timer dann>durchgelaufen ist.
Ja.
>Müsste ich dann irgendwie mit nem Interrupt lösen wenn er überläuft>oder?
So in etwa. Ich bin nicht sehr firm in C (eigentlich gar nicht). Aber in
der ISR eine Variable (igendwie global) setzen und in 'while (!(UCSRA &
(1<<RXC)))' mit abfragen. Nach Verlassen der while-Schleife kann man
dann an Hand der Variable entscheiden.
@hmn
>Unter windows hat man wenig Zugriff.
Mit den entsprechenden API-Funktionen kommt man ganz schön weit.
Eine recht ausgefeilte Serielle Komponente gibt es auch von der
Zeitschrift 'Toolbox'.
MfG Spess
while(!(UCSRA&(1<<RXC)))// warten bis Zeichen verfuegbar
4
;
5
returnUDR;// Zeichen aus UDR an Aufrufer zurueckgeben
6
}
7
8
9
voidusart_gets(char*Buffer,uint8_tMaxLen)
10
{
11
uint8_tNextChar;
12
uint8_tStringLen=0;
13
14
NextChar=usart_getc();// Warte auf und empfange das nächste Zeichen
15
16
// Sammle solange Zeichen, bis:
17
// * entweder das String Ende Zeichen kam
18
// * oder das aufnehmende Array voll ist
19
wert=checksumme(NextChar,wert);
20
*Buffer++=NextChar;
21
ende=wert;
22
while((UCSRA&(1<<RXC))&&StringLen<MaxLen-1)
23
{
24
NextChar=usart_getc();
25
*Buffer++=NextChar;
26
27
wert=checksumme(NextChar,wert);
28
ende=wert;
29
StringLen++;
30
31
};
32
33
34
35
}
36
37
anweisungen:
38
usart_gets(daten,sizeof(daten));
39
40
41
USART_Transmit(ende);
42
gotoanweisungen;
wenn ich in hterm 20(hex) schicke kommt 00 zurück obwohl ja 20 kommen
müsste.
wenn ich 20 20 20(also alles eingeben und auf einmal schicken) eingebe
dann kommt 00 60 raus. also das 60 stimmt ja(lasse alle empfangenen
Zeichen aufaddieren) aber warum kommt vorher 00 was wird hier zu oft
durchlaufen oder was ist hier schief???
Ich verzweifle an so einer einfachen Sache
>>>Unter windows hat man wenig Zugriff.>Mit den entsprechenden API-Funktionen kommt man ganz schön weit.
Es war mir bisher nicht moeglich eine unterbruchsfreie Uebertragung von
groesseren Datenmengen hinzubekommen. Einen Buffer macht windows noch
unterbruchsfrei, aber sobald man mehrere Buffer verwendet, zB bei mehr
als 64kbyte, gibt's Unterbrueche von hunderten von millisekunden.
Christian J. schrieb:
> Protokolle ohne Timeout lasse ich bei Zertifizerungen nicht durchgehen,> die gehen gleich wieder zum Kunden zurück zur Nachbearbeitung.
Was soll den dieser Quatsch?
Man muß schon dem Entwickler überlassen, wie er die Übertragung
absichert.
Ordentliche Protokolle brauchen kein Timeout.
Ich habe oft Stringprotokolle, die 0x0D oder 0x0A als Endekennzeichen
benutzen. Zum Testen nimmt man ein Terminalprogramm und dann wäre ein
Timeout Blödsinn, so schnell kann ich nicht tippen.
Wenn ein Kommando unvollständig ist und das Endekennzeichen fehlt, nützt
ein Timeout absolut garnichts.
Für eine Zertifizierung ist dagegen wichtig, daß ein gestörtes Kommando
keinen Schaden anrichtet, d.h. durch das Protokoll ein
Übertragungsfehler mit hoher Warscheinlichkeit erkannt wird. Mit nem
Timeout erreicht man das nicht, daher ist ein Timeout völlig sinnfrei.
Peter
Ein Timeout macht was ganz anderes. Nimm ein normales Protokol, das als
Zustandsmaschine ablaeuft. Da geht nun einmal ein einzelnes Zeichen
verloren. Der Empfaenger wartet ewig. Daher hat man einen langen Timeout
und startet die Zustandsmaschine neu. Macht man vor allem auf der Master
seite. Kann aber auch bei einem Slave Sinn machen.
Hi
>Ordentliche Protokolle brauchen kein Timeout.
Aber nur, wenn die Gegenstelle immer vorhanden und bereit ist. Wenn
nicht greift kein Protokoll.
MfG Spess
also ich hätte es ja fasst hinbekommen ohne irgendwelche Timeouts oder
Protokolle wenn mir mal jemand sagen würde warum da oben Anweisungen
zweimal ausgeführt werden statt nur einmal...
oho schrieb:
> Ein Timeout macht was ganz anderes. Nimm ein normales Protokol, das als> Zustandsmaschine ablaeuft. Da geht nun einmal ein einzelnes Zeichen> verloren. Der Empfaenger wartet ewig.
Und wen störts?
Der SRAM für den Empfangspuffer ist ja permanent reserviert, daher
fressen einige Bytes eines gestörten Pakets kein Brot.
Irgendwann kommt aber wieder ein neues Paket und dann ist er wieder
synchron.
Der Master kann auch zu Anfang oder nach längeren Pausen ein spezielles
Sync-Paket schicken. Dann weiß der Slaver sicher, das eventuelle Reste
im Empfangspuffer Müll sind.
Peter