Hallo. Ich weiß nicht wie ich unter C den RS232 Port lesen/schreiben soll. Ich hab keine Ahnung was es da für Befehle gibt und was die machen. Ich hab vor Daten von meinem Atmega16 an den PC zu senden. Kann mir da jemand helfen?
Der Reihe nach CreateFile("COM1:",... // Port öffnen GetCommState // vorbereiten der Schnittstellenparameter, spart den kompletten DCB selbst zu bauen SetCommState // angepasste Werte aktivieren (Baudrate, Stopbits,...) ReadFile / WriteFile // die eigentliche Datenübertragung CloseHandle // das wars ;-) Hoffe Du hast die MSDN-CD's installiert. Da gibts dann nähere Infos zu. Falls nicht: http://msdn.microsoft.com
Hi! Kuck mal hier: http://pvbrowser.org/pvbrowser/sf/manual/rllib/html/classrlSerial.html Download des Ganzen: http://pvbrowser.de/pvbrowser/tar/rllib.tar.gz Funktioniert super. Musst halt all jene Dateien mit in dein Projekt mitnehmen, nach denen der Compiler schreit. mfg W.K.
Jo Jan, schon schlimm einfach so ein paar Brocken hinzuwerfen wo der Kumpel doch gern ein komplettes Programm gehabt hätte...
Du wolltest doch die Befehle wissen, die man für serielle Kommunikation unter Windows braucht?! Das sind sie - mehr ist da nicht (ok, ein, zwei Sachen gibts da noch, aber für Deinen Zweck reicht das). Du brauchst im einfachsten Fall genau diese Funktionen in dieser Reihenfolge. Mach MSDN auf, lokal oder online und schau Dir die genaue Syntax an. Ein komplettes Beispiel kann ich Dir nicht geben - und würde Dir auch nicht viel bringen, weil der eigentliche Kommunikationsteil ja nur einen kleinen Teil der Programme ausmacht. Ach ja, Get-/SetCommTimeouts hatte ich noch vergessen. Ist wichtig um ein definiertes Timing zu erhalten.
Und ReadFile sollte in einem eigenen Thread stehen und mit WaitCommEvent und WaitForSingleObject auf ein Read- oder sonstiges Ereignis am Port warten. Sonst hilft nur pollen im main thread. HyperTerminal tut's aber auch, ganz ohne programmieren. Blackbird
@ Blackbird:
WaitForSingleObject kenn ich, aber welche Funktionen braucht man dafür:
> Sonst hilft nur pollen im main thread.
?
Gruß, Feadi
Pollen: Am Anfang die Timeouts einstellen, z.B.: so:
1 | COMMTIMEOUTS ct; |
2 | GetCommTimeouts (hCom, &ct); |
3 | // Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes
|
4 | ct.ReadIntervalTimeout = 1000 / BAUDRATE * (dcb.ByteSize + |
5 | (dcb.Parity == NOPARITY ? 0 : 1) + |
6 | (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2; |
7 | ct.ReadTotalTimeoutMultiplier = 0; // [ms] wird mit Read-Buffer-Size multipliziert |
8 | ct.ReadTotalTimeoutConstant = 50; // wird an ReadTotalTimeoutMultiplier angehängt |
9 | ct.WriteTotalTimeoutMultiplier = 0; |
10 | ct.WriteTotalTimeoutConstant = 0; |
11 | SetCommTimeouts (hCom, &ct); |
Ja, und dann in einer Schleife immer ReadFile aufrufen. Das ist aber die schlechteste Variante, besser ist ein eigener Thread (CreateThread), in dem man auf ein Read-Ereignis am Port wartet und dann erst ReadFile aufruft. Weil ja dann auch ein Byte angekommen ist. Zuerst wird eine Overlapped-Struct erstellt und mit einem Event verknüpft.
1 | OVERLAPPED o; |
2 | memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen |
3 | o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Event setzten |
dann eine Maske mit den Events, af die man warten möchte und eine, die die eintreffenden Events aufnimmt, erstellt:
1 | DWORD dwSetMask = EV_RXCHAR | EV_ERR; |
2 | DWORD dwEvtMask; |
und dann wird in einer Endlosschleife auf die Events gewartet:
1 | do // in Endlos-Schleife auf Empfangssignale warten: |
2 | {
|
3 | WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalen verknüpfen |
4 | |
5 | if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event |
6 | {
|
7 | if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen: |
8 | {
|
9 | bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL); |
10 | ...
|
11 | if (dwEvtMask & EV_ERR) // Zeichen an RxD empfangen: |
12 | {
|
13 | ...
|
Naja, das Übliche mit DCB, Fehlerauswerten, Sende- und Empfangspuffer setzen, Schließen von Thread und COm und Event usw. nicht vergessen. Schreiben kann man aus jedem Thread heraus, sollte nicht im Empfangsthread sein und wenn möglich, in einem eigenen Thread ablaufen, wel man so ganz bequem feststellen kann, ob die Zeichen auch wirklich raus sind (an den Treiber) und nicht der Puffer noch voll ist und man Zeichen überschreibt. Für das Öffnen, Schließen und Setzen der seriellen Ports und der einzelnen Pins gibts es massig C/C++ -Code-Schnipsel und -Klassen. Aber keine mir bekannte behandelt das Empfangen in einem Thread. Es wird immer nur eine schön eingepackte ReadFile-Routine vorgestellt, aber wo soll man die aufrufen? Blackbird
Vor Aufruf der do-while-Schleife kommt noch das Setzen der Maske:
1 | SetCommMask (hCom, dwSetMask); // Empfangssignale definieren |
Hatte ich vergessen. Blackbird
Noch'n Zusatz, zum Pollen: Den Code für den Empfangsthread kann man auch in den main-Thread packen und statt INFINITE in WaitForSingleObject eine Wartezeit angeben. Auf einen Event braucht man dann aber nicht warten. Blackbird
Vielen Danke für die Erklärung! Das probiere ich bei Gelegenheit gleich mal aus. Gruß, Feadi
Blackbird wrote: > Für das Öffnen, Schließen und Setzen der seriellen Ports und der > einzelnen Pins gibts es massig C/C++ -Code-Schnipsel und -Klassen. Aber > keine mir bekannte behandelt das Empfangen in einem Thread. Es wird > immer nur eine schön eingepackte ReadFile-Routine vorgestellt, aber wo > soll man die aufrufen? Doch, bei CodeGuru: http://www.codeguru.com/Cpp/I-N/network/serialcommunications/article.php/c2483 Funktioniert wunderbar, nehme ich in leicht erweiterter Form auch immer. Ich hab mir noch Binärdatentransfer und das ordentliche Schließen der Schnittstelle sowie Behandlung der COM bis 255 hinzugefügt.
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.