Lowlevel
Lowlevel => Lowlevel-Coding => Thema gestartet von: Masen 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!
-
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 :) )
-
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 ...
-
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
-
danke schonmal!
wer noch ergänzungen hat, bitte posten ;)
-
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
-
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
-
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(...) ?
-
Jo :)
-
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
-
wie sehen dann da die argumente aus ?
analog zu ReadFile ?
WriteFile(hcom, string, 5, &nBytesRead, NULL);
so dann ?
-
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.
}
-
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 ?
-
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
-
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.
-
@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:
-
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
-
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?
-
@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 (http://msdn.microsoft.com/en-us/library/aa363260(VS.85).aspx). Vielleicht auch mal die Dokumentation zu diesen ganzen Funktionen (http://msdn.microsoft.com/en-us/library/aa363194(VS.85).aspx) durchlesen.
-
@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 (http://msdn.microsoft.com/en-us/library/aa363260(VS.85).aspx). Vielleicht auch mal die Dokumentation zu diesen ganzen Funktionen (http://msdn.microsoft.com/en-us/library/aa363194(VS.85).aspx) 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 ?
-
So kleines Update , das Problem das ich Daten nicht 2mal Auslesen konnte hab ich in den Griff bekommen, in dem ich nach jedem Lesen CloseHandle() ausgeführt hab ... Doch anscheinend klappt das Senden von Daten an den mC nicht , nach dem Absenden krieg ich immer Fehler Meldungen nach ausführen von CreateFile...
ich prüfe folgendermassen:
h_com = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0 , NULL);
if (h_com == INVALID_HANDLE_VALUE) {
printf ("Handle error %d.\n", GetLastError());
EingabeBufferLoeschen();
getchar();
return (1);
}
dann schicke ich einen string an den mC:
unsigned short int Interval;
unsigned long nBytesWrite;
char WriteString[7];
EingabeBufferLoeschen();
scanf ("%i",&Interval);
sprintf(WriteString, "t%i\n", Interval);
WriteFile(hcom,WriteString,7,&nBytesWrite,NULL);
CloseHandle (hcom);
das ganze klappt dann wohl nicht so ganz, obige fehler abfrage ergibt dann einen fehler code 5 als return wert von GetLastError();
-
Moin
http://msdn.microsoft.com/en-us/library/ms681382(VS.85).aspx
sollte auskunft über deinen Fehler geben.
hab ich das gefühl, das du im kompletten ablauf irgendwie den wurm drinn hast?
1. Comm port öffnen,
2. Configurieren,
3. Daten senden und schreiben
4. bei erneuten senden und schreiben mit 3 weitermachen!
5. wenn nicht comm port wieder schliessen und Handel löschen.
-
hi,
also von der reihenfolge passt das schon alles .... das problem taucht ja auch nach dem senden auf, also scheint da ein problem mit zu sein, ist das die WriteFile funktion denn so in ordnung wie ich sie benutze ?
-
Hi,
muss doch nochmal die Community um Hilfe, Projekt Abgabe Datum ist nah, und ab gesehen von einem kleinen Prob hab ich alle anderen aus dem weg geschafft ... es geht darum, das mein Programm bei der Kommunikation mit dem MC einzufrieren scheint, BIS ich dann mal ein Terminal Programm ausführe (hterm) dann läuft in meiner Software alles prima ...dennoch scheint auch beim einfrieren die kommunikation zu klappen, da der MC Daten empfängt (LED bestätigt das) ... desweiteren meldet sich auf der PC seite auch keine fehlermeldungen ... es ist auch nicht so das mein programm wirklich "abstürzt" sondern an der stelle wo was empfangen werden müsste, geht es nicht weiter, die konsole lässt sich jedoch ganz normal schließen ...
weiß da echt nicht weiter, da ich die serielle schnittstelle so initialisiere, wie man es jedem Tutorial oder sonst wo im Internet findet ... an dem Rechner liegt es auch nicht, da auf 2 ausprobiert, 1mal mit echter RS232 schnittstelle, 1mal mit RS232/USB adapter... jedes mal das selbe phänomen ...
hoffe echt das mir da jemand weiterhelfen kann :|
hier mal meine init funktion
HANDLE init()
{
DCB dcb;
HANDLE h_com;
BOOL fSuccess;
h_com = CreateFile(ComPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0 , NULL);
if (h_com == INVALID_HANDLE_VALUE)
{
printf ("Handle error %d.\n", GetLastError());
EingabeBufferLoeschen();
getchar();
return (1);
}
dcb.DCBlength = sizeof(DCB);
fSuccess = GetCommState(h_com, &dcb);
if (!fSuccess)
{
printf ("GetCommState error %d.\n", GetLastError());
EingabeBufferLoeschen();
getchar();
return (2);
}
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
fSuccess = SetCommState(h_com, &dcb);
if (!fSuccess)
{
printf ("error %d.\n", GetLastError());
EingabeBufferLoeschen();
getchar();
return (3);
}
return h_com;
}
-
hat keiner ne idee ?
-
hab mir jetzt hier nicht alles genau durchgelesen und hab auch nicht viel ahnung von W[...]s-Programierung, aber mit was liest du denn die daten ein? bzw. was macht die funktion wenn keine daten vorhanden sind? eventuell wartet sie bis welche vorhanden sind, dann solltest du dir entweder ne andere funkiton suchen die nicht wartet, oder vorher überprüfen ob daten vorhanden sind.
-
hm,ne das ist ja allgemein nicht das problem ... sondern das mein Programm erst was auslesen kann NACHDEM ich ein Terminal programm (zB Putty) auf die schnittstelle ausgeführt hab ... ich weiß echt nicht weiter, was macht putty damit das läuft ? ich hab mir nun auch schon den quellcode angeguckt, ich kann da nix erkennen ... weiß da keiner weiter? bald ist abgabe da muss das laufen, und es kann ja echt nicht sein ... muss wohl irgendwas dummes sein °-° weiß keiner rat ?!?