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
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.