Forum: PC-Programmierung Visual C++ CLR(.net2012) Serialport, Empfang


von Mani (Gast)


Lesenswert?

Hallo
Ich habe eine Frage, ich habe in einer eigenen Klasse(RS232) eine RS232 
Behandlung geschrieben.
Ich kann über ein Form die RS232 einstellen, Öffnen und Schließen.
Nun möchte ich von der Klasse RS232 die empfangenden Daten 
weiterleitern.

Was ich bisher gemacht haben ist mir ein Event in meiner RS232 Klasse zu 
schreiben und nun wollte ich ganz einfach die
1
_serialport->DataReceived +=gcnew SerialDataReceivedEventHandler(DataReceivedHandler);
nutzen um in dem:
1
void DataReceivedHandler(Object^ sender,SerialDataReceivedEventArgs^ e)
2
{
3
  SerialPort^ sp = (SerialPort^)sender;
4
  String^ indata = sp->ReadExisting();
5
  Console::Write(indata);
6
}
mir ein Event auszulösen und die Daten im "indata" weiterzureichen um im 
Form damit zu arbeiten.

Aber leider ist der DatareceivedHandler ein eigenes Thread und ich steh 
gerad auf dem Schlauch wie ich die Daten rüberbekomme.

Hat einer eine Idee?
Invoke ist wohl ein Stichwort aber der scheint das in dem Punkt nicht zu 
kennen.

Der Handler wird in meiner RS232_init() bereit gestellt:
1
int RS232_class::RS232_init()
2
  {
3
    try
4
    {
5
      _serialport->DataReceived +=gcnew SerialDataReceivedEventHandler(DataReceivedHandler);
6
      _serialport->ReadTimeout=500;
7
      _serialport->WriteTimeout=500;
8
      _serialport->Open();
9
      
10
11
      RS232_class::RS232_empfang("t");
12
13
    }
14
    catch(System::IO::IOException^ e)
15
    {
16
      return 0;
17
    }
18
    
19
    
20
    return 1;
21
  }

von bluppdidupp (Gast)


Lesenswert?

http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c
...die zweite Antwort würde ich mir ansehen. "this" wäre in deinem Falle 
dann vermutlich die Form?

von Mani (Gast)


Lesenswert?

Danke für den Link.
Glaub aber ich hab eine andere Richtung gedacht gehabt und frag mich ob 
es überhaupt geht.
Ich wollte quasi das Event abfangen in meiner RS232 Routine und die dann 
weiterleiten und selber ein Event starten, das irgendeine übergeordnete 
Form ein Event bekommt und darauf reagieren kann.
Die meisten Routinen beschäftigen sich damit das Event direkt in der 
Form einzubinden, ich wollte ein zwischenschritt über eine eigene 
Klasse.

von bluppdidupp (Gast)


Lesenswert?

Dann musst du in deinem DataReceived-EventHandler in der RS232_class 
doch nur  dein eigenes Event feuern?
1
this.meinEigenesEvent.Invoke(indata);
...mit dem Thread darf sich der Nutzer der RS232_class dann rumschlagen.

von Mani (Gast)


Lesenswert?

So dachte ich mir das auch, leider bekomm ich dann die Meldung das es 
kein statischer Member sei..
Und ein Invoke lässt er mich irgendwie nicht benutzen, oder mach ich was 
falsch mit meinem:
//  RS232_class::RS232_empfang("test");
// gibt fehler, da keine statische Member?
?

Klassendeklarationen:
1
//Eventhandler
2
delegate void RS232_EmpfangEventHandler(String^);
3
 
4
ref class RS232_class
5
{
6
private:
7
    static SerialPort^ _serialport = gcnew SerialPort;
8
 
9
    String^ d;
10
   
11
public:
12
    //
13
    delegate int RS232_init(SerialPort^ _serialport);
14
    delegate void RS232_close(SerialPort^ _serialport);
15
    delegate void RS232_config(SerialPort^ _serialport_in, SerialPort^ _serialport_out);
16
    delegate String^ RS232_getport(void);
17
 
18
    //
19
    event RS232_EmpfangEventHandler^ RS232_empfang;
20
 
21
    //interne
22
    void RS232(void);
23
    bool RS232_anfrage_open(void);
24
    int RS232_init();
25
    void RS232_close();
26
    void RS232_config(SerialPort^ _serialport_in);
27
    String^ RS232_getport(void);
28
 
29
    bool RS232_senden(String^ Sin);
30
};  
31
32
33
  void DataReceivedHandler(Object^ sender,SerialDataReceivedEventArgs^ e)
34
{
35
    SerialPort^ sp = (SerialPort^)sender;
36
    String^ indata = sp->ReadExisting();
37
    Console::Write(indata);
38
 
39
//  RS232_class::RS232_empfang("test");
40
// gibt fehler, da keine statische Member?
41
}

Methoden:
1
 
2
int RS232_class::RS232_init()
3
    {
4
        String^ s;
5
        s="test hallo";
6
        try
7
        {
8
            _serialport->DataReceived +=gcnew SerialDataReceivedEventHandler(DataReceivedHandler);
9
            _serialport->ReadTimeout=500;
10
            _serialport->WriteTimeout=500;
11
            _serialport->WriteBufferSize=100;
12
            _serialport->Open();
13
 
14
//          Console::WriteLine(Thread::CurrentThread->GetData);
15
            RS232_class::RS232_empfang("test");
16
        }
17
        catch(System::IO::IOException^ e)
18
        {
19
            return 0;
20
        }
21
       
22
       
23
        return 1;
24
    }

von bluppdidupp (Gast)


Lesenswert?

Ist ja auch kein statischer Member - "RS232_class::" wird nicht 
benötigt.

In C# würde man einfach sowas scheiben:
1
if (RS232_empfang!=null) // Ist überhaupt ein Event-Listener registriert?
2
{
3
   // Japp - Event feuern:
4
   RS232_empfang("Daten");
5
}

von Mani (Gast)


Lesenswert?

Hmm nehm ich RS232_empfang(); direkt, meckert er das er das nicht kennt.
1
void DataReceivedHandler(Object^ sender,SerialDataReceivedEventArgs^ e)
2
{
3
  SerialPort^ sp = (SerialPort^)sender;
4
  String^ indata = sp->ReadExisting();
5
  Console::Write(indata);
6
  
7
//  Console::WriteLine(Thread::CurrentThread->GetData);
8
  RS232_empfang("test");
9
  
10
11
}

Meldung:
1>RS232.cpp(24): error C3861: "RS232_empfang": Bezeichner wurde nicht 
gefunden.


Oder versteh ich das falsch?

von bluppdidupp (Gast)


Lesenswert?

Hmm, dein DataReceivedHandler() scheint außerhalb der Klasse definiert 
zu sein? Sollte der nicht unter private stehen?

von Mani (Gast)


Lesenswert?

Hmm in einem Buch das ich genommen hatte wurd das Eventsystem so 
beschrieben, das der Handler zum auslösen außerhalb der Klasse stehen 
soll..

Wenn ich mir ein Handler in der Datareceived erstell stürzt es ab, 
vermutlich weils ins nirgendwo hinzeigt.

Auch wenn ich mein Datareceived Handler unter Privat setz innerhalb 
meiner Klasse, findet der mein RS232_empfang nicht innerhalb der 
Datareceived.

Bisher fand ich alles ziemlich Logisch und Nachvollziehbar aber gerade 
stehe ich auf dem Schlauch.
Mein Event funktioniert auch, weil es innerhalb von RS232_init wird eins 
geworfen und im Form kann ich das abfangen und auf der Console ausgeben.

Ich hab Console als Debugmonitor drin, neben der Form.

von bluppdidupp (Gast)


Lesenswert?

Gut das scheint wohl eine C++/CLI Besonderheit zu sein.
In C# wäre es nichtmal möglich Funktionen außerhalb einer Klasse zu 
definieren ;D

Dann muss wohl jemand mit C++/CLI Kenntnissen her ;D

von Mani (Gast)


Lesenswert?

Ich schätz das es einfach eine globale Variable ist, bzw ein gloaber 
Verweis. Danke dir aber für deine Tipps.
Ich glaub irgendwann geh ich auch nach C#, wollte nur erstmal ein 
Grundgerüst bauen bei CLI.

Hoffe einer hat noch eine Idee zu dem Problem, ich schein wohl 
irgendetwas zu übersehen oder hab was falsch verstanden.

von Mani (Gast)


Lesenswert?

Ich mal wieder..
Ich habe es mal in C# versucht was zu coden.
1
namespace RS232_serialport
2
{
3
    public delegate void RS232_Receive_Handler(string datain);//object sender, EventArgs e);
4
5
    public class RS232
6
    {
7
        private SerialPort SP = new SerialPort("COM1");
8
        public RS232_Receive_Handler _RS232_receive_handler;
9
10
        public RS232()
11
        {
12
13
        }
14
15
        public void RS232_init()
16
        {
17
            SP.BaudRate = 9600;
18
            SP.Parity = Parity.None;
19
            SP.StopBits = StopBits.One;
20
            SP.DataBits = 8;
21
            SP.Handshake = Handshake.None;
22
            SP.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
23
24
            SP.Open();
25
            RS232_empfang("teststring");
26
        }
27
28
        public bool RS232_isopen()
29
        {
30
            if (SP.IsOpen) { return true; }
31
            return false;
32
        }
33
34
        public void RS232_close()
35
        {
36
            SP.Close();
37
        }
38
39
        public void RS232_empfang(string datain)
40
        {
41
           _RS232_receive_handler(datain);
42
        }
43
44
        public void RS232_cons(string datain)
45
        {
46
            RS232_empfang(datain);
47
        }
48
49
        private static void DataReceivedHandler(object sender,SerialDataReceivedEventArgs e)
50
        {
51
            RS232 _rs232 = new RS232();
52
53
            SerialPort sp = (SerialPort)sender;
54
            string indata = sp.ReadExisting();
55
       //     Console.WriteLine("Data Received:");
56
            //    Console.Write(indata);
57
            //_rs232.RS232_cons(indata);
58
            
59
        }
60
61
    }
62
}
Einglich alles wie in C++ nur in C# geschrieben. Aber ich bekomme eine 
Nullexception, sobald ich von der Datareveice ins RS232_empfang(datain); 
geht, da in RS232_empfang scheinbar die 
"_RS232_receive_handler(datain);" nicht mehr auffingbar ist.
Hat einer eine Idee?
Invoke geht bei den Punkt irgendwie nicht und ich find meist nur direkt 
in GUI hilfe in Verbindung mit Invoke.

Ich will einglich die Daten aus dem Reveicehandler rausschicken zu 
meinem eigenen Handler, der dann in einer Gui extra verwaltet wird.

Ist das ungewöhnlich die ganze RS232 geschichte in eine extra Klasse zu 
verpacken, wo auch die ganze Datenverarbeitung drin steckt?
In der GUI wollt ich dann einglich nur aufrufe machen, zb RS232_config, 
init...

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.