C# Serielle kommunikation - bin datei transferieren.

Gast #2662728
Lesenswert?

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
Gast #2662762
Lesenswert?

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);

              }

          }
Gast #2662783
Lesenswert?

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);

              }

          }
Gast #2664832
Lesenswert?

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);
Gast #2666577
Lesenswert?

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.
Gast #2667477
Lesenswert?

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?
Gast #2667489
Lesenswert?

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.
Gast #2667514
Lesenswert?

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).
Gast #2667587
Lesenswert?

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 ...
Gast #2667610
Lesenswert?

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
Gast #2668883
Lesenswert?

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?
Gast #2668924
Lesenswert?

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
  }
Gast #2670398
Lesenswert?

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
          }
Gast #2670404
Lesenswert?

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.
Gast #2670423
Lesenswert?

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);
Gast #2670470
Lesenswert?

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.
Gast #2670495
Lesenswert?

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.
Gast #2670566
Lesenswert?

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);
                    }
          }
Gast #2670621
Lesenswert?

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?
Gast #2671966
Lesenswert?

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...
Gast #2675909
Lesenswert?

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




          }
Gast #2675923
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren