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
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
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ß
Fox Xx schrieb: > (hab kein Oszi um zu Messen) dann häng doch mal einen anderen PC dran (oder eine andere Schnittstelle auf dem PC, auf das Programm läuft) und schau, ob der was empfängt...
Fox Xx schrieb: > lso in der Beschreibung steht das die Hardware mir 14 Byte als Antwort > schickt. Hast du eine Lösung oder Ansatz für mich? ja, warte bis du 14 byte zuammen hast. Wenn du erst 4 byte ampfangen hast dann musst noch auf weitere 10byte warten.
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 in c# ist das arbeiten mit der rs232 so schön einfach.
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
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
Hex Oschi schrieb: > Ein vernuenftiges Protokoll hilft da eine Menge wenn keine Daten mehr kommen, hilft das Protokoll auch nicht mehr weiter.
wie soll das protokoll aussehen? also ich denke in c# wird der timeout wohl irgend ein default haben, wundert mich das der in c++ kein hat. könnt ihr mir beim einstellen des timeouts helfen?
Fox Xx schrieb: > könnt ihr mir beim einstellen des timeouts helfen? http://msdn.microsoft.com/en-us/library/aa363437%28v=vs.85%29.aspx
> txt einfach nur daher, weil ich die Klasse schnell rauskopiert habe > und irgendwo zwischenspeichern musste wenn du das als cls_COM.c abgespeichert hättest, hätte das länger gedauert? Merkwürdig ....
>>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.
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.
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ß
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.
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.
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ß
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.
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.
Fox Xx schrieb: > Zeichen als Antwort zurück senden, beginnend mit ">". steht eventuell auch etwas über das ende drin? Zeilenumbruch? 0byte? Ohne ein Definiertes ende ist das Protokoll müll. Könnte ja sein das nach 10min noch etwas kommt.
nein,
>xxxxxxxxxxxxx
wobei x für Zahlen als ASCII stehen
also in c# hatte ich immer sofort die Antwort.
Fox Xx schrieb: > wobei x für Zahlen als ASCII stehen > also in c# hatte ich immer sofort die Antwort. und woher weiss du das die entwort vollständig war? Schau doch mal nach ob am ende ein 0x13 oder 0x12 kommt.
ok, nochmal sorry,*schäm "ES werden alle Antworttelegramme mit einen CR (=hex13) vervollständigt." "xxxxxxxx>"
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.
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.
kennt ihr evt eine Klasse die sich um alles kümmert? In der ich nur ein paar Methoden aufrufen muss wie "DatenLesen()"?
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.
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; > ...
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.
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; |--->
hi eine weitere frage zur rs232, wenn ich jetzt keine ASCII Zeichen senden will, sondern Hex bzw Dezimal, gibt es da eine Lösung? gruß
Fox Xx schrieb: > wenn ich jetzt keine ASCII Zeichen senden will, sondern Hex bzw Dezimal, > gibt es da eine Lösung? ja. Wo sieht du den unterschied zwischen ASCII Hex und Dezimal? Wenn du dir darüber klar bist, dann sollte es auch klar sein wie man sie sendet.
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.