Autor Thema: Serielle Schnittstelle unter Windows  (Gelesen 16322 mal)

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« am: 03. July 2008, 12:26 »
Hej,
hat nicht gerade mit OS Dev oder äusserstem Low-Level zu tun, denke mal aber das hier dennoch einige bescheid wissen werden.

Brauche eine möglichst Komfortable Lösung um einen String aus einer Seriellen Schnittstelle zu lesen. Unter Linux geht das ja super einfach , analog zum auslesen einer Datei.Nun frag ich mich ob es irgendwie Bibliotheken, etc, gibt , die einem ähnliches Handling unter Windows ermöglichen.

Es geht nämlich um folgendes, von einem Microcontroller kommen Daten an der Seriellen Schnittstelle in folgender Form an "234,256,267,...." , diesen String , möchte ich halt auch in der selben Form einlesen ...

Danke im voraus!

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #1 am: 03. July 2008, 13:12 »
Auch unter Windows kann man dass per CreateFile lösen:

HANDLE init()
{
 HANDLE h_com = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0 , NULL);
 DCB dcb;
 COMMTIMEOUTS cto;

 GetCommState(h_com, &dcb);

 dcb.BaudRate = 115200;
 dcb.ByteSize = 8;
 dcb.Parity   = NOPARITY;
 dcb.StopBits = ONESTOPBIT;

 SetCommState(h_com, &dcb);

 GetCommTimeouts(h_com,&cto);

 cto.ReadTotalTimeoutConstant=0;
 cto.ReadTotalTimeoutMultiplier=0;

 SetCommTimeouts(h_com,&cto);

 return h_com;
}

////////////////////////////////////////////////////////////////////////////////

char getc(HANDLE hcom)
{
 static unsigned long int counter = 0;
 counter++;
 
 unsigned long nBytesRead;
 char input[2];

 ReadFile(hcom, input, 1, &nBytesRead, NULL);

 return input[0];
}

(Ich hatte im code noch einige debug-ausgaben... sollte also irgendetwas komisch/überflüssig sein, liegt es daran :) )

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #2 am: 03. July 2008, 18:58 »
das nun die lösung über die window.h bibliothek oder ? a. versteh ich nicht ganz, wie das da alles abläuft, und b. hab ich da nur die möglichkeit das byte-weiße einzulesen oder ? so ein ganzer string wär aber gut ^^

mein professor meinte, es gäbe da wohl ne möglichkeit mit cin/cout zu arbeiten, da müsste man die stream irgendwie auf die serielle schnittstelle umleiten oder so?!? so ganz hab ich das nicht verstanden ...

RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #3 am: 03. July 2008, 19:38 »
char string[1000];
ReadFile(hcom, string, 1000, &nBytesRead, NULL);

Und ja, es ist die winapi :)

Wie es mit streams geht weiß ich nicht...
Ich habe auch kein windows mehr, um es mal eben zu testen...
schonmal folgendes versucht:
fstream com("COM1", ...);o.ä.

Zum ablauf:
"datei" öffnen
Einstellungen vornehmen
timeouts einstellen
aus der datei lesen

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #4 am: 03. July 2008, 19:45 »
danke schonmal!

wer noch ergänzungen hat, bitte posten ;)

ChristianF

  • Beiträge: 296
    • Profil anzeigen
    • DeutschOS - Betriebssystem Projekt
Gespeichert
« Antwort #5 am: 04. July 2008, 08:15 »
Schau mal, vielleicht hilft dir das weiter:
http://www.mathematik.uni-marburg.de/~cpp/streams/datei_8.html
 
Da wird der Stream von cout umgesetzt auf eine zuvor geöffnete Datei.
Vielleicht funktioniert das auch mit dem COM-Handle.
 
Gruß Christian

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #6 am: 04. July 2008, 09:34 »
Moin

willst du nur wissen, was auf der Schnitstelle passiert?

oder Willst du pc seitig auch ein eigenes Programm haben.

1. Möglichkeit währe Hyperterminal, wenn der deine Daten versteht,
2. Docklight

3. brauchst du selbstgeschriebenes Programm,
3a. Win API
3b. Es gibt meines wissens auch eine AktivX componente dafür
3c. Es gibt das gleiche auch für Borland CBuilder und Delphi
3d. für java gibts auch zwei Bibliothek RTXComm und Comm.jar von sun ( wenn die noch existiert )

gruss

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #7 am: 21. July 2008, 11:45 »
hey,
danke nochmal an alle!

@RedEagle: hab nun deinen Ansatz umgesetzt, vielen dank nochmal!
wie lautet dann eigentlich die Funktion um einen String an die Serielle Schnittstelle zu senden ? WriteFile(...) ?


RedEagle

  • Beiträge: 244
    • Profil anzeigen
    • RedEagle-OperatingSystem - Projekt
Gespeichert
« Antwort #8 am: 21. July 2008, 12:12 »
Jo :)

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #9 am: 21. July 2008, 12:17 »
Moin

ja mit WriteFile kann man daten auf den handel rausschreiben.
Mit ReadFile daten empfangen.

CreateFile // öffnen des com ports
CloseHandle // nach gebrauch den handel wieder löschen

WriteFile // daten schreiben
ReadFile // daten lesen

noch ein paar nützliche Funktionen zum Comm port

GetCommState // staus des ports ermittlen
SetCommState // staus verändern bautrate, stopByts Parity, ...
GetCommTimeouts // timeouts ermitteln
SetCommTimeouts // timeouts setzen

mehr gibts wie immer unter der MSDN




Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #10 am: 21. July 2008, 12:22 »
wie sehen dann da die argumente aus ?

analog zu ReadFile ?

WriteFile(hcom, string, 5, &nBytesRead, NULL);


so dann ?

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #11 am: 21. July 2008, 12:48 »
Moin ich verwend das so.
     
if (!WriteFile ( hInterface,             // Port handle
                 pabTransmitData,       // Pointer to the data to write
                 (DWORD)wTransmitData_len,  // Number of bytes to write
                 &dwNumBytesWritten,   // Pointer to the number of bytes written     
                 NULL))   
{
   // WriteFile failed. Report error.
}

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #12 am: 22. July 2008, 12:43 »
ok danke schonmal, ich probier das bei gelegenheit zu implementieren ....
EDIT : Wie mach ich das dann wenn ich ein Integer übertragen möchte ?


folgender komischer bug der mich grad beschäftigt, ich kann mit meinem Programm die Serielle Schnittstelle erst auslesen, wenn ich das davor mit einer anderen Terminal Software ausgelesen habe ... ansonsten hängt das Programm an der Stelle wo es versucht mit der Schnittstelle zu kommunizieren ... das selbe Problem tritt auf wenn man auf eine COM schnittstelle auswählt an der nichts dran hängt oder existiert... also irgendwie komisch das ganze, zumahl es zwingend notwendig ist das man meine software benutzen kann ohne vorher eine andere terminal software ausgeführt zu haben ... woran könnte das liegen ?
« Letzte Änderung: 22. July 2008, 13:14 von Masen »

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #13 am: 22. July 2008, 13:16 »
Moin

du hast auch den port nach dem öffnen konfiguriert? Baudrate, Start bits, stop bits, parity, ....

das sollte man danach mit SetCommState machen, sonst geht das mit grosser warscheinlichkeit in die hose.

gruss

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #14 am: 22. July 2008, 14:16 »
EDIT : Wie mach ich das dann wenn ich ein Integer übertragen möchte ?

#include <stdint.h>
uint32_t myFirstInteger;
if (!WriteFile ( hInterface,                // Port handle
                 &myFirstInteger,            // Pointer to the data to write
                 4,                                   // Number of bytes to write
                 &dwNumBytesWritten,   // Pointer to the number of bytes written     
                 NULL))   
{
   // WriteFile failed. Report error.
}

Das ist natürlich nur eine Möglichkeit. Es kommt halt auch drauf an, was der auf der anderen Seite der Leitung erwartet. Also ob du dich zB das mit einem anderen Programm mit einem best. Protokoll verbindest, dann musst du dich natürlich an das Protokoll halten.
Zu beachten ist halt, dass der benutzte Typ (hier uint32_t) auf beiden Maschinen gleich kodiert ist, ansonsten musst du es halt von Hand konvertieren.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #15 am: 23. July 2008, 15:49 »
@Termite :

ich benutzte da die init funktion von RedEagle, natürlich mit angepasster Baud Rate .... funktioniert auch wunderbar , aber nur wenn ich zuerst das Terminal Programm ausführe, und danach mein Programm starte ... bisschen seltsam find ich das schon  :roll:

Termite

  • Beiträge: 239
    • Profil anzeigen
Gespeichert
« Antwort #16 am: 23. July 2008, 23:15 »
nabend

hab ich ganz übersehen

schau dir mal die Einstellungen an, die du mit GetComState ausliests. ggf. ist da noch irgend ein wert anders gesetzt.

auch liefert meines wissens Set und GetComState einen Return value. Werte die mal aus, und prüfe ggf. den error code GetError oder GetLastError. ggf wird da was gesetzt.

ps. hab heut selber mal wieder was für den com port zusammen gehackt. Anders kann man das nicht mehr nennen. grr MS ist doch zu blöd die com events gescheit zu implementieren. TX_EMPTY wird ausgelöst, wenn das letzte zeichen verschickt wurde. Ich warte darauf und danach schalte ich die baudrate um. und was macht windows, sendete die letzten zeichen der vorgehenden nachricht doch glatt mit der neuen baudrate.  :x


Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #17 am: 25. July 2008, 12:19 »
hi,

@termite:also das mit den Error Funktionen und Return Values müsstest du mal bitte etwas genauer erläutern, weiß nämlich gar nicht was ich da für Werte erwarten soll, von daher hilft mir das so erstmal nicht weiter  :-o


dann hab ich noch so ein problem, und zwar wenn ich mir vom controller einmal die Daten schicken lasse, die auslese, und dann aber nochmal schicken lasse, und auslesen will (quasi erneuter start meiner funktion zum auslesen), erhalte ich die eigentlich daten nicht mehr, als string erhalte ich ein großes "A" ... muss ich da irgendwie den Buffer löschen oder so ? wie mach ich das am besten ? den wenn ich das gesamte programm neustarte geht es wieder ...

eventuell hängt das ganze ja auch mit dem problem zusammen das ich vorher ein terminal ausführen muss ... das siehts ja übrigens auch danach aus, das das erst das terminal programm den comport so "richtig aktiviert" oder so ... reicht den die init funktion die ich benutze überhaupt aus ? oder muss ich den vorher den comport noch irgendwie speziell initialisieren?

bluecode

  • Beiträge: 1 391
    • Profil anzeigen
    • lightOS
Gespeichert
« Antwort #18 am: 25. July 2008, 13:04 »
@termite:also das mit den Error Funktionen und Return Values müsstest du mal bitte etwas genauer erläutern, weiß nämlich gar nicht was ich da für Werte erwarten soll, von daher hilft mir das so erstmal nicht weiter  :-o
Schau dir halt die Dokumentation von Microsoft an: MSDN: GetCommState. Vielleicht auch mal die Dokumentation zu diesen ganzen Funktionen durchlesen.
lightOS
"Überlegen sie mal 'nen Augenblick, dann lösen sich die ganzen Widersprüche auf. Die Wut wird noch größer, aber die intellektuelle Verwirrung lässt nach.", Georg Schramm

Masen

  • Beiträge: 31
    • Profil anzeigen
Gespeichert
« Antwort #19 am: 25. July 2008, 13:33 »
@termite:also das mit den Error Funktionen und Return Values müsstest du mal bitte etwas genauer erläutern, weiß nämlich gar nicht was ich da für Werte erwarten soll, von daher hilft mir das so erstmal nicht weiter  :-o
Schau dir halt die Dokumentation von Microsoft an: MSDN: GetCommState. Vielleicht auch mal die Dokumentation zu diesen ganzen Funktionen durchlesen.

also ich hab nun mal eine angepasste initialisierung aus diesem beispiel hier genommen :
http://msdn.microsoft.com/en-us/library/aa363201(VS.85).aspx

mal abgesehen davon das mein Compiler die Funktion "SecureZeroMemory(" nicht kennt, klappt auch alles ... ist ja auch im grunde das gleiche wie von RedEagle, sind halt nur die Fehler Abfragen drinne ... jedoch tauchen keine Fehler auf, die Problematik bleibt aber die selbe... ich komm da irgendwie nicht weiter, und langsam wird die zeit knapp ... auch das mit dem empfangen vom "A" anstatt der Daten ist komisch, tippe da mal darauf das cih  den Buffer irgendwie woher löschen muss ?

 

Einloggen