Hallo ich möchte einzelne Zeichen aus einer binärdatei lesen und an eine serielle schnittstelle übergeben (COM Port zu einem ZigBee Modul) jedoch habe ich das Problem das es nicht funktioniert wie ich es will private void button1_Click(object sender, EventArgs e) { using (BinaryReader b = new BinaryReader(File.Open("C:/Users....compression.bin", FileMode.Open))) { // 2. // Position and length variables. int pos = 0; //string x; // 2A. // Use BaseStream. int length = (int)b.BaseStream.Length; char[] buff = new char[length]; while (pos < length) { // 3. // Read integer. buff[pos] = b.ReadChar(); // einzelne Zeichen auslesen string x = new string(buff); serialPort1.Write(x); { buff[pos] = v[i]; } */ // 4. // Advance our position variable. pos ++; } string s = new string(buff); //x=ByteArrayToString(buff); textBox1.AppendText(s); } } Als Fehlermeldung bekomme ich: Der Ausgabe-Zeichenpuffer zu klein für die codierten Zeichen. Codierung von "Unicode (UTF-8)" in Ausweichposition "System.Text.DecoderReplacementFallback". Parametername: chars Mache ich das richtig oder gibt es auch eine andere Lösung für mein Vorhaben
string x = new string(buff); serialPort1.Write(x); warum wandelst du auch erst in einen String um? Sende doch gleich das byte. WriteByte oder so.
amateur schrieb: > anders gehts nicht es gbt kein bytewrite klar geht es anders - stings sind er falsche weg!!!! Eventuell mal selber die doku lesen? http://msdn.microsoft.com/de-de/library/system.io.ports.serialport.aspx Write(Byte[], Int32, Int32) Schreibt eine angegebene Anzahl von Bytes unter Verwendung von Daten aus einem Puffer in den seriellen Anschluss.
Hier etwas sauberer: private void button1_Click(object sender, EventArgs e) { using (BinaryReader b = new BinaryReader(File.Open("C:/Users...compression.bin", FileMode.Open))) { int pos = 0; int length = (int)b.BaseStream.Length; char[] buff = new char[length]; while (pos < length) { buff[pos] = b.ReadChar(); string x = new string(buff); serialPort1. pos ++; } string s = new string(buff); textBox1.AppendText(s); } }
So richtig? private void button1_Click(object sender, EventArgs e) { using (BinaryReader b = new BinaryReader(File.Open("C:/Users...compression.bin", FileMode.Open))) { int pos = 0; int length = (int)b.BaseStream.Length; byte[] buff = new byte[length]; while (pos < length) { buff[pos] = b.ReadByte(); //string x = new string(buff); pos ++; } // serialPort1.Write(buff, 0, length); string s=ByteArrayToString(buff); textBox1.AppendText(s); } }
Deine Version würde mit einer for-Schleife besser aussehen: private void button1_Click(object sender, EventArgs e) { using (BinaryReader b = new BinaryReader(File.Open("C:/Users...compression.bin", FileMode.Open))) { int length = (int)b.BaseStream.Length; byte[] buff = new byte[length]; for (int pos = 0; pos < length; pos++) buff[pos] = b.ReadByte(); serialPort1.Write(buff, 0, length); string s=ByteArrayToString(buff); textBox1.AppendText(s); } } Probiere mal dieses: FileStream s = new FileStream("test.txt", FileMode.Open); byte[] Data; s.Read(Data, 0, s.Length); serialPort1.Write(Data, 0, Data.Length);
Dann solltest du nicht "test.txt" als Dateinamen nehmen, vermute ich. Oder was meinst du mit der Frage?
OK. Aber wie funktioniert es mit der rekonstruktion dieses Files auf der anderen seite?
amateur schrieb: > OK. Aber wie funktioniert es mit der rekonstruktion dieses Files auf der > anderen seite? was soll diese dumme frage? Es kommen doch daten aus der Datei drüben an, wenn sie dort genauso wieder in eine Datei geschrieben werden hast du das Bild drüben. Es spielt überhaupt keine rolle was das für eine Datei ist, es kann auch ein Video sein.
Google mal X-, Y- oder Z-Modem. Das sind Protokolle zur Übertagung von Dateien per DFÜ (seufz), bzw. serieller Schnittstelle. Sicherlich gibt es auch Implementierungen in C#.
Hallo, ich bin jetzt soweit dass ich die bin dateien RICHTIG einlese. using (FileStream fs = File.OpenRead(path)) { Int64 f = fs.Length; byte[] b = new byte[f]; UTF8Encoding temp = new UTF8Encoding(true); while (fs.Read(b, 0, b.Length) > 0) { string s = ByteArrayToString(b); textBox1.AppendText(s); serialPort1.Write(b, 0, b.Length); } In b steht genau das was ich möchte.... Das Problem ist leider auf der Empfängerseite... private void serialPort1_DataReceived (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { RxString = serialPort1.ReadExisting(); int y = serialPort1.BytesToRead; serialPort1.Read(buff, 0, 96966); this.Invoke(new EventHandler(DisplayText)); } Es werden jedoch nur 392(y=0x188) übertragen :-( und das irgendwo in dem File -> also nicht schön von anfang an). Als Übertragungsmedium habe ich ZigBee Module die als Wireless Uart laufen. Was mache ich hier falsch?
amateur schrieb: > RxString = serialPort1.ReadExisting(); > int y = serialPort1.BytesToRead; > serialPort1.Read(buff, 0, 96966); > this.Invoke(new EventHandler(DisplayText)); das ist ja auch unsinn, die liest hier 2mal ein. DAs kann ja nicht gut gehen. einmal hier: > RxString = serialPort1.ReadExisting(); und noch einmal > serialPort1.Read(buff, 0, 96966); und wall soll diese zahl dort? Du kannst gar nicht wissen ob so viele zeichen da sind. du braucht nur: readSize += serialPort1.Read(buff, readSize, serialPort1.BytesToRead ); readSize ist dabei die größe die bis zu diesem zeitpunkt angekommen ist. muss also eine variabel außerhalb von serialPort1_DataReceived sein, sinnvoll ist auch voher die Größe der Datei zu übertragen sonst weist du ja nicht wenn schluss ist.
Peter II schrieb: > das ist ja auch unsinn, die liest hier 2mal ein. DAs kann ja nicht gut > gehen. > > einmal hier: >> RxString = serialPort1.ReadExisting(); > > und noch einmal Das ist nur für die ausgabe auf dem Textbox :-) Peter II schrieb: > und noch einmal > >> serialPort1.Read(buff, 0, 96966); > > und wall soll diese zahl dort? Du kannst gar nicht wissen ob so viele > zeichen da sind. Ich weiss dass so viele Daten anliegen... Aber auch wenn ich da einfach so mal 1000 eingebe kommen keine 1000 Daten an sondern 458. Und das komische ist jetzt es fängt vorne an und nach einpaar Daten (~15) springt es zu einer anderen Stelle??? und macht da weiter. Das Ende stimmt auch (die letzten paar Daten).
Ich habe inzwischen herausgefunden dass immer 10 Byte auf einmal gesendet werden und dann sprung irgendwohin und noch mal 10 Byte und noch mal und noch mal un am ende die letzten 127 Byte richtig ...
ruffy d. monkey schrieb: > Das ist nur für die ausgabe auf dem Textbox :-) das darfst du drozdem nicht machem, dann nach dem Lesen sind die Daten weg, man kann sie nicht 2 mal lesen! > Ich habe inzwischen herausgefunden dass immer 10 Byte auf einmal > gesendet werden und dann sprung irgendwohin und noch mal 10 Byte und > noch mal und noch mal un am ende die letzten 127 Byte richtig ... nein das ist nicht so, es können auf einer Seriellen Leitung nicht 10 byte auf einmal gesendet werden! Sie werden immer die reihe nach gesendet. Wegen der Puffer in der Harder oder im Betriebsystem kommen sie in verschienden Blöcken an, die anzahl kann aber jedes mal anders sein! > letzten 127 Byte richtig glaube ich nicht, weil im Puffer nur 10 byte reinpassen
Wie kann ich mir die "Sprünge" erklären? Kommen die ZigBee Module nicht nach?
ruffy d. monkey schrieb: > Wie kann ich mir die "Sprünge" erklären? Kommen die ZigBee Module nicht > nach? optimierung. Warum sollte der PC für jedes byte einzeln die Empfangsroutinge aufrufen? Dann wartet man lieber bis ein baar bytes da sind.
jetzt muss ich leider weg, da ich noch ein Test schreiben muss Regelungstechnik :D vielen dank für die antworten und anregungen ich werds mir morgen nochmal intensiv anschauen.
hallo, guten morgen bin wieder da! Ich habe grad vorhin probiert mit HTerm Daten zu senden. Wenn ich eigene Eingaben mache und diese nicht sehr lange mache (bis 138 Byte) wird alles übertragen. Genau ab diesen 139 Byte geht schon 1 Byte verloren. Wenn ich 276 Byte übertrage kommen nur 20 heil an??? Was ist das?
ruffy d. monkey schrieb: > Was ist das? keine ahnung, dafür müssten wir mal den code sehen mit dem du die daten empfängst.
welchen Code meinst du? auf den ZigBee Modulen?(RZWirelessUart-http://www.atmel.com/tools/RZ600.aspx?tab=documents (RZ600 HW)) kann der COM Port Treiber nicht schuld sein? oder die USB?
Aber wenn es auch mit dem HTerm Terminal nicht funktioniert muss doch an anderer Stelle das Problem sein.
1 | using System; |
2 | using System.Collections.Generic; |
3 | using System.ComponentModel; |
4 | using System.Data; |
5 | using System.Drawing; |
6 | using System.Text; |
7 | using System.Windows.Forms; |
8 | |
9 | namespace SimpleSerial |
10 | { |
11 | public partial class Form1 : Form |
12 | { |
13 | // Add this variable |
14 | |
15 | string RxString; |
16 | byte[] buff = new byte[127]; |
17 | |
18 | public Form1() |
19 | { |
20 | InitializeComponent(); |
21 | } |
22 | |
23 | private void buttonStart_Click(object sender, EventArgs e) |
24 | { |
25 | serialPort1.PortName = "COM8"; |
26 | serialPort1.BaudRate = 57600; |
27 | |
28 | serialPort1.Open(); |
29 | if (serialPort1.IsOpen) |
30 | { |
31 | buttonStart.Enabled = false; |
32 | buttonStop.Enabled = true; |
33 | textBox1.ReadOnly = false; |
34 | } |
35 | } |
36 | |
37 | private void buttonStop_Click(object sender, EventArgs e) |
38 | { |
39 | if (serialPort1.IsOpen) |
40 | { |
41 | serialPort1.Close(); |
42 | buttonStart.Enabled = true; |
43 | buttonStop.Enabled = false; |
44 | textBox1.ReadOnly = false; |
45 | } |
46 | |
47 | } |
48 | |
49 | private void Form1_FormClosing(object sender, FormClosingEventArgs e) |
50 | { |
51 | if (serialPort1.IsOpen) serialPort1.Close(); |
52 | } |
53 | |
54 | private void textBox1_KeyPress(object sender, KeyPressEventArgs e) |
55 | { |
56 | // If the port is closed, don't try to send a character. |
57 | |
58 | if(!serialPort1.IsOpen) return; |
59 | |
60 | // If the port is Open, declare a char[] array with one element. |
61 | char[] buff = new char[1]; |
62 | |
63 | // Load element 0 with the key character. |
64 | |
65 | buff[0] = e.KeyChar; |
66 | |
67 | // Send the one character buffer. |
68 | serialPort1.Write(buff, 0, 1); |
69 | |
70 | // Set the KeyPress event as handled so the character won't |
71 | // display locally. If you want it to display, omit the next line. |
72 | e.Handled = true; |
73 | } |
74 | |
75 | private void DisplayText(object sender, EventArgs e) |
76 | { |
77 | textBox1.AppendText(RxString); |
78 | } |
79 | |
80 | private void serialPort1_DataReceived |
81 | (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) |
82 | { |
83 | //RxString = serialPort1.ReadExisting(); |
84 | int y = serialPort1.BytesToRead; |
85 | serialPort1.Read(buff, 0, y); |
86 | |
87 | } |
88 | } |
89 | } |
So ich schreibe jetzt die 10 Byte Daten an den Serialport und lese diese dann ein und füge sie zusammen. Aber 110. Byte ist noch in Ordnung 111.-119. ist die Wieder holung des letzten Blockes [101] 101 byte [102] 65 byte [103] 0 byte [104] 147 byte [105] 101 byte [106] 65 byte [107] 0 byte [108] 183 byte [109] 26 byte bis hier [110] 65 byte richtig [111] 101 byte [112] 65 byte [113] 0 byte [114] 147 byte [115] 101 byte [116] 65 byte [117] 0 byte [118] 183 byte [119] 26 byte danach geht es ab der 111 im Originalen weiter... Wieso???
1 | //Sender
|
2 | private void button1_Click(object sender, EventArgs e) |
3 | {
|
4 | |
5 | string path = @"C:\Users\ipa\Desktop\jpeg_compression.txt"; |
6 | |
7 | |
8 | |
9 | //Open the stream and read it back.
|
10 | using (FileStream fs = File.OpenRead(path)) |
11 | {
|
12 | Int64 f = fs.Length; |
13 | byte[] b = new byte[f]; |
14 | int off = 0; |
15 | decimal pakete = f/10; |
16 | decimal paket = Math.Round(pakete); |
17 | fs.Read(b, 0, b.Length); |
18 | |
19 | for (int a = 1; a < paket; a++) |
20 | {
|
21 | serialPort1.Write(b, off, 10); |
22 | off = (10 * a); |
23 | }
|
24 | }
|
25 | }
|
26 | |
27 | //Empfänger
|
28 | private void serialPort1_DataReceived |
29 | (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) |
30 | {
|
31 | serialPort1.Read(buff, 0, 10); |
32 | buff.CopyTo(buff2, offset); |
33 | offset = offset + 10; |
34 | if (offset >= 98150) |
35 | {
|
36 | CreateFile(buff2); |
37 | }
|
38 | }
|
serialPort1.Read(buff, 0, 10); hier ist schon mal ein fehler. Es ist nicht sicherstellt das wirklich 10 zeichen gelesen werden. Man muss den return wert von Read auswerten, dort steht drin wie viele daten wirklich gelesen wurden. Und dann mit dem 2. array kannst du dir sparen, was glaubst du was der 2. parameter der Read funktion macht? - es ist der offset für das array.
Peter II schrieb: > Und dann mit dem 2. array kannst du dir sparen, was glaubst du was der > 2. parameter der Read funktion macht? - es ist der offset für das array. Na um es später in eine Datei reinzuschreiben. Ich habe das Problem dass wenn ich viele Bytes schreibe sich das Programm sehr komisch verhält so finktioniert es zum größten Teils (bis auf einige effekte). Immernoch dasselbe mit serialPort1.Read(buff, 0, serialPort1.BytesToRead);
ruffy d. monkey schrieb: > Immernoch dasselbe mit > > serialPort1.Read(buff, 0, serialPort1.BytesToRead); wie sie der code complett aus? Mit so einer zeile kann niemand etwas anfangen.
steht doch immer noch der gleiche unsinn drin
1 | private void serialPort1_DataReceived |
2 | (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) |
3 | {
|
4 | serialPort1.Read(buff, 0, 10); |
5 | buff.CopyTo(buff2, offset); |
6 | offset = offset + 10; |
7 | if (offset >= 98150) |
8 | {
|
9 | CreateFile(buff2); |
10 | }
|
11 | }
|
du musst auch abfragen wie viele daten gelesen wurden, nur weil du 10 byte willst bekommst du sich nicht immer.
Ich hab das hier vergessen (sender seite) Peter II schrieb: > steht doch immer noch der gleiche unsinn drin Ich hab rumprobiert ohne erfolg also alles rückgängig gemacht
ruffy d. monkey schrieb: > Ich hab rumprobiert ohne erfolg also alles rückgängig gemacht dann kann man dir nicht helfen. Ich habe dir gezeigt wo der fehler ist, keine ahnung wie du versucht hast ihn zu beheben, aber mit diesem empfangscode wird es NIE sauber gehen. Schreibt erstmal eine ordentliche funktion, dabei achtest du auf folgendes: - du musst BytesToRead verwenden um rauszubekommen wie viel du lesen darst - du muss den Returnwert von read verwenden um zu wissen wie viel gelesen wurde dann postest du diese routine, auch wenn sie eventuell noch nicht geht.
ruffy d. monkey schrieb: > Aber wenn es auch mit dem HTerm Terminal nicht funktioniert muss doch an > anderer Stelle das Problem sein. Stimmt allerdings.
so? brint aber auch nicht viel aber es sind bis zum 4033. byte identisch(Eingabe = Ausgabe). Danach keine Übereinstimmung. private void serialPort1_DataReceived (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { int x=serialPort1.Read(buff2, 0, serialPort1.BytesToRead); //buff.CopyTo(buff2, offset); offset = offset + x; if (offset >= 98150) { CreateFile(buff2); } }
verbinde doch mal direkt die sende und empfangsleitung am PC - stimmt dann die gesendeten und empfangen daten? Ich kenne diese funktmodule nicht, was seht denn dort zur datensicherheit? Kümmern sich die geräte selber darum oder muss du das machen?
Also inzwischen bin ich mir sicher, dass das Problem die zu schnelle Übergabe der Daten an den Modul ist. Denn sobald ich nach jeden 88 Bytes einen Sleep(99) mache kann ich 12kByte ohne Probleme übertragen. Man sagte mir aber ich müsste mich um diese Laufzeiten bzw. dieses warten nicht kümmern da es in den unteren Schichten gemacht werden müssten. Der Treiber ist glaub schuld...
dann musst du eventuell die Flusskontrolle nutzen. Wenn dein Gerät außer Reichweite ist, dann bekommst du es ja gar nicht mit und sendest fröhlich weiter.
ich habe eine Art Terminalprogramm geschrieben in C#, welches mir Datenpakete(kleiner 127 Byte) aus einer JPEG file bildet und diese werden dann übertragen. Auf der Empfängerseite werden diese Pakete wieder zusammengesetzt. Mein Problem ist, dass nach ~12 kByte nichts mehr ankommt. Bis 12kByte ist alles OK. Das was gesendet wird wird auch empfangen und zusammengesetzt. Dies funktioniert jedoch nur, wenn ich zwischen diesen Paketen pausen einlege (Sleep(100)) (ms). Erste Frage: Wieso muss ICH diesen Sleep implementieren, wird es nicht vom Betriebssystem bzw. vom COM Port Treiber gemacht? Zweite Frage: Wieso hört es immer bei 12 kByte auf? Puffer voll?? Wird es aber nach dem lesen nicht geleert? Sender: private void button1_Click(object sender, EventArgs e) { string path = @"C:\Users\ipa\Desktop\adidas.jpg"; //Open the stream and read it back. using (FileStream fs = File.OpenRead(path)) { Int64 f = fs.Length; byte[] b = new byte[f]; decimal pakete = f/100; /100 Byte große Datenpakete decimal paket = Math.Round(pakete); fs.Read(b, 0, b.Length); Int32 offset=0; for (int a = 0; a <= paket-1; a++) { serialPort1.Write(b,offset,100); System.Threading.Thread.Sleep(60); offset = offset + 100 ; }serialPort1.Close(); } } Empfänger: private void serialPort1_DataReceived (object sender, System.IO.Ports.SerialDataReceivedEventArgs e) { do { x = serialPort1.Read(buff2, offset, serialPort1.BytesToRead); offset = offset + x; } while (offset <= 31130); //das File ist 31142 Byte groß; CreateFile(buff2); //JPEG datei wird reproduziert }
ruffy d. monkey schrieb: > Dies funktioniert jedoch nur, wenn ich > zwischen diesen Paketen pausen einlege (Sleep(100)) (ms). Erste Frage: > Wieso muss ICH diesen Sleep implementieren, wird es nicht vom > Betriebssystem bzw. vom COM Port Treiber gemacht? hast du die Frage darüber gelesen? > dann musst du eventuell die Flusskontrolle nutzen. dafür müsste man aber die doku deiner module lesen
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.