Hallo zusammen, ich versuche eine serielle Schnittstelle mithilfe von C++ auszulesen. Ich habe mich vorher auf Google und im Forum umgeschaut und leider nichts passendes zu meiner eigenen Anwendung gefunden (Korrekturen werden einem nicht übel genommen :-D) Zunächst einmal mein Code: //Headerdateien #include <stdio.h> //Standard Input/Output Bibliothek #include <Windows.h> //Hauptprogramm Start int main() { //Öffnen der seriellen Schnittstelle DCB sDcb; HANDLE hFile; COMMTIMEOUTS sTo; hFile=CreateFile("\\\\.\\COM1",GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXIST ING,FILE_ATTRIBUTE_NORMAL,0); if(hFile==INVALID_HANDLE_VALUE)return 0; memset(&sDcb,0,sizeof(sDcb)); sDcb.DCBlength = sizeof(sDcb); sDcb.BaudRate = 9600; // Baudrate sDcb.fParity = FALSE; sDcb.fBinary = TRUE; sDcb.Parity = NOPARITY;// Kein Paritybit sDcb.StopBits = ONESTOPBIT; sDcb.fOutxCtsFlow = FALSE; sDcb.fOutxDsrFlow = FALSE; sDcb.fDtrControl = DTR_CONTROL_ENABLE; sDcb.fRtsControl = RTS_CONTROL_ENABLE; sDcb.fDsrSensitivity = FALSE; sDcb.fAbortOnError = FALSE; sDcb.ByteSize = 8; // 8 Datenbits if(!SetCommState(hFile,&sDcb)) { CloseHandle(hFile); return 0; } sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Tomeout sTo.ReadTotalTimeoutMultiplier = 0; sTo.ReadTotalTimeoutConstant = 0; sTo.WriteTotalTimeoutMultiplier= 1; // 1*2 ms Write Timeout sTo.WriteTotalTimeoutConstant = 2; if(!SetCommTimeouts((HANDLE)hFile,&sTo)) { CloseHandle(hFile); return 0; } //Lesezugriff auf die serielle Schnittstelle DWORD dwCount; char cData[16]; ReadFile(hFile,cData,16,&dwCount,0); return 0; } Mit diesem Code bekomme ich folgenden Compilerfehler: Fehler 1 error C2664: 'CreateFileW': Konvertierung des Parameters 1 von 'const char [9]' in 'LPCWSTR' nicht möglich c:\users\master\documents\visual studio 2012\projects\rs232_auslesen_02\rs232_auslesen_02\rs232_auslesen_02.cpp 23 1 RS232_auslesen_02 Das Beispiel habe ich von folgender Seite: http://members.inode.at/anton.zechner/az/Seriell.htm Jetzt möchte ich gerne wissen ob jemand weiß was das Problem ist. Außerdem würde es mich interessieren ob das wirklich die einfachste Art und Weiße ist die Daten aus der seriellen Schnittstelle zu lesen. Für meine Anwendung ist es nur notwendig, dass ich die Daten danach noch im C++ Programm weiterverarbeiten kann. Eventuell notwendige Bibliotheken oder Programme für einfachere Lösungen können ohne Probleme installiert werden. Ich möchte auch noch anmerken das ich ein ziemlich blutiger Anfänger mit C++ bin. Außer einem Semester in meinem Grundstudium habe ich keine Erfahrung damit. Vielen Dank im voraus für eure Hilfe Spezies31
Stefan F. schrieb: > Fehler 1 error C2664: 'CreateFileW': Konvertierung des Parameters 1 > von 'const char [9]' in 'LPCWSTR' nicht möglich du hast eine Unicode projekt und übergibst kein Unicode. teste mal mit CreateFile(TEXT("\\\\.\\COM1"), ....
Hallo Peter II, danke ich hatte nur die Lösung gefunden den Zeichensatz nicht festzulegen aber so ist das natürlich angenehmer (kann man nicht vergessen). Ich hätte zudem noch drei andere Fragen: 1. Wird mit dem oberen Code die Serielle Schnittstelle dauernd abgefragt? Also bekomme ich immer den aktuellen Wert oder bekomme ich nur einen Wert. 2. Warum funktioniert meine Dauerschleife nicht (nachträglich eingefügt)? Code der Dauerschleife: ... while(TRUE) { ... Sleep(1000); } ... Die Dauerschleife soll das Datenabfragen nur immer wieder wiederholen, da beim Starten der .exe das Fenster sofort wieder zugeht (Sonst sehe ich ja nichts). 3. Ich lese beim googeln immer wieder von Lösungen mit dem "serialport"-Befehl und das man dafür das .Net Framework installiert haben muss. Könnte jemand kurz und prägnant die Möglichkeiten eine serielle Schnittstelle auszulesen aufzählen? Nur damit ich mal einen Überblick habe was es da alles gibt und was die vermutlich schnellste Technik in meinem Fall ist. Mit freundlichen Grüßen Spezies31
Stefan F. schrieb: > 1. Wird mit dem oberen Code die Serielle Schnittstelle dauernd > abgefragt? Also bekomme ich immer den aktuellen Wert oder bekomme ich > nur einen Wert. sie wird so oft gelesen wie du read aufrufst
1 | DWORD dwCount; |
2 | char cData[16]; |
3 | |
4 | ReadFile(hFile,cData,16,&dwCount,0); |
hier liest du maximal 16 zeichen (im return von ReadFile steht die anzahl die wirklich gelesen wurden). Wenn du noch mehr lesen musst, dann musst du halt readFile mehrfach ausführen. > Warum funktioniert meine Dauerschleife nicht (nachträglich > eingefügt)? wo hast du sie eingefügt und was macht sie nicht?` > Könnte jemand kurz und prägnant die Möglichkeiten eine > serielle Schnittstelle auszulesen aufzählen? du hast doch schon alles was du brauchst, was fehlt dir denn da noch?
Hallo Peter II, erstmal danke für die Antwort. Zunächst mal erkläre ich was ich tun will. Ich will zeitlich unbegrenzt (24/7) die Daten einer seriellen Schnittstelle (RS232) in regelmäßigen Abständen lesen und den aktuellen Wert in einer Variablen speichern. Meine Idee dafür war, das ich einfach über den ReadFile Befehl eine Endlosschleife mit Wartezeit verwende. Diese habe ich wie folgt eingebaut: //Headerdateien #include <stdio.h> //Standard Input/Output Bibliothek #include <Windows.h> //Hauptprogramm Start int main() { while(TRUE) { //Öffnen der seriellen Schnittstelle DCB sDcb; HANDLE hFile; COMMTIMEOUTS sTo; hFile=CreateFile(TEXT("\\\\.\\COM1"),GENERIC_READ|GENERIC_WRITE,0,0,OPEN _EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hFile==INVALID_HANDLE_VALUE)return 0; memset(&sDcb,0,sizeof(sDcb)); sDcb.DCBlength = sizeof(sDcb); sDcb.BaudRate = 9600; // Baudrate sDcb.fParity = FALSE; sDcb.fBinary = TRUE; sDcb.Parity = NOPARITY;// Kein Paritybit sDcb.StopBits = ONESTOPBIT; sDcb.fOutxCtsFlow = FALSE; sDcb.fOutxDsrFlow = FALSE; sDcb.fDtrControl = DTR_CONTROL_ENABLE; sDcb.fRtsControl = RTS_CONTROL_ENABLE; sDcb.fDsrSensitivity = FALSE; sDcb.fAbortOnError = FALSE; sDcb.ByteSize = 8; // 8 Datenbits if(!SetCommState(hFile,&sDcb)) { CloseHandle(hFile); return 0; } sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Tomeout sTo.ReadTotalTimeoutMultiplier = 0; sTo.ReadTotalTimeoutConstant = 0; sTo.WriteTotalTimeoutMultiplier= 1; // 1*2 ms Write Timeout sTo.WriteTotalTimeoutConstant = 2; if(!SetCommTimeouts((HANDLE)hFile,&sTo)) { CloseHandle(hFile); return 0; } //Lesezugriff auf die serielle Schnittstelle DWORD dwCount; char cData[16]; ReadFile(hFile,cData,16,&dwCount,0); Sleep(1000); } return 0; } So wie ich das verstanden habe sollte mit diesem Code jede Sekunde eine Com-Schnittstelle geöffnet werden und 16 Zeichen aus der RS232 Schnittstelle lesen. Allerdings verstehe ich dann nicht so richtig woher das Programm weiß wo/wann das Startbit kommt (sprich die Synchronisation). Wie ich mir dann den effektiven Wert der Nachricht (z.B. Gewicht in kg oder eine Länge in Metern) aus der Nachricht rausziehe ist mir erstmal egal. Es geht mir nur darum mal in einem Wort oder Byte die Informationen einer Nachrichtenübertragung zu speichern. Zu meiner Frage nach den Möglichkeiten zum auslesen von RS232 Schnittstellen wollte ich auf vielleicht bekannte Bibliotheken raus mit denen man durch ein paar Zeilen Code ziemlich einfach eine RS232 Schnittstelle auslesen kann. Beim googeln habe ich schon ein paar gefunden wie z.B.: http://www.teuniz.net/RS-232/ Ich habe mich dann aber für den (anscheinend) Standardweg mit den ReadFile-Befehlen entschieden und mir ein Beispiel an folgendem Code genommen habe: http://www.progforum.com/showthread.php?5504-RS232-Schnittstelle-mit-C-auslesen Ich verwende Visual Studio 2012 SP4. Die meisten der von mir gefundenen Bibliotheken gibt es aber nicht für dieses Visual Studio und verursachen bei mir Compilerfehler (kann auch sein das ich evtl. etwas beim einbinden falsch mache da bin ich mir nicht so sicher).
Stefan F. schrieb: > Meine Idee dafür war, das ich einfach über den ReadFile Befehl eine > Endlosschleife mit Wartezeit verwende. Diese habe ich wie folgt > eingebaut: naja, warum ständig den Port öffnen und dann nicht mal schließen? Normalerweise öffnet man ihn einmal und liest ihn dann regelmäßig aus. Nur wenn es einen fehler gibt, kann man ihn erneut öffnen. > . Allerdings verstehe ich dann nicht so richtig woher > das Programm weiß wo/wann das Startbit kommt (sprich die > Synchronisation). dem Programm ist das egal, es kommt von der Hardware ein zeichen an und das liest du aus. Start und Stop macht schon selbständig die Hardware. Das Programm könnte so aussehen Port öffnen while(1) { Daten lesen If Fehler beim Lesen { Port schließen Port öffnen } } Port schließen > Zu meiner Frage nach den Möglichkeiten zum auslesen von RS232 > Schnittstellen wollte ich auf vielleicht bekannte Bibliotheken raus mit > denen man durch ein paar Zeilen Code ziemlich einfach eine RS232 > Schnittstelle auslesen kann. Beim googeln habe ich schon ein paar > gefunden wie z.B.: ich verstehe nicht, was man an den 4 Funktionen noch vereinfachen will CreateFile SetCommState SetCommTimeouts ReadFile Auch mit einer Lib musst du die Timeouts und Parameter setzen, genauso musst du ein Read machen. Was erhoffst du dir von einer Lib? Es gibt auch keine lib für eine while-schleife. Beim suchen ein passenden Lib hast du mehr zeit verbracht als mit dem eigentlichen Programm.
Hallo Peter II, erstmal wieder Danke für die schnelle und gute Antwort. Mein Programm läuft jetzt so wie ich es mir vorgestellt habe. Mein Code sieht jetzt so aus:
1 | //Headerdateien
|
2 | |
3 | #include <stdio.h> //Standard Input/Output Bibliothek |
4 | #include <Windows.h> //Funktionen für die Kommunikation über RS232 |
5 | |
6 | |
7 | //Hauptprogramm Start
|
8 | |
9 | int main() |
10 | {
|
11 | |
12 | //Öffnen der seriellen Schnittstelle
|
13 | |
14 | DCB sDcb; |
15 | HANDLE hFile; |
16 | COMMTIMEOUTS sTo; |
17 | |
18 | |
19 | hFile=CreateFile(TEXT("\\\\.\\COM1"),GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); |
20 | if(hFile==INVALID_HANDLE_VALUE)return 0; |
21 | memset(&sDcb,0,sizeof(sDcb)); |
22 | sDcb.DCBlength = sizeof(sDcb); |
23 | sDcb.BaudRate = 9600; // Baudrate |
24 | sDcb.fParity = FALSE; |
25 | sDcb.fBinary = TRUE; |
26 | sDcb.Parity = NOPARITY;// Kein Paritybit |
27 | sDcb.StopBits = ONESTOPBIT; |
28 | sDcb.fOutxCtsFlow = FALSE; |
29 | sDcb.fOutxDsrFlow = FALSE; |
30 | sDcb.fDtrControl = DTR_CONTROL_ENABLE; |
31 | sDcb.fRtsControl = RTS_CONTROL_ENABLE; |
32 | sDcb.fDsrSensitivity = FALSE; |
33 | sDcb.fAbortOnError = FALSE; |
34 | sDcb.ByteSize = 8; // 8 Datenbits |
35 | |
36 | if(!SetCommState(hFile,&sDcb)) |
37 | {
|
38 | CloseHandle(hFile); |
39 | return 0; |
40 | }
|
41 | |
42 | sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Tomeout |
43 | sTo.ReadTotalTimeoutMultiplier = 0; |
44 | sTo.ReadTotalTimeoutConstant = 0; |
45 | sTo.WriteTotalTimeoutMultiplier= 1; // 1*2 ms Write Timeout |
46 | sTo.WriteTotalTimeoutConstant = 2; |
47 | if(!SetCommTimeouts((HANDLE)hFile,&sTo)) |
48 | {
|
49 | CloseHandle(hFile); |
50 | return 0; |
51 | }
|
52 | |
53 | |
54 | |
55 | //Lesezugriff auf die serielle Schnittstelle (komplett)
|
56 | |
57 | //Dauerschleife für ständiges Lesen
|
58 | |
59 | while(1) |
60 | {
|
61 | |
62 | //einzelner Lesezugriff
|
63 | DWORD dwCount; |
64 | char cData[1]; |
65 | |
66 | ReadFile(hFile,cData,1,&dwCount,0); //Lesen von 1 Byte (Größe einer char-Variablen) an Daten |
67 | |
68 | printf_s("Folgender Char wurde gelesen: %c \n",cData[0]); |
69 | |
70 | |
71 | //Wenn ein Fehler auftritt erneutes öffnen des COM Ports
|
72 | |
73 | if(ReadFile==FALSE) |
74 | {
|
75 | //Öffnen der seriellen Schnittstelle
|
76 | |
77 | DCB sDcb; |
78 | HANDLE hFile; |
79 | COMMTIMEOUTS sTo; |
80 | |
81 | |
82 | hFile=CreateFile(TEXT("\\\\.\\COM1"),GENERIC_READ|GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); |
83 | if(hFile==INVALID_HANDLE_VALUE)return 0; |
84 | memset(&sDcb,0,sizeof(sDcb)); |
85 | sDcb.DCBlength = sizeof(sDcb); |
86 | sDcb.BaudRate = 9600; // Baudrate |
87 | sDcb.fParity = FALSE; |
88 | sDcb.fBinary = TRUE; |
89 | sDcb.Parity = NOPARITY;// Kein Paritybit |
90 | sDcb.StopBits = ONESTOPBIT; |
91 | sDcb.fOutxCtsFlow = FALSE; |
92 | sDcb.fOutxDsrFlow = FALSE; |
93 | sDcb.fDtrControl = DTR_CONTROL_ENABLE; |
94 | sDcb.fRtsControl = RTS_CONTROL_ENABLE; |
95 | sDcb.fDsrSensitivity = FALSE; |
96 | sDcb.fAbortOnError = FALSE; |
97 | sDcb.ByteSize = 8; // 8 Datenbits |
98 | |
99 | if(!SetCommState(hFile,&sDcb)) |
100 | {
|
101 | CloseHandle(hFile); |
102 | return 0; |
103 | }
|
104 | |
105 | sTo.ReadIntervalTimeout = MAXDWORD; // 0 ms Read-Tomeout |
106 | sTo.ReadTotalTimeoutMultiplier = 0; |
107 | sTo.ReadTotalTimeoutConstant = 0; |
108 | sTo.WriteTotalTimeoutMultiplier= 1; // 1*2 ms Write Timeout |
109 | sTo.WriteTotalTimeoutConstant = 2; |
110 | if(!SetCommTimeouts((HANDLE)hFile,&sTo)) |
111 | {
|
112 | CloseHandle(hFile); |
113 | return 0; |
114 | }
|
115 | |
116 | }//IF-Anweisung zu für Neuöffnung des Ports bei einem Fehler |
117 | |
118 | }//Endlosschleife zu |
119 | |
120 | |
121 | return 0; |
122 | }
|
Tut mir leid wegen der etwas verschobenen Formatierung. Ich habe einen Befehlssatz gefunden "ComTools.h" und "ComTools.cpp" mit denen man es in 5 Zeilen Code machen kann. Aber ich finde die Version mit windows.h wesentlich übersichtlicher. Warum ich nach anderen Möglichkeiten gefragt habe, war weil ich etwas verwirrt war wie das alles von statten gehen soll. Jetzt läuft die Übertragung aber und ich denke ich habe es verstanden. Vielen Dank nochmal für deine Hilfe. Falls ich noch Probleme habe melde ich mich nochmal. --- Wenn Du den Text oberhalb des Texteingabefeldes gelesen hättest, wüsstest Du, daß dieses Forum Tags für die Quelltextformatierung anbietet ... [ c ] [ /c ] -rufus
:
Bearbeitet durch User
Stefan F. schrieb: > Mein Code sieht jetzt so aus: warum ist der code zum öffnen der Schnittstelle Doppelt? Code den man mehrfach braucht legt man in eine Funktion.
1 | ReadFile(hFile,cData,1,&dwCount,0); |
warum wertest du den Return code nicht aus?
1 | if(ReadFile==FALSE) |
wo kommt denn ReadFile her? Und warum schließt du den Comport am ende nicht? (oder auch wenn ein Fehler aufgetreten ist)
Stefan F. schrieb: > if(ReadFile==FALSE) Das ist garantiert nicht das, was Du willst. Vor allem: Das ist nie FALSE, denn ReadFile ist eine Funktion, und die hat eine Adresse, und die ist nicht Null.
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.