C++ Serielle Schnittstelle leist speichert "falsche" Werte

M1ch1

Lieutenant
Registriert
Nov. 2009
Beiträge
787
Hi
ich hab ein Problem mit der Programierung/abfragen einer Seriellen schnitstelle.

Ich verwende Visual Studio 2015 und dass Projekt wird als C++/CLR konsolenanwendugn geschrieben

Der Verwendete Code: https://msdn.microsoft.com/de-de/library/system.io.ports.serialport.datareceived(v=vs.110).aspx

Dass funktioniert auch so weit, allerdings gibt es bei manchen Zeichen Probleme.

Per Definition gibt es immer 17Bytes an Daten zurück, welche mit einem 0xFD beginnen sollten, und in den Letzten 8 BYtes Sensorwerte codieren sollte, welche im Bereich von 0x80-0x95 liegen sollten.

Nun kommen bei mir auch die 17Byte an, allerdings gibt es bei den hohen werten Fehler.

Mein String:
3F 3 23 6 5 3F 0 11 0 7F 7F 7F 7F 7A 3F 7F 7F

Soll String:
FD 03 23 06 05 EC 00 11 00 7E 80 7F 7F 80 80 7B 7F

Richtig sind also die niedrigen Werte (3 23 6 5 11). Bei den hohen werten gibt es allerdings unterschiede welche ich mir nicht erklären kann.

Auf Empfehlung eines Freundes habe ich auch mal mit static_cast<unsigned> versucht die ausgabe zu "korrigieren", allerdings hat sich dadurch die ausgabe nicht verändert.

Da ich nun leider nicht Tief genug in C++ drin stecke, um nachfolziehen zu können was in meinem kopierten Code abgeht, hoffe ich dass mir hier einer helfen kann.

Grüße
M1ch1

Code:
ref class PortDataReceived  //Quelle:https://msdn.microsoft.com/de-de/library/system.io.ports.serialport.datareceived(v=vs.110).aspx
{
public:
	static void Main()
	{
		SerialPort^ mySerialPort = gcnew SerialPort("COM3");

		mySerialPort->BaudRate = 115200;											//BAudrate von Hterm übernommen
		mySerialPort->Parity = Parity::None;
		mySerialPort->StopBits = StopBits::One;
		mySerialPort->DataBits = 8;
		mySerialPort->Handshake = Handshake::None;
		mySerialPort->RtsEnable = true;

		mySerialPort->DataReceived += gcnew SerialDataReceivedEventHandler(DataReceivedHandler);

		mySerialPort->Open();

		Console::WriteLine("Zum Bendet belibige Taste drücken!");
		Console::WriteLine();
		Console::ReadKey();
		mySerialPort->Close();


	}

private:
	static void DataReceivedHandler(
		Object^ sender,
		SerialDataReceivedEventArgs^ e)
	{
		SerialPort^ sp = (SerialPort^)sender;
		int Bytestoread = sp->BytesToRead;
String^ indata = sp->ReadExisting();
for (int i = 0; i < Bytestoread; i++)
			{
				cout << hex << static_cast<unsigned>(indata[i]);
								}
			}
 
Sind die Parameter vorgegeben?
Sonst verringere mal die Baudrate und vor allem nutze ein Handshake.
 
@miac:
Parameter sind vorgegeben. vondaher kann ich da leider keine Veränderungen vornehmen.

@mo2mk:
Hab jetzt nur kurz überflogen, und werde es mir nacher ncoh genauer durchlesen, aber wenn ich es richtig verstanden habe, beschriebt dass doch lediglich, wie die Daten in die Bytes geschrieben werden (sehr grob gesagt).
Da allerdings nicht alle BYtes falsch interpretiert werden (BYte 2-5 sind korrekt) fällt doch ein fehler dieser art raus? Denn dann müssten diese BYtes doch auch falsch interpretiert werden, oder?
 
Zuletzt bearbeitet:
Ist das denn eine physische Schnittstelle oder was virtuelles?
 
Dann sollte in der Tat Handshake und Baudrate keine Rolle spielen.
Muß man sich die Daten nochmal ansehen.

Du sprichst von einem String. Sind die Daten binär oder als Char formatiert.

Was meinst du mit Soll String?
 
Zuletzt bearbeitet:
als "Soll String" habe ich die Daten bezeichnet, welche ich laut Dokumentation empfangen sollte, und mit Hterm empfange (damit kann ich aber leider nur die Werte anzeigen, ich möchte/muss diese aber weiter verarbeiten)

Da die Daten beim einlesen in einem String^ abgelegt werden, und bei der Ausgabe Fragezeichen und co ausgegeben werden, gehe ich von einem Char aus.

Werde morgen mal schaun, ob es etwas bringt, wenn ich ReadExsiting durch ReadByte ersetze, und den Datentyp auf Array ändere, und somit die gesamte Nachricht BYteweise in dem Array speichere.
 
Nochmal zu Verdeutlichung:
Istwerte sind die, die tatsächlich vorhanden sind, Sollwerte die, die Du erwartest.

Somit sind die Istwerte nicht die Sollwerte und die Istwerte sind im Empfänger falsch.
Ergänzung ()

Bei den Daten hast Du, glaube ich, jetzt erkannt, daß es ein Konvertierungsproblem geben könnte.

Beispiel:
Ziffer 3 benötigt als Char ein Byte und wird als 33h abgelegt.
Ziffer 3 kann aber auch als 3h in einem Halbbyte abgelegt werden.
 
Zuletzt bearbeitet:
Laut deinen Angaben sieht das Protokoll ein 0xFD am Anfang des Datentelegramms vor. Solange das nicht vorhanden ist, muss man davon ausgehen, das du irgend etwas bekommst , aber nicht das gewünschte Telegramm. Wenn du deinen Code so änderst, das du alles wegwirfst bis das erste 0xFD kommt und dann die folgenden Bytes auswertest, sieht dann das Ergebnis plausibel aus ?
 
Ich weiß, dass solche Hinweise auf den ersten Blick immer wenig zielführend sind aber ich kann nur generell Empfehlen bei C++ sehr früh zu überlegen, ob man nicht zumindest QtCore (ohne GUI) verwenden sollte.
Imho ist das genau so wie C++11, STL oder Boost ein wesentlicher Bestandteil, den man nicht ignorieren sollte.
Es gibt einfach keine einfachere und besser dokumentierte C++ Lib und bevor ich mit der WindowsApi auch nur Anfange würde ich immer direkt Qt verwenden weil es nicht nur Plattformunabhängig sondern um länger einfacher zu verwenden ist:
http://doc.qt.io/qt-5/qtserialport-index.html
http://doc.qt.io/qt-5/qtserialport-terminal-example.html
Natürlich nervt es immer so einen 'Umweg' zu machen, wenn man denkt man wäre schon beinahe am Ziel.
Aber spätestens wenn du dann weiter machst, einen eigenen Receiver-Thread willst und per Event informiert werden willst sobald Daten verfübar sind wirst du dich freuen wie einfach das in Qt geht.
 
Zuletzt bearbeitet:
Bei Qt hast du halt immer einen riesen Rattenschwanz hinten dran, der noch um Welten größer ist als bei Boost (von der STL gar nicht zu reden).

Hast du schonmal versucht Qt static zu linken auf Windows? Dann weißt du was ich meine. Und jedes mal xxxx Dlls mitgeben ist für mich auch keine Lösung!
 
@kuddlmuddl was der TE da nutzt, ist schon kein reinrassiges C++ mehr, sondern .NET C++. Insofern hat er da schon ein Framework.
 
kein reinrassiges C++ mehr, sondern .NET C++. Insofern hat er da schon ein Framework.
Das war der Grund für mich zu schreiben.. denn wie toll es mit .NET funktioniert sieht man ja ;)
Ich wollte ihm halt ersparen viel Zeit/Lernen im .NET Framework zu 'versenken' was weder richtig plattformunabhängig ist noch das beste (imho).

Bei Qt hast du halt immer einen riesen Rattenschwanz hinten dran, der noch um Welten größer ist als bei Boost (von der STL gar nicht zu reden).
Wie gesagt: Man muss natürlich die dll mitliefern aber solange man auf UI verzichtet ist das extrem wenig. Der Ram-Verbraucht durch Qt steigt um weniger als 2MB. Außerdem: Schon beim schreiben eines Programms Festplattenplatz beim Kunden sparen zu wollen hört sich für mich nach typischem Premature Optimization (Link2) an. Wo ist das Problem wenn die Entwicklung doppelt so schnell geht und man dafür ein paar MB auf der Festplatte verbraucht?

Hast du schonmal versucht Qt static zu linken auf Windows? Dann weißt du was ich meine. Und jedes mal xxxx Dlls mitgeben ist für mich auch keine Lösung!
Nein ich linke immer dynamisch, da man nur dann kommerziell verwendete Programme schreiben darf ohne an Qt zu zahlen. Wieso auch nicht? Wenn jemand einen Software-Installer ausführt sind eh zig Dateien dabei - wieso nicht auch 2, 3 dlls von Qt?
 
Zuletzt bearbeitet:

Ähnliche Themen

Zurück
Oben