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
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ß..
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?
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???
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.
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
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.
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).
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
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.
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.
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
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.