Hallo Freunde, ich möchte mit Microsoft Visual Studio in einem C-Programm über eine serielle Schnittstelle (RS232) auf einem Windowsrechner mit einem Mikrocontroller (MSP430G2335) kommunizieren. Leider finde ich nur Beispiele für Linux und/oder C++ bzw C# (http://msdn.microsoft.com/) Wäre für jede Hilfe (Tipps, Links, etc.) sehr dankbar!! Danke im Vorraus. Christian
:
Verschoben durch User
Schonmal nach "msdn rs232 c" gegoogelt ? ... Aber mal ganz im ernst..wenn du schon VisualStudio und Windows hast dann nimm doch C# .. macht wesentlich mehr Spaß..
Hab da nu glaubich was interessantes gefunden: http://msdn.microsoft.com/en-us/library/ff802693.aspx Leider in Englisch :(
Christian schrieb: > Leider in Englisch :( Hm, wenn du so auf dem Kriegsfuß mit englisch stehst, wie wäre es denn dann für dich mit VBA (Visuelles Basic für Applikationen)? Das gibt es auch auf deutsch. http://de.wikipedia.org/wiki/Visual_Basic_for_Applications
Wegstaben Verbuchsler schrieb: > Christian schrieb: >> Leider in Englisch :( > > Hm, wenn du so auf dem Kriegsfuß mit englisch stehst, wie wäre es denn > dann für dich mit VBA (Visuelles Basic für Applikationen)? Das gibt es > auch auf deutsch. > > http://de.wikipedia.org/wiki/Visual_Basic_for_Applications Ich möchte mit C Programmieren ;)
Christian schrieb: > Ich möchte mit C Programmieren ;) na gut, dann hier dei Übersetzung der Microsoft-Seite: https://translate.google.de/translate?sl=en&tl=de&js=y&prev=_t&hl=de&ie=UTF-8&u=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fff802693.aspx&edit-text=&act=url
Ich blick da irgendwie noch nicht ganz durch. Es gibt wohl eine .NET und eine WINAPI. Weiß grad ehrlich gesagt noch nicht ganz wie ich vorgehen soll..
Christian schrieb: > Weiß grad ehrlich gesagt noch nicht ganz wie ich vorgehen soll.. wenn du C Programmieren will, dann kannst du wohl kaum die .net API nutzen. Wo ist also dein Problem?
Wenn ich das richtig verstanden habe sollte es mit (write,read,open ...) gehen??
Christian schrieb: > Wenn ich das richtig verstanden habe sollte es mit (write,read,open ...) > gehen?? nein, open wird nicht gehen. Createfile wird auch in dem link in der MSDN verwendet.
Wie kommst du darauf? Das ist doch pures C. Übrigens auf lange Sicht wirst du nicht um Englisch herumkommen. Man braucht allerdings auch kein gutes Englisch um das zu verstehen.
TriHexagon schrieb: > Wie kommst du darauf? Das ist doch pures C. Reading osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); Ist doch entweder nur Struktur oder damit wird ne Membervariable einer Klasseangesprochen oder nich? Und ne Struktur seh ich hier grad nicht???
Ne osReader wurde so deklariert:
1 | OVERLAPPED osReader = {0}; |
OVERLAPPED ist eine Struktur aus der WinAPI und sieht so aus:
1 | typedef struct _OVERLAPPED { |
2 | ULONG_PTR Internal; |
3 | ULONG_PTR InternalHigh; |
4 | union { |
5 | struct { |
6 | DWORD Offset; |
7 | DWORD OffsetHigh; |
8 | };
|
9 | PVOID Pointer; |
10 | };
|
11 | HANDLE hEvent; |
12 | } OVERLAPPED, *LPOVERLAPPED; |
Christian schrieb: > Reading > osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); > > Ist doch entweder nur Struktur oder damit wird ne Membervariable einer > Klasseangesprochen oder nich? > Und ne Struktur seh ich hier grad nicht??? wobei man das eigentlich gar nicht braucht. Für den Anfang reicht einfach read und write. OVERLAPPED wird du nicht brauchen.
CreateFile fürs Öffnen des Ports. ReadFile/WriteFile für Lesen/Schreiben (Allerdings blockierend) CloseHandle für Schliessen des Ports. BuildCommDCB ist noch recht nützlich für die Serial-Port-Parameter. Die OVERLAPPED-Struktur braucht man bei Asynchronen Dateizugriffen (nicht blockierend) in Verbindung mit Events.
Wobei ich nun zwei unterschiedliche Varianten gefunden habe.. http://www.zeiner.at/informatik/c/serialport.html und http://msdn.microsoft.com/en-us/library/ff802693.aspx kann man da sagen welche besser ist? bzw worin die sich unterscheiden?
Christian schrieb: > Wobei ich nun zwei unterschiedliche Varianten gefunden habe.. > http://www.zeiner.at/informatik/c/serialport.html den vergisst du gleich wieder. Mit _inp bzw. _outp direkt an den Portbausteinen rumzufummeln, hat man vor 30 Jahren gemacht. Jedes noch so schmalbrüstige Betriebssystem, das den Namen Betriebssystem auch verdient, darf dir das nicht zulassen. Gewöhn dich daran, mit dem Betriebssystem zu arbeiten und nicht dagegen. > http://msdn.microsoft.com/en-us/library/ff802693.aspx > > kann man da sagen welche besser ist? bzw worin die sich unterscheiden? Ich versteh schön langsam ehrlich nicht mehr, wo jetzt dein Problem ist. Es wurde doch schon alles gesagt: Die serialle Schnittstelle programmierst du in erster Linie wie einen Dateizugriff. Du öffnest die 'Datei', du schreibst auf die 'Datei', du liest von der 'Datei' und wenn du fertig bist, dann schliesst du die 'Datei' wieder. Das alles unterscheidet sich nur wenig davon, wie man mit einer echten Datei auf einer Festplatte arbeiten würde. Die einzige Komplikation entsteht, wenn man asynchron auf eingehende Bytes auf der Seriellen reagieren möchte. Damit kann man sich beschäftigen, für die ersten Schritte und fürs erste Rumprobieren kann man dieses Thema aber auch erst mal links liegen lassen. Wenn du einfach mal anfangen würdest und deine ersten Testprogramme zum Thema 'serielle Schnittstelle' schreiben würdest, anstatt das Web nach einem Link abzusuchen, in dem du genau den Code findest der genau das tut, was du möchstest (und den du so nicht finden wirst), dann wärst du schon längst weiter. Jetzt sind fast 24 Stunden vergangen und du hast noch kein einziges Testprogramm zusammen gestellt, das einfach mal die Seriell öffnet, ein paar Bytes rausbläst und die Serielle wieder schliesst. Da hätte man die Thematik ja auch Schritt für Schritt lernen können
:
Bearbeitet durch User
Das Problem was er hat ist, dass er keine minimale Lösung findet und er sich jetzt nicht näher mit der RS232 WinAPI Kommunikation auseinandersetzten will. Kurz gesagt will er ein kleines Codestück, dass er kopieren und einfügen will. Also mit möglichst wenig Aufwand. Er findet allerdings keines und anstatt sich nun einfach mal die Microsoft Seite durchzulesen, sucht er weiter im Internet. Wenn er sich gestern die Seite genauer angeschaut hätte, wäre er schon längst fertig. Und nein du brauchst kein "Overlapped I/O" und somit schrumpft der Code den du brauchst auf vielleicht 10% von dem was da alles auf der Seite steht. Wenn du C benutzen willst, musst du auch mehr Arbeit reinstecken und dich mit Details auseinandersetzten. Das ist der Preis. Bei C# hat man das Thema RS232 mit vielleicht drei Zeilen erledigt.
TriHexagon schrieb: > Wenn du C benutzen willst, musst du auch mehr Arbeit reinstecken und > dich mit Details auseinandersetzten. Das ist der Preis. Ganz genau! Christian schrieb: > Wobei ich nun zwei unterschiedliche Varianten gefunden habe.. > http://www.zeiner.at/informatik/c/serialport.html > und > http://msdn.microsoft.com/en-us/library/ff802693.aspx > > kann man da sagen welche besser ist? bzw worin die sich unterscheiden? Vergiss es, low level wird meines Wissens seit XP nicht mehr ohne Weiteres unterstützt und das aus gutem Grund! CREATEFILE und Co. sind deine Freunde, wenn du in C auf der API programmieren willst. Grundlagen zum Thema API-Programmierung (nicht RS232 explizit, aber Filezugriff) liefert dir Charles Petzold. Bedeutet Arbeit und 'ne Menge Code. Ebenfalls solltest du dich mit der DCB-Struktur beschäftigen, über die die Config der RS232 läuft. Wenn deine Anwendung dann nicht-blockierend, also asynchron, empfangen können soll, dann brauchst du Threads, was auch einige Arbeit mit WINAPI bedeutet. C# bietet dir hier schon Lösungen an, auch solche mit Threads, die vergleichsweise wirklich kurz und bündig sind.
:
Bearbeitet durch User
g. b. schrieb: > Vergiss es, low level wird meines Wissens seit XP nicht mehr ohne > Weiteres unterstützt und das aus gutem Grund! Nicht erst seit XP, das ist so schon seit Windows NT 3.1. Und sinnvoll ist es, weil direkte Port-Zugriffe natürlich nur mit den Schnittstellen funktionieren würden, die sich hinter diesen I/O-Ports verbergen. Hinter welchen I/O-Ports aber verbergen sich virtualisierte Schnittstellen wie USB-Seriell-Wandler? Und wie findet man die I/O-Ports heraus, die beispielsweise die Schnittstellen auf PCI-Karten verwenden? Da ist das Konzept, die vom System vorgesehenen Devicetreiber zu verwenden, deutlich überlegen.
Warum das Rad zum 100. mal neu erfinden? Speziell für die serielle Schnittstelle gibt es mehr als genügend fertige Lösungen. Ich persönlich bevorzuge die liboapc: https://git.fedorahosted.org/cgit/OpenAPC.git/tree/liboapc Ist Open Source, funktioniert unter Windows und Linux gleichermaßen, ist ausgereift und kann auch noch einiges mehr.
Harstad schrieb: > Warum das Rad zum 100. mal neu erfinden? man könnte aber auch sagen, warum ein zusätzlich lib verwenden die eventuell auch fehler hat und die man updaten muss, wenn die Api schon alles bietet was man braucht und diese Software nie unter Linux laufen muss.
Peter II schrieb: > wenn die Api schon > alles bietet was man braucht Die Erfahrung zeigt, daß die API und vor allem ihre Dokumentation so ... komplex ist, daß es insbesondere Anfängern nur selten gelingt, ein stabil laufendes Programm zu konstruieren. Die liboapc allerdings ist kein hilfreicher Vorschlag für jemanden, der in C programmieren möchte. (NB: Ich kenne und nutze die Win32-API seit über 20 Jahren).
:
Bearbeitet durch User
Rufus Τ. Firefly schrieb: > Nicht erst seit XP, das ist so schon seit Windows NT 3.1. Gut, NT hatte ich da mal weggelassen, weil damals ja bei den meisten Privatanwendern Win95, 98 und XP lief. Ein Grund, der mir einfiel, soweit ich mich zurückerinnern kann, war, dass sich die low level - Programmierung dem System weitestgehend entzog. Wenn dann eine 2. Applikation auf dieselbe Ressource zugreifen wollte, dann kam es nicht selten zu Abstürzen. Mit XP hatte man da neben NT dann den Riegel aus gut verständlichen Gründen vorgeschoben. Mit der API32 ist man über den Filezugriff so auf der sichereren Seite. Ausnahme war da mal ein Tool, das den direkten Portzugriff auf den LPT unter XP zulies, womit man aber das alte Problem wieder riskierte. Damit konnte man dann aber alte Hardware noch notbetreiben. Wir hatten in der Firma mal einen Programmieradapter für ein Tool, für das es keinen Nachfolger mehr gab. Da lohnte der Einsatz. Aber auch nur dort. Korrigier mich, wenn ich falsch liege. Gruß Gunb
:
Bearbeitet durch User
g. b. schrieb: > Mit XP hatte man da neben > NT dann den Riegel aus gut verständlichen Gründen vorgeschoben. Nicht "neben" NT. XP ist eine NT-Version, wie auch "Windows 2000" eine NT-Version ist. Nur Windows 95/98/98Se/Me sind nicht NT. Wobei auch unter Windows 95 der Gebrauch der Win32-API zur Schnittstellenprogrammierung mehr als ratsam war; das direkte Befummeln von I/O-Adressen war im Grunde genommen nur unter DOS nötig (da die BIOS-Funktionen für die Ansteuerung der seriellen Schnittstelle etwas zu primitiv waren).
Rufus Τ. Firefly schrieb: > Nicht "neben" NT. XP ist eine NT-Version, wie auch "Windows 2000" eine > NT-Version ist. Nur Windows 95/98/98Se/Me sind nicht NT. Das ist mir alles bekannt. Die NT-Versionen und 2000 habe ich explizit ausgeklammert, weil sie privat eher ihr Schattendasein hatten. Verbreitet war XP. Und gerade weil XP ja ein NT-Abkömmling ist, war der direkte HArdwarezugriff wie unter den 9x-Versionen ja nicht mehr möglich. Eben was ich oben meinte. Rufus Τ. Firefly schrieb: > Wobei auch unter Windows 95 der Gebrauch der Win32-API zur > Schnittstellenprogrammierung mehr als ratsam war; Genau, habe ich auch nie gemocht, wenn Leute die Quick&Dirty-Lösung über low level machten. Die Probleme waren vorprogrammiert. DCB-Struktur studieren, ein paar kleine Codebeispiele durcharbeiten und die Kiste läuft. Anwendungen mit WINAPI direkt würde ich aber auch heute nicht mehr schreiben. Und wenn, dann nur mit Petzold auf dem Tisch. Noch immer eines der besten API-Bücher überhaupt, auch wenn die Schnittstellen hier nicht das Thema sind.
1 | #include <windows.h> |
2 | #include <stdio.h> |
3 | #include <stdlib.h> |
4 | #include <string.h> |
5 | #include <ctype.h> |
6 | #include <sys/types.h> |
7 | #include <sys/stat.h> |
8 | |
9 | /*----------------------------------------------------------------------------------------------------
|
10 | * open port
|
11 | *----------------------------------------------------------------------------------------------------
|
12 | */
|
13 | static HANDLE |
14 | open_port (wchar_t * comport) |
15 | {
|
16 | HANDLE hPort; |
17 | |
18 | hPort = CreateFile (comport, // Pointer to the name of the port |
19 | GENERIC_READ | GENERIC_WRITE, |
20 | // Access (read-write) mode
|
21 | 0, // Share mode |
22 | NULL, // Pointer to the security attribute |
23 | OPEN_EXISTING, // How to open the serial port |
24 | 0, // Port attributes |
25 | NULL); // Handle to port with attribute |
26 | |
27 | return (hPort); |
28 | }
|
29 | |
30 | /*----------------------------------------------------------------------------------------------------
|
31 | * Configure serial port
|
32 | *----------------------------------------------------------------------------------------------------
|
33 | */
|
34 | static int |
35 | init_port (HANDLE hPort, int baudrate) |
36 | {
|
37 | DCB PortDCB; |
38 | |
39 | // Initialize the DCBlength member.
|
40 | PortDCB.DCBlength = sizeof (DCB); |
41 | |
42 | // Get the default port setting information.
|
43 | GetCommState (hPort, &PortDCB); |
44 | |
45 | // Change the DCB structure settings.
|
46 | PortDCB.BaudRate = baudrate; // Current baud |
47 | PortDCB.fBinary = TRUE; // Binary mode; no EOF check |
48 | PortDCB.fParity = TRUE; // Enable parity checking |
49 | PortDCB.fOutxCtsFlow = FALSE; // No CTS output flow control |
50 | PortDCB.fOutxDsrFlow = FALSE; // No DSR output flow control |
51 | PortDCB.fDtrControl = DTR_CONTROL_ENABLE; // DTR flow control type |
52 | PortDCB.fDsrSensitivity = FALSE; // DSR sensitivity |
53 | PortDCB.fTXContinueOnXoff = TRUE; // XOFF continues Tx |
54 | PortDCB.fOutX = FALSE; // No XON/XOFF out flow control |
55 | PortDCB.fInX = FALSE; // No XON/XOFF in flow control |
56 | PortDCB.fErrorChar = FALSE; // Disable error replacement |
57 | PortDCB.fNull = FALSE; // Disable null stripping |
58 | PortDCB.fRtsControl = RTS_CONTROL_ENABLE; // RTS flow control |
59 | PortDCB.fAbortOnError = FALSE; // Do not abort reads/writes on error |
60 | PortDCB.ByteSize = 8; // Number of bits/byte, 4-8 |
61 | PortDCB.Parity = NOPARITY; // 0-4=no,odd,even,mark,space |
62 | PortDCB.StopBits = ONESTOPBIT; // 1 stop bit |
63 | // PortDCB.StopBits = ONE5STOPBITS; // 1.5 stop bits (does not work on some USARTs)
|
64 | // PortDCB.StopBits = TWOSTOPBITS; // 2 stop bits
|
65 | |
66 | // Configure the port according to the specifications of the DCB
|
67 | // structure.
|
68 | if (!SetCommState (hPort, &PortDCB)) |
69 | {
|
70 | DWORD dwError; |
71 | // Could not configure the serial port.
|
72 | dwError = GetLastError (); |
73 | MessageBox (NULL, TEXT("Unable to configure the serial port"), TEXT("Error"), MB_OK); |
74 | return (FALSE); |
75 | }
|
76 | return (TRUE); |
77 | }
|
78 | |
79 | /*----------------------------------------------------------------------------------------------------
|
80 | * close serial port
|
81 | *----------------------------------------------------------------------------------------------------
|
82 | */
|
83 | static int |
84 | close_port (HANDLE hPort) |
85 | {
|
86 | int rtc; |
87 | |
88 | rtc = CloseHandle (hPort); |
89 | return (rtc); |
90 | }
|
91 | |
92 | int
|
93 | main (int argc, char ** argv) |
94 | {
|
95 | HANDLE hPort; |
96 | wchar_t comport[256]; |
97 | |
98 | if (argc == 2) |
99 | {
|
100 | mbstowcs(comport, argv[1], 256); |
101 | hPort = open_port (comport); |
102 | |
103 | if (hPort != (HANDLE) ERROR_INVALID_HANDLE) |
104 | {
|
105 | if (init_port (hPort, 9600)) |
106 | {
|
107 | unsigned char sendbuf[256]; |
108 | int len; |
109 | int n_written; |
110 | |
111 | strcpy ((char *) sendbuf, "Hello World\r\n"); |
112 | len = strlen ((char *) sendbuf); |
113 | |
114 | if (WriteFile(hPort, sendbuf, len, &n_written, NULL) |
115 | {
|
116 | printf ("Success!\n"); |
117 | }
|
118 | }
|
119 | close_port (hPort); |
120 | }
|
121 | }
|
122 | return 0; |
123 | }
|
War das jetzt so schwierig?
:
Bearbeitet durch Moderator
Für einen Anfänger, der noch nie API-Programmierung gemacht hat wie der Threadopener ist da sicher nicht trivial. Für Erfahrene ist es trivial. Ist das nun so schwierig zu verstehen?
Progger schrieb: > Für einen Anfänger, der noch nie API-Programmierung gemacht hat wie der > Threadopener ist da sicher nicht trivial. Für Erfahrene ist es trivial. Ich habe den Code aus MSDN abgetippt (bis auf das main) und dabei etwas vereinfacht. Auf die Quelle wurde der TO mehrfach hingewiesen.
Ich kämpfe zur Zeit eher erfolglos trotz MSDN Kommunikation mit dem Einlesen von Daten mittels Read als Overlapped-Modus. Könntest du evtl. einen funktionierenden Code "abtippen"?
Zeig mal deinen Source-Code zum Thema Overlapped. Es gibt da noch ne 2. Möglichkeit im blockierenden Modus ohne Overlapped. Multithreading, eventuell mit Message-Queue zum Hauptthread. Der Empfangsthread kann dann auf das Read-Ende warten. Das läßt sich aber natürlich auch mit Overlapped vereinbaren.
Franz schrieb: > Ich kämpfe zur Zeit eher erfolglos trotz MSDN Kommunikation mit dem > Einlesen von Daten mittels Read als Overlapped-Modus. Hier ist es gut erklärt (mit Beispiel-Code): http://msdn.microsoft.com/en-us/library/ff802693.aspx
Ich habe ein Win32-Konsolen-Projekt mit Visual C++ 2010 angelegt und den obigen Sourcecode eingefügt. Dabei wurde jedoch folgende Fehlermeldung erzeugt: 1) schnittstelle.cpp(105): warning C4996: 'mbstowcs': This function or variable may be unsafe. Consider using mbstowcs_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> c:\program files\microsoft visual studio 10.0\vc\include\stdlib.h(498): Siehe Deklaration von 'mbstowcs' 2) schnittstelle.cpp(116): warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. 1> c:\program files\microsoft visual studio 10.0\vc\include\string.h(105): Siehe Deklaration von 'strcpy' 3) schnittstelle.cpp(119): error C2664: 'WriteFile': Konvertierung des Parameters 4 von 'int *' in 'LPDWORD' nicht möglich 1> Die Typen, auf die verwiesen wird, sind nicht verknüpft; die Konvertierung erfordert einen reinterpret_cast-Operator oder eine Typumwandlung im C- oder Funktionsformat. 4) schnittstelle.cpp(120): error C2143: Syntaxfehler: Es fehlt ')' vor '{' Mir scheint es, dass es durch die Version von C++ Konvertierungsprobleme gibt. Wer kann mir helfen?
Werner M. schrieb: > 3) schnittstelle.cpp(119): error C2664: 'WriteFile': Konvertierung des > Parameters 4 von 'int *' in 'LPDWORD' nicht möglich dann mach doch den passenden Type daraus > DWORD n_written; > 4) schnittstelle.cpp(120): error C2143: Syntaxfehler: Es fehlt ')' vor > '{' also klammern sollte man schon setzen können wenn man programmiert.
Peter II schrieb: > also klammern sollte man schon setzen können wenn man programmiert. Hatte ich übersehen. Wie kann man noch die 2 Warnings beseitigen?
> Wie kann man noch die 2 Warnings beseitigen? steht doch da: This function or variable may be unsafe. Consider using mbstowcs_s instead Oder einfach mal die Fehlernummer bei Google suchen http://msdn.microsoft.com/de-de/library/ttcz0bys.aspx
Christian schrieb: > Ich möchte mit C Programmieren ;) und warum nicht win lcc32? http://www.cs.virginia.edu/~lcc-win32/ müsste jede Menge Beispielcode geben für serielle, ich gestehe die habe ich noch nicht geöffnet.
turboposty schrieb: > Wie kann man noch die 2 Warnings beseitigen? Steht doch in Warnings. Man muss sie nur lesen. Setze die Preprocessor-Konstante _CRT_SECURE_NO_WARNINGS z.B. ganz oben in schnittstelle.cpp:
1 | #define _CRT_SECURE_NO_WARNINGS
|
Alternativ nutzt Du mbstowcs_s() und strcpy_s(). Ist auch in der Warning so angegeben. Fertig.
:
Bearbeitet durch Moderator
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.