Serielleschnittstelle RS232 C++

#2167641
Lesenswert?

Hallo,

ich versuche grade Daten über die RS232 Schnittstelle zu Senden und zu 
Empfangen.

Ich Sende zwei Byte an die Hardware und erwarte dann eine Antwort von ca 
14 Byte.
Mein Programm bleibt allerdings beim Lesen stehen, da ich nicht weiß ob 
er wirklich sendet (hab kein Oszi um zu Messen), denke ich mal er wartet 
auf eine Antwort die nie kommt.

kann es sein das ich zu schnell bin und evt ein wait irgendwo brauche?
ich denke das er den Port richtig öffnet, wenn ich mit einen anderen 
Programm auf den Port nach den öffnen zugreifen will, bekomme ich eine 
Fehlermeldung das der Port bereits verwendet wird.

wäre nett wenn ihr mir weiter helfen könntet.
Ich nutze c++ in Visual Studio

ich habe diese Frage auch in einem anderen Forum gestellt, jedoch 
bekomme ich hier keine Antwort.

ich würde mich auch über eine Alternative Lösung freuen.

danke
Angehängte Dateien:
Gast #2167678
Lesenswert?

warum verwendest du *.txt für c++ dateien?

Das lesen sieht eigentlich gut aus. Ein wait (oder besser Sleep) ist 
nicht notwendig. Aber du beachtest nicht das das die Anzahl die Maximale 
anzahl von bytes ist, das read return dir anzahl der gelesen bytes. Wenn 
also 5 byte ankommen dann kann es schon passieren das read dann schon 
beendet. Damit hast du aber nicht die 14 byte gelesen.

Was macht eigentlich der .net code zwischen deinem C++ code? Oder ist 
das C++.net
#2167697
Lesenswert?

Hallo,

danke für die antwort.

txt einfach nur daher, weil ich die Klasse schnell rauskopiert habe und 
irgendwo zwischenspeichern musste und nicht extra den Compiler starten 
wollte.

der c# Code kommt daher, das ich vorher die ganze Klasse in c# 
geschrieben habe, aber aus Kompatibilitätsgründen es nun doch in c++ 
umsetzen muss.
Ich hatte die Fragmente drin gelassen, weil ich mir nicht Sicher war ob 
der c++ an der Stelle so Funktioniert.
Der c# Code funktioniert einwand frei und Komuniziert auch wunderbar mit 
der Hardware in der c++ Klasse hängt er sich auf.

also in der Beschreibung steht das die Hardware mir 14 Byte als Antwort 
schickt. Hast du eine Lösung oder Ansatz für mich?

gruß
Gast #2167876
Lesenswert?

Fox Xx schrieb:

> gut und nun wartet er bis die kommen restlichen bytes kommen, wenn die
> natürlich nie kommen steht das programm.
> wie löse ich das problem
dann gibt es ein timeout, den kann man bei der schnittstelle einstellen.

>in c# ist das arbeiten mit der rs232 so schön einfach.
nein es ist dort genauso, wenn du es nicht beachtest hast dann hattest 
du bis jetzt glück das es funktioniert

http://msdn.microsoft.com/de-de/library/ms143549.aspx
#2167914
Lesenswert?

Man kann blockierend arbeiten, oder nicht blockierend. Aus Debug- und 
anderen Gruenden wuerd ich nicht blockierend bevorzugen. Man muss auch 
immer damit rechnen, dass das Kabel nicht eingesteckt wurde, resp erst 
nachtraeglich eingesteckt wird, sowie irgendwann gezogen wird. In allen 
Faellen sollte sich die Software nicht aufhaengen. Ein vernuenftiges 
Protokoll hilft da eine Menge
#2168141
Lesenswert?

>>Hex Oschi schrieb:
>> Ein vernuenftiges Protokoll hilft da eine Menge
>
>wenn keine Daten mehr kommen, hilft das Protokoll auch nicht mehr
weiter.

Doch, das Protokol hilft das sich die Software nicht blockiert. Man kann 
das Device dann ja neu booten und die software macht weiter.
Gast #2168182
Lesenswert?

Hex Oschi schrieb:
> Doch, das Protokol hilft das sich die Software nicht blockiert. Man kann
> das Device dann ja neu booten und die software macht weiter.
nein denn ein Protokoll ist nur für den Gut-Fall da, wenn jemand den 
Stecker zieht hilft das Protokoll nicht weiter. Dann muss man mit 
sinnvollen Timeouts arbeiten und dann zu einem Status zurückgehen von 
den man neu beginnen könnte.
#2168538
Lesenswert?

das habe ich noch im Netz gefunden, würde das damit gehen?
Es ist ja möglich noch mehr Register einzustellen, welche wären den noch 
sinnvoll?
1
COMMTIMEOUTS cto;
2
ZeroMemory(&cto,sizeof(COMMTIMEOUTS));
3

4
cto.ReadIntervalTimeout            = 1000;
5
cto.ReadTotalTimeoutMultiplier    = 10;        
6
cto.ReadTotalTimeoutConstant    = 5;
7

8
BOOL bResTimeout = SetCommTimeouts(m_serialcon, &cto);
9

10
if (!bResState )
11
{
12
   return 0;
13
}

also ich denke mal das er hier nach 1000ms das lesen Abbricht oder?
aber was macht Multiplier und Constant?

> wenn du das als cls_COM.c abgespeichert hättest, hätte das länger
> gedauert? Merkwürdig ....

ja, weil ich den Code auf einem Stick hatte aber auf dem Rechner kein 
Compiler
Edit: ok, hätte das natürlich im Editor als .c speichern können, hab ich 
ehrlich gesagt aber auch überhaupt nicht dran gedacht.

> http://msdn.microsoft.com/en-us/library/aa363437%2...

verstehe ich nicht ganz wie ich das genau Programmieren soll, wenn ich 
das richtig verstehe, soll hier die Read Methode in einem anderen Thread 
arbeiten oder?
aber würde der Thread dann nicht auch endlos weiterlaufen wenn keine 
Daten kommen, bzw er würde die Empfangegenen 3 Bytes nie weiter reichen, 
weil er auf die anderen 10 Bytes wartet?

danke und gruß
Gast #2168560
Lesenswert?

dafür muss man mehr wissen was du genau an daten erwartest bzw was von 
der gegenstelle gesendet wird.

Du hast gesagt das die Gegenstelle immer 14byte sendet. Dafür braucht 
man keinen Thread. Du sammelst einfach alle bytes bis du 14 hast und 
dann gibt du es zurück. Wenn du nach ein zu langen zeit nichts 
emfpfängst (über den Timeout festlege) dann muss du entscheiden wie es 
weiter gehen soll. In c++ ist es üblich eine Exception zu werfen.
Gast #2169134
Lesenswert?

Ich hab da auch mal nen Problem gehabt, man mußte zwingend nen 
BuildCommDCB ausführen damit die Kommunikation funktioniert. Weil ALLE 
Elemente müssen initialisiert werden.
Also alle initalisiern oder BuildCommDCB :
typedef struct _DCB {
  DWORD DCBlength;
  DWORD BaudRate;
  DWORD fBinary  :1;
  DWORD fParity  :1;
  DWORD fOutxCtsFlow  :1;
  DWORD fOutxDsrFlow  :1;
  DWORD fDtrControl  :2;
  DWORD fDsrSensitivity  :1;
  DWORD fTXContinueOnXoff  :1;
  DWORD fOutX  :1;
  DWORD fInX  :1;
  DWORD fErrorChar  :1;
  DWORD fNull  :1;
  DWORD fRtsControl  :2;
  DWORD fAbortOnError  :1;
  DWORD fDummy2  :17;
  WORD  wReserved;
  WORD  XonLim;
  WORD  XoffLim;
  BYTE  ByteSize;
  BYTE  Parity;
  BYTE  StopBits;
  char  XonChar;
  char  XoffChar;
  char  ErrorChar;
  char  EofChar;
  char  EvtChar;
  WORD  wReserved1;
} DCB, *LPDCB;

 Nen sch.. Fehler der mir tagelang kopfschmerzen gemacht hat.
#2169220
Lesenswert?

Peter II schrieb:
> dafür muss man mehr wissen was du genau an daten erwartest bzw was von
> der gegenstelle gesendet wird.
>
> Du hast gesagt das die Gegenstelle immer 14byte sendet. Dafür braucht
> man keinen Thread. Du sammelst einfach alle bytes bis du 14 hast und
> dann gibt du es zurück. Wenn du nach ein zu langen zeit nichts
> emfpfängst (über den Timeout festlege) dann muss du entscheiden wie es
> weiter gehen soll. In c++ ist es üblich eine Exception zu werfen.

was musst du den noch genau wissen?

uwe, muss ich wissen was die einzelnen Register bewirken?
einfach vor die Ini packen?
ist der Timeout mit drin?

gruß
Gast #2169226
Lesenswert?

Fox Xx schrieb:
> was musst du den noch genau wissen?

wie das übertragungsprotokoll aussieht. Du behauptest das immer 14 
Zeichen gelesen werden sollen, das wiederspricht sich mit

PortLesen() == ">"

denn das ist nur 1 Zeichen.

Dann ist es wichtig zu wissen ob das Gerät von sich aus sendet oder ob 
du eine Anfrage hinschickt und darauf immer eine Antwort kommt (und in 
welcher zeit).

Wegen UWE:
es ist auch einfach möglich mit GetCommState die alten werte auszulesen 
und dann die werte anzupassen und dann sie wieder mit SetCommState zu 
setzten dann kannst du auf jeden fall keinen Vergessen.
#2169238
Lesenswert?

also das Protokoll sieht so aus:

1. Es werden zwei Byte zwei ASCII zeichen an die Hardware geschickt.
2. Die Hardware schickt einmalig eine Antwort, zB 14 Zeichen.

also das Gerät sendet nicht selber.

ich hatte das oben etwas missverständlich ausgedrück sorry, also 
nochmal.
die Hardware sendet natürlich nicht immer genau 14 Zeichen, ich hatte 
das so geschrieben weil ich dachte ich hätte alle anderen Methoden aus 
der Datei entfernt und bezog mich daher nur auf die Methode 
"PositionLesen()", hier soll die Hardware laut der Beschreibung 14 
Zeichen als Antwort zurück senden, beginnend mit ">".
Laut meinen c# Code Funktioniert dies auch einwandfrei, lediglich in c++ 
bekomme ich es nicht hin.

Die Zeit ist eine gute frage, in meinen c# Code warte ich ein 
Augenblick, aber im Handbuch steht dazu nichts.
Gast #2169263
Lesenswert?

naja dann los.

Schreibe eine funktion die daten von der Serielen schnittstelle abruft 
bis eine CR kommt und sie dann als String zurück liefert

std::string s;
char c;
while( true ) {
  size_t r = readfile( c, 1 ... );
  if ( r != 1 ) {
     throw Exception("Fehler beim empfang");
  }
  if ( c == '\n' ) {
     break;
  }

  s += c;
}

return s;

so in der Art, man könnte auch mehre zeichen gleichzeitig empfangen aber 
man muss dann aber eh einzeln schauen ob das ende erreicht ist - für den 
anfang sollte es so aber gehen.
Gast #2169535
Lesenswert?

Fox Xx schrieb:
> und wenn das CR nie kommt?
> bzw wenn überhaupt nichts kommt?
dann gibt es ja die exception - weil read nicht 1 zurückliefert. Wenn 
aber immer etwas kommt und nie ein \n dann geht dieser code nicht. Aber 
man könnte ja auch noch die länge begrenzen.
Gast #2169944
Lesenswert?

Fox Xx schrieb:
> ennt ihr evt eine Klasse die sich um alles kümmert?
> In der ich nur ein paar Methoden aufrufen muss wie "DatenLesen()"?

was ist denn so schwer daran die funktion so zu schreiben wie ich sie 
schon hingeschrieben habe? Einfacher geht es nun wirklich nicht.
#2170674
Lesenswert?

wird es morgen mal probieren,

was ist mit dem Registern von Uwe und oder dem Timeout?

Uwe schrieb:
> typedef struct _DCB {
>   DWORD DCBlength;
>   DWORD BaudRate;
>   DWORD fBinary  :1;
>   DWORD fParity  :1;
>   DWORD fOutxCtsFlow  :1;
>   DWORD fOutxDsrFlow  :1;
>   DWORD fDtrControl  :2;
>   DWORD fDsrSensitivity  :1;
>   DWORD fTXContinueOnXoff  :1;
>   DWORD fOutX  :1;
>   DWORD fInX  :1;
>   DWORD fErrorChar  :1;
>   DWORD fNull  :1;
>   DWORD fRtsControl  :2;
>   ...
Gast #2170714
Lesenswert?

Versuch es doch mit den Timeout die du oben gefunden hast, etwas passen 
sie oder du musst sie verlängern oder kürzen.

Das von UWE brauchst du nicht wenn du

GetCommState
-> parameter anpassen
SetCommState

machst, den rest kannst du alles so lassen.

Selbst ohne Timeouts geht es, du könnte es passieren wenn jemand den 
stecker zieht das dein programm dann hängt.
Gast #2174718
Lesenswert?

Hallo Fox Xx

in Deinem Code stimmt die Reihenfolge nicht.

DCB dcb;
dcb.DCBlength = sizeof(DCB);

zuerst Port-Config lesen
  GetCommState(m_PortHandle, &dcb)

// Konfigurationen des Ports setzen

wieso hier schon SetCommState und dann erst DCB-Parameter setzen?
Das  gehört hinter dcb.Binary=TRUE

*        if (SetCommState(m_PortHandle, &dcb))
*    {
*    m_StatusMeldung = "Fehler: Konnte Konfigurationen
*                nicht setzen!";
*      return false;
*    }
|
|        dcb.BaudRate    = m_Baudrate;      // Baud Rate
|        dcb.Parity      = m_Parity;        // Parity
|        dcb.ByteSize    = m_Databit;      // Data Bits
|        dcb.StopBits    = m_Stopbit;      // Stop Bits
|        dcb.fBinary = TRUE;
|--->

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