Forum: PC-Programmierung Nutzdaten für RS232 Frame


von malzu (Gast)


Lesenswert?

Hallo,
ich stehe momentan vor einem Problem, bei dem ich einfach den Durchblick 
verloren habe. Ich denke in diesem Forum kann mir am besten geholfen 
werden da ihr was von der Hard- und Software versteht.
Also: Ich bin gerade dabei eine RS232 Schnitstelle zu programmieren. 
Dazu habe ich ein Frame definiert das aus Header, Nutzdaten und EoF 
(Eond of Frame) besteht. Die Nutzdaten sollen 50 Pakete aus jeweils 8 
bit also 1 byte sein. Ich programmiere mit C++ und habe meine Nutzdaten 
durch eine sehr einfache Zufallszahlengeneration erstellt. Es kommt ein 
bistream mit 300 bit heraus. Also einfach eine Zahlenfolge von Nullen 
und Einsen in zufälliger Reihenfolge und davon dann 300 hintereinander. 
Momentan speichere ich das in ein int Array. Jetzt sind meine Nutzdaten 
ja aber ein char Array[50]. Das heisst ich habe 400 bit zur Verfügung in 
diesem Array. Mein problem dabei ist denke ich die Konvertierung. Also 
wie bekomme ich es jetzt hin dass 8 int Werte sich zu einem char Wert 
zusammentun und ich sie somit einfach in das char Array speichern kann.
Konkret:
int Array[16] = {0,0,1,1,1,1,0,1,0,0,1,1,0,1,0,1};
char Array[2] = ????

Ich hoffe irgendjemand versteht meine wirren ausführungen, ich weis 
nicht wie ich das anders erklären soll. Kann mir jemand helfen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du weißt aber schon, daß eine UART eine Hardwarekomponente ist, die 
sowohl in PCs als auch in µCs Dir diese gesamte Arbeit abnimmt? In die 
UART steckt man die zu übertragenden Nutzdaten hinein, und aus der UART 
kommen die übertragenen Nutzdaten auch wieder heraus. Framing, Start- 
und Stopbits kümmern nur die UART, nicht aber deren Nutzer.

Was genau hast Du vor?

von malzu (Gast)


Lesenswert?

Also ich schreibe eine GUI mit MFC in der dann beim Start die Daten 
generiert und über die RS232 gesendet werden sollen. Die Daten werden 
eben mit rand() %2; generiert und in ein int Array[300] geschrieben. 
Also habe ich sozusagen einen Bitstream mit 300 bit.

Diese UART müsste ich ja irgendwie ansprechen, oder? Also eigentlich 
geht es mir nur darum, dass ich die Nullen und Einsen in das char Array 
bekomme und zwar so dass eine Null nur 1 bit Platz braucht und eine 1 
auch nur 1 bit Platz braucht. Weil momentan sind sie ja als int 
gespeichert und jedes int brauch ja 32 bit Platz. Und wenn ich schreibe 
char a = "01001100"; dann hat das ja nicht nur 8 bit, oder liege ich da 
falsch. Außerdem wüsst ich nicht wie ich das nachher wieder auseinander 
klamüsern müsste.

Hat denn jemand Erfahrung mit der Schnittstellenprogramierung von RS232? 
Ich nutze eine freie Bibliothek von CodeProject - nennt sich CSerial von 
Ramon de Klein. Ich versteh halt einfach nicht wie ich das mit den 
Nutzdaten hinbekomme. Vielleicht bin ich einfach zu doof dafür oder sitz 
aufm Schlauch. :(

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du musst Dich überhaupt nicht um den Bitstrom kümmern. Dafür ist die 
Hardware in Form der seriellen Schnittstelle Deines PCs da. Die muss 
initialisiert werden (Datenformat und Baudrate), und überträgt ab da 
jedes ihr übergebene Byte.

Und das tut auch CSerial, sieh Dir einfach das Codebeispiel auf 
http://www.codeproject.com/KB/system/serial.aspx im Abschnitt "Sending 
Data" an.
Das initialisiert die Schnittstelle und sendet dann die Zeichenfolge 
"Hello world". Das sind bereits die Nutzdaten, mehr Aufwand ist nicht 
erforderlich.

von malzu (Gast)


Lesenswert?

Ja das habe ich so eigentlich auch verstanden. Aber wenn ich anstatt 
"Hello World" z.B. "11001100" übertrage sind das ja nicht wirklich 8bit 
die ich da übertrage, oder? Es geht mir eigentlich darum dass ich 
wirklich 8 bit übertrage wenn ich 8 Einser und Nuller übertrage.
Immerhin richtet man im Header ja auch ein STX und nach den Nutzdaten 
ein ETX ein damit gemerkt wird wann die Daten zu ende sind. Die bit 
sollen halt eigentlich nicht als String sonder wirklich als bit 
übergeben werden.

von Ralf (Gast)


Lesenswert?

> Die bit sollen halt eigentlich nicht als String sonder wirklich als bit
> übergeben werden.
Dann wäre eine achtfache Shiftoperation mit jeweiligem Verordern aber 
besser. Ein UART arbeitet byte- und nicht bit-orientiert.

Oben hast du geschrieben, dass du die Bits mit
1
rand() %2;
generierst. Warum machst du das nicht direkt so, dass dir ein zufälliges 
Byte rausfällt? Das Byte schickst du dann und gut ist =)

Ralf

von malzu (Gast)


Lesenswert?

Ich verstehe jetzt was du meintest mit "CSerial macht das". Weil man 
nach dem Öffnen des COM mit Open() ja das Setup() aufruft und da alles 
einstellt. Man stellt einfach ein welche Baudrate, wie viele Bits, ob 
ein Parity Bit und wie viele Stop Bits gesetzt werden sollen. Ja, ich 
verstehe, man muss eigentlich kein eigenes Frame aufsetzten.
Jetzt ist es aber so, ich habe zwei Dokus von Programmen die diese 
Bibliothek nutzen um Daten zu senden und in beiden ist erklärt wie man 
ein Frame aufsetzt. Warum sollten die das dann machen? Werden dann die 
selber gebastelten Frames in die von der Bibliothek erstellten Frames 
eingefügt?

von malzu (Gast)


Lesenswert?

Ralf schrieb:
> Dann wäre eine achtfache Shiftoperation mit jeweiligem Verordern aber
> besser. Ein UART arbeitet byte- und nicht bit-orientiert.
>
> Oben hast du geschrieben, dass du die Bits mitrand() %2;generierst. Warum machst 
du das nicht direkt so, dass dir ein zufälliges
> Byte rausfällt? Das Byte schickst du dann und gut ist =)

Wie sieht denn so eine Shiftoperation aus? Das hab ich noch nie gemacht. 
Es geht halt darum dass ich beim Empfangen wieder genau rauslesen kann 
wann eine 0 oder eine 1 kam, damit ich die dann wieder in ein int Array 
schreiben kann und damit weiter arbeiten.

Also die Reihenfolge ist zwar eigentlich zufällig, aber nach den 300 bit 
soll dann wieder die selbe "zufällige" Reihenfolge kommen. Damit sie 
immer gleich ist, benutze ich srand(1);
Außerdem wenn ich immer nur ein Byte schicke würde das die 
Geschwindigkeit ja runter ziehen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> Jetzt ist es aber so, ich habe zwei Dokus von Programmen die diese
> Bibliothek nutzen um Daten zu senden und in beiden ist erklärt wie man
> ein Frame aufsetzt. Warum sollten die das dann machen? Werden dann die
> selber gebastelten Frames in die von der Bibliothek erstellten Frames
> eingefügt?

Das wird wohl so sein, daß es sich bei diesen Frames um aus mehreren 
Bytes zusammengesetzte Frames handelt, also eine Protokollebene oberhalb 
der durch die UART-Hardware vorgenommenen Byte-Übertragung.

von Helmut L. (helmi1)


Lesenswert?

Da du ja einen Header fuer deinen Datenframe konstruiert hast hast du 
nicht mehr alle Kombinationen in deinen 8Bit Zeichen frei. Ich wuerde 
jetzt immer 4 deiner "Bits" zu einem Hexzeichen zusammenfassen und das 
uebertragen.

char SendByte;

 // Bits zusammen fassen
 SendByte = Array[0+p] | (Array[1+p] << 1) | (Array[2+p] << 2) | 
(Array[3+p] << 3);

 // Den Arrayindex hochzaehlen
  p+=4;

 // Nach HEX wandlen  '0123456789ABCDEF'
 if(SendByte > 9) SendByte += ('A'-10);
 else             SendByte += '0';

 // Und ausgeben
 SendByte ausgeben

Gruss Helmi

von Michael U. (amiga)


Lesenswert?

Hallo,

malzu schrieb:
> Hallo,
> ich stehe momentan vor einem Problem, bei dem ich einfach den Durchblick
> verloren habe. Ich denke in diesem Forum kann mir am besten geholfen
> werden da ihr was von der Hard- und Software versteht.
> Also: Ich bin gerade dabei eine RS232 Schnitstelle zu programmieren.
> Dazu habe ich ein Frame definiert das aus Header, Nutzdaten und EoF
> (Eond of Frame) besteht. Die Nutzdaten sollen 50 Pakete aus jeweils 8
> bit also 1 byte sein. Ich programmiere mit C++ und habe meine Nutzdaten
> durch eine sehr einfache Zufallszahlengeneration erstellt. Es kommt ein
> bistream mit 300 bit heraus. Also einfach eine Zahlenfolge von Nullen
> und Einsen in zufälliger Reihenfolge und davon dann 300 hintereinander.
Du willst also seriell einen Header, 50 Byte Nutzdaten und EOF senden.
Warum erzeugts Du also als Zufallsdaten nicht einfach 50 Zufallszahlen 
im Bereich 0...255 und legst diese in einem Byte-Array ab?
Das sind dann 50 zufällige 8er Gruppen mit zufälliger 0-1 Verteilung, 
also das, was Du haen willst.
Den Kram schickst Du dann in einer Schleife raus (Header davor natürlich 
und EOF dahinter) und fertig.
Ich kann kein C++ und kenne auch Dein System nicht.
Welcher Datentyp 8Bit breit ist, weiß ich also nicht. Das Array kann 
natürlich auch int oder sonstwas binäres gräßeres sein, dann mußt Du 
eben beim Senden auf Byte casten/maskieren/was-auch-immer.

> int Array[16] = {0,0,1,1,1,1,0,1,0,0,1,1,0,1,0,1};
> char Array[2] = ????

Ob char auf Deinem System 8Bit ist weiß ich nicht, in meinem uralten VB6 
ist das z.B. 16Bit.

Gruß aus Berlin
Michael

von Karl H. (kbuchegg)


Lesenswert?

malzu schrieb:
> Also ich schreibe eine GUI mit MFC in der dann beim Start die Daten
> generiert und über die RS232 gesendet werden sollen. Die Daten werden
> eben mit rand() %2; generiert und in ein int Array[300] geschrieben.
> Also habe ich sozusagen einen Bitstream mit 300 bit.

Nein.
Hast du nicht.
Du hast 300 Bytes

Auch wenn jedes der Bytes bei dir momentan nur den Wert 0 oder 1 haben 
kann, sind es immer noch Bytes und keine Bits.

> Diese UART müsste ich ja irgendwie ansprechen, oder? Also eigentlich
> geht es mir nur darum, dass ich die Nullen und Einsen in das char Array
> bekomme und zwar so dass eine Null nur 1 bit Platz braucht und eine 1
> auch nur 1 bit Platz braucht.

Das hört sich jetzt schon ganz anders an, als der Kauderwelsch von 
vorher.

> Weil momentan sind sie ja als int
> gespeichert und jedes int brauch ja 32 bit Platz. Und wenn ich schreibe
> char a = "01001100";

Das kannst du so gar nicht schreiben, weil es Unsinn ist.

> dann hat das ja nicht nur 8 bit, oder liege ich da
> falsch. Außerdem wüsst ich nicht wie ich das nachher wieder auseinander
> klamüsern müsste.

Du bist auf der Suche nach
  >>      Schiebeoperation nach links
  <<      Schiebeoperation nach rechts
  &       binäres Verunden
  |       binäres Verodern

mit diesen Operationen setzt du dir eine Funktion zusammen, die jeweils 
8 char nimmt und daraus ein Gesamtbyte generiert, welche genau die Bits 
gesetzt hat, die in den 8 Eingangswerten als 1 markiert sind.

Hilfe dazu findest zb hier
http://www.mikrocontroller.net/articles/Bitmanipulation

Aber wie schon aufgeführt:
Eigentlich ist es Schwachsinn, sich zunächst mühsam 8 einzelne 'Bits' zu 
erzeugen, nur um die dann mühsam zu einem Byte zusammenzustoppeln. Da 
kannst du dir auch gleich ein Byte mit einem Wert von 0 bis 255 erzeugen 
lassen. Macht genau das gleiche.

> Hat denn jemand Erfahrung mit der Schnittstellenprogramierung von RS232?

Das hat damit nichts zu tun.
Über eine RS232 gehen Bytes raus. Wo die Bytes herkommen interessiert 
die Schnittstellenprogrammierung nicht.

> Ich nutze eine freie Bibliothek von CodeProject - nennt sich CSerial von
> Ramon de Klein. Ich versteh halt einfach nicht wie ich das mit den
> Nutzdaten hinbekomme. Vielleicht bin ich einfach zu doof dafür oder sitz
> aufm Schlauch. :(

Du versteifst dich zu sehr auf Bits. Die interessieren niemanden auf 
dieser Ebene. Die kleinste Einheit ist ein Byte.

von malzu (Gast)


Lesenswert?

Hallo alle zusammen,

vielen Dank für eure Antworten. Ich werde mir das alles nochmal durch 
den Kopf gehen lassen und mir eure Antworten nochmal genauer anschauen. 
Ich danke euch auf jeden Fall schonmal vielmals.

Grüße malzu

von kruemeltee (Gast)


Lesenswert?

rand() bis 255 und gut is :)
ein rand() = 1 byte

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
Noch kein Account? Hier anmelden.