Ströme lenken
-
@Konstantin
Ich empfehle dir dringendst dich erstmal technisch über die COM-Schnittstellen zu informieren. Wenn du solche Fragen stellst, dann vermute ich mal, dass du überhaupt keine Ahnung von den seriellen Schnittstellen hast.Also zu Erklärung....
Die COM-Schnittstellen sind normalerweise 9-polig (es gibt auch 25-polige ;)).
CreateFile() heißt: Du machst einen Stream auf zur COM-Schnittstelle, wie bei einer normalen Datei.
DTR, RTS, TxD, DTS, DSR und RxD sind einzelnen Pins an einer bestimmten vordefinierten Stelle der Schnittstelle. Welche genau kann ich dir jetzt leider auch nicht sagen, aber da gibts sicher Infos im WWW (hab schonmal was dazu gefunden mit Bildern ;)).
GetCommModemStatus() ist dazu da, um den Status, der angegebenen COM-Schnittstelle zu ermittelt. Einschließlich der Zustände der einzelnen Pins.
Zusätzlich gibt es noch den Pin GND (auch Ground genannt). Das und nur das ist der Minuspol!! Alle anderen 8 Pins bzw. 24 Pins sind pluspolig! Außerdem bringen die Schnittstellen normalerweise nur einen durchschnittliche Leistung von 5 V! Um so länger das Kabel von der Schnittstelle weggeht um so niedriger wird die Leistung, was eigentlich logisch ist ;).
@Side
Wär vielleicht mal interesant für die FAQ
-
@AJ
in der Tat bin ich auf diesem Gebiet leider nicht sehr bewandert, es ist aber dringend notwenig, zu erfahren wie das läuft, also entschuldige meine nervige Fragerei, aber eine bitte hätt ich noch:
könntest du mir vielleicht ein kleines Beispiel posten, wie ich an einem Pin eine Spannung anlegen kann, um zum beispiel eine LED an diesen Pin mit dem einen Ende(der Anode) anzuschliessen und mit dem anderen Ende an der Masse(umständlich formuliert, aber ich bin recht müde). Wie muss dann der Code geschrieben sein? Muss ich dann einfach nur nach initialisierung die Methode z.B. .SetRTS(TRUE) aufrufen, und bis die methode SetRTS(FALSE) aufgerufen wird, fließt dann ein Strom ? Das wäre ja dann in der tat recht simpel. Also nochmals vielen Dank, gruß Konstantin
-
@konstantin
Na klar mach ich gern. Ich schreib dir jetzt mal einfach zwei Funktionen mit einer kleinen Spielerei für das LED#include "cport.h" ... void blinkeLED(int sek, int anz, int millisek) { ComPort comp; //erzeuge Objekt für Schnittstelle comp.SetOPEN(1); //Öffne COM1 (GND hat ab jetzt Strom) while(!kbhit()) //Prüft ob eine Taste gedrückt wurde { blinke(comp, anz, millisek); sleep(sek); //wartet sek Sekunden bis es weitergeht } getch(); //fängt die Eingabe ab if(kbhit()) //wenn nötig getch(); //ein zweites mal (Sondertasten) comp.SetCLOSE(); //Schließt Schnittstelle (Alle Pins kein Strom) } void blinke(ComPort comp, int anz, int millisek) { int i; for(i=0;i<anz;++i) { comp.SetRTS(TRUE); //Strom auf RTS-Leitung (LED leuchtet) Sleep(millisek); //wartet millisek Millisekunden bis es weitergeht comp.SetRTS(FALSE); //Strom weg von RTS-Leitung (LED aus) } }
Wenn du jetzt blinkeLED(2, 3, 300) z. B. aus main() aufrufst, dann blinkt dein angeschlossenes LED alle zwei Sekunden dreimal im Abstand von 300 Millisekunden. Pass aber auch auf, dass das LED passt! Sonst gehts kaputt oder es leuchtet erst gar nicht.
Kleine Korrektur an mich: Es sind nicht 5 V sondern durchschnittlich 8 V, die anliegen an den Pins!!!
@mynona
Mir ist aufgefallen, dass dein Code noch nicht ganz ausgereift ist. Was ist z. B. wenn man zuerst COM1 öffnet, offen lässt und dann noch COM2 öffnet? Die Variable hCom wird dann vom zweiten Öffnen überschrieben, aber was ist dann mit COM1??? Ich würde empfehlen hCom auch in die Klasse mit einzubinden und nicht als einzige globale Variable ;).
-
Globale Variablen sind immer schlecht ... wohl auch hier. Hab keine Ahnung von Ports ... aber ne Klasse ist immer gut ! Werd mir das mal genauer ansehen - vielleicht kann man da auch was lernen.
@AJ: Wär tatsächlich was für die FAQ ... wenn der Thread fertig ist schieb ich ihn dorthin - hier am besten ohne Veränderung: Ich kenn mich sowieso nicht aus, und es sind keine Schrott-Postings hier.
MfG SideWinder
-
@aj die klasse habe ich fürn eigen betrieb geschrieben, und ich öffne doch nicht 2 coms nacheinander mit einem handle, naja auch da testen ob handle funtzt usw überprüfen,etc aber für mich war des unwichtig weil ich mir dachte du passt da schon uf
-
@mynona: Seit wann bist du nicht mehr registriert?
MfG SideWinder
-
@mynona
Naja ich pass da schon auf, sonst wärs mir ja gar nicht aufgefallen ;). Hab deinen Code für mich auch ein wenig umgeändert, damit man mehrere COM-Ports öffnen kann. Vielleicht erweitere ich es auch noch um ein paar Abprüfungen und Spielereien :D.
-
Den endgültigen Code könntest du dann hier posten - dann kommt der Thread auch endgültig in die FAQ.
MfG SideWinder
-
ich?
seitdem windows gecrasht ist und ich zu faul war auf anmelden zu klicken und mynona + mein passwort einzutragen, zuviel arbeit
-
So jetzt hab ich mir mal die Zeit genommen und die Klasse fertig geschrieben. Ich poste sie jetzt mal hier rein:
cport.h
#ifndef CPORT_H #define CPORT_H "cport.h" #include <windows.h> class ComPort { private: HANDLE hCom; public: enum {OFF,ON}; enum {MAX_PORT = 6}; enum {STATE_ERR = -3, OPEN_ERR, WRONG_PORT, COMM_OK}; ComPort(void); ~ComPort(void); HANDLE GetHCom(void); int OpenCom(int portnr); void CloseCom(void); BOOL SetUART(DCB *dcb); BOOL SetUART(long baud, char bytes, char parity, char stopbit); BOOL SetTimeouts(COMMTIMEOUTS *timeouts); BOOL SetTimeouts(long interval, int multiplier, int constant); void SetDTR(int kz); void SetRTS(int kz); void SetTXD(int kz); void SetAll(int kz); void SetAll(int dtr, int rts, int txd); BOOL GetCTS(void); BOOL GetDSR(void); unsigned long Send(const char *text); unsigned long Receive(char *text, size_t maxsize); static const char *GetCP(int index); }; #endif
cport.c
#include "cport.h" ComPort::ComPort(void) { hCom=INVALID_HANDLE_VALUE; } ComPort::~ComPort(void) { CloseCom(); } HANDLE ComPort::GetHCom(void) { return hCom; } int ComPort::OpenCom(int portnr) { DCB dcb; BOOL res; if(portnr<=0||portnr>MAX_PORT) return(WRONG_PORT); hCom = CreateFile(GetCP(portnr-1), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(hCom==INVALID_HANDLE_VALUE) return(OPEN_ERR); res=GetCommState(hCom, &dcb); if(!res) { CloseCom(); return(STATE_ERR); } return(COMM_OK); } void ComPort::CloseCom() { CloseHandle(hCom); hCom=INVALID_HANDLE_VALUE; } BOOL ComPort::SetUART(DCB *dcb) { if(hCom!=INVALID_HANDLE_VALUE) return(SetCommState(hCom, dcb)); else return(false); } BOOL ComPort::SetUART(long baud, char bytes, char parity, char stopbit) { if(hCom!=INVALID_HANDLE_VALUE) { DCB dcb; dcb.BaudRate=baud; dcb.ByteSize=bytes; dcb.Parity=parity; dcb.StopBits=stopbit; return(SetCommState(hCom, &dcb)); } else return(false); } BOOL ComPort::SetTimeouts(COMMTIMEOUTS *timeouts) { if(hCom!=INVALID_HANDLE_VALUE) return(SetCommTimeouts(hCom, timeouts)); else return(false); } BOOL ComPort::SetTimeouts(long interval, int multiplier, int constant) { if(hCom!=INVALID_HANDLE_VALUE) { COMMTIMEOUTS timeouts; timeouts.ReadIntervalTimeout=interval; timeouts.ReadTotalTimeoutMultiplier=multiplier; timeouts.ReadTotalTimeoutConstant=constant; return(SetCommTimeouts(hCom, &timeouts)); } else return(false); } void ComPort::SetDTR(int kz) { if(hCom!=INVALID_HANDLE_VALUE) if(kz==ON) EscapeCommFunction(hCom, SETDTR); // setzen else EscapeCommFunction(hCom, CLRDTR); // Loeschen } void ComPort::SetRTS(int kz) { if(hCom!=INVALID_HANDLE_VALUE) if(kz==ON) EscapeCommFunction(hCom, SETRTS); // setzen else EscapeCommFunction(hCom, CLRRTS); // Loeschen } void ComPort::SetTXD(int kz) { if(hCom!=INVALID_HANDLE_VALUE) if(kz==ON) EscapeCommFunction(hCom, SETBREAK); // setzen else EscapeCommFunction(hCom, CLRBREAK); // Loeschen } void ComPort::SetAll(int kz) { SetAll(kz, kz, kz); } void ComPort::SetAll(int dtr, int rts, int txd) { SetDTR(dtr); SetRTS(rts); SetTXD(txd); } BOOL ComPort::GetCTS(void) { if(hCom!=INVALID_HANDLE_VALUE) { DWORD COMStatus; GetCommModemStatus(hCom, &COMStatus); if(COMStatus & MS_CTS_ON) return ON; return OFF; } else return OFF; } BOOL ComPort::GetDSR(void) { if(hCom!=INVALID_HANDLE_VALUE) { DWORD COMStatus; GetCommModemStatus(hCom, &COMStatus); if(COMStatus & MS_DSR_ON) return ON; return OFF; } else return OFF; } unsigned long ComPort::Send(const char *text) { if(hCom!=INVALID_HANDLE_VALUE) { unsigned long sent; WriteFile(hCom, text, strlen(text), &sent, NULL); return(sent); } else return(0); } unsigned long ComPort::Receive(char *text, size_t maxsize) { if(hCom!=INVALID_HANDLE_VALUE) { unsigned long received; ReadFile(hCom, text, maxsize, &received, NULL); text[received]=0; return(received); } else return(0); } const char *ComPort::GetCP(int index) { static const char *CP[]={"COM1","COM2","COM3","COM4","COM5","COM6"}; if(index>-1&&index<ComPort::MAX_PORT) return(CP[index]); else return(""); }
Mit freundlicher Unterstützung von mynona, die das Grundgerüst lieferte und der Webseite http://www.htl-rankweil.vol.at/lhr/ze/c/serialport.html , auf der einige nützliche Informationen über die seriellen Schnittstellen stehen.
Wenn ihr irgendwelche Fehler entdeckt, schreibt mir bitte eine E-Mail, damit ich es korrigieren kann. Ihr könnt auch gerne mit einer E-Mail die Quellcodedateien anfordern bei mir.
Wäre nett, wenn sich Marc++us vielleicht dazu bereit erklärt, die Dateien auf dem Server zum Download bereitzustellen.
WICHTIG!!!
Ich hab die Dateien mit dem Compiler Borland 5.5 compiliert. Es gibt also keine Gewährleistung, dass der Quellcode bei jedem Compiler funktioniert (Feedback obs geht, wäre spitze). Ich konnte den Quellcode auch leider nicht direkt Testen, da mir dazu momentan die Mittel fehlen (auch hier wäre Feedback erwünscht).Edit: //aj: Verbesserung des Quellcodes (statt static const -> ENUM; deutschsprachige Methoden in englisch unbenannt)
[ Dieser Beitrag wurde am 24.05.2002 um 23:52 Uhr von AJ editiert. ]
-
@AJ: Wieso machst du aus deinen ganzen static-Konstanten keine Enums? Zudem ist eigentlich alles durchgehend in Englisch, nur das hier nicht:
HANDLE HolHCom(void);
Bin ich richtig in der Annahme, das das "Hol Handle Com-Port" heißen soll?
Zudem würde ich nie ein Handle zurückgeben, der User kann dann mit CloseHandle() deinen Com-Port schließen, ohne das dies deine Klasse merkt.
MfG SideWinder
-
du meinst das mit den enums wohl so oder :
anstelle von
static const int MAX_PORT=6; static const int ON=1; static const int OFF=0; static const int COMM_OK=0; static const int WRONG_PORT=-1; static const int OPEN_ERR=-2; static const int STATE_ERR=-3;
meintest du wohl so
enum {OFF,ON}; enum {MAX_PORT = 6}; enum {COMM_OK}; enum {STATE_ERR = -3, OPEN_ERR, WRONG_PORT};
oder ?
[ Dieser Beitrag wurde am 24.05.2002 um 22:12 Uhr von firefly editiert. ]
-
Yo, das mein ich!
MfG SideWinder
-
@Side
Lässt sich ja noch ändern
Übrigens merkt meine Klasse schon, ob das Handle geschlossen wurde von außen. Was meinst du wofür ich bei jeder Methode eine Abfrage eingebaut hab, ob es ein INVALID_HANDLE_VALUE ist? Ich vermute mal, dass CloseFile() schon so klug ist und den Handle auf diesen Wert setzt. Habs nur sicherheitshalber beim Schließen eingebaut, falls doch nicht ;).Falls es nicht auf den Wert gesetzt wird und das macht jemand, dass er das Handle einfach von außen schließt und greift dann nochmal drauf zu, dann kann ich ihm auch nicht helfen. Ich kann nicht jeden Fehler jedes potenziellen Programmierers abfangen. Da würde ich ja ewig dran rumprogrammieren.
Etwas Selbstinitiative erwarte ich schon, z. B. dass man sich informiert über die seriellen Schnittstellen bevor man damit rumspielt. Deswegen hab ich auch den Link hinzugefügt.
Ich kann ja noch ein Beispiel dazu angeben, wie man es verwendet. Jetzt ändere ich erstmal den Code um, wegen den ENUMS und der Sprachunterschiede.
-
@mynonA:
Du bist erst 13 und kannst schon sowas??????????????????????????
Oh schei*e!!!!!!!!
Du bist ja echt sup er!
Der Thread witrd aber gefaqt!
-
Yo, sicherlich aber ich warte noch auf weitere Verbesserungsvorschläge zu Mynonas und AJs Klasse.
Nur perfekt ist gut genug ;).
MfG SideWinder
-
@Side
Perfekt gibt es nichtIch glaube du kannst das so lassen und in die FAQ stellen. Bevor ich noch auf die Idee komme und sämtliche Protokolle einbaue (auch wenn ich mich darüber erst informieren müsste ;)).
-
Jede Idee wäre mir recht :), ich schau mal den Code selbst durch mach noch ein paar dumme Anmerkungen und verschiebe nach deinen Antworten das ganze in die FAQ ;).
MfG SideWinder
-
meine güte, leute, wenn ich ewusst hätte, was ich mit dieser frage aushelöst habe, dann hätte ich sie glaube ich gar net gestellt.
scheint ja wohl doch relativ komplex zu sein, dabei hatte ich ursprünglich vor, einfach nur ein paar selbstgebaute schaltungen über den pc zu steuern. naja, also dann will ich mich bei euch allen erst einmal HERZLICH BEDANKEN, ich glaube einen ausführlicheren Lösungsweg wird man wohl nirgendwo anders finden. also, nochmals vielen DANK für euer aller Mühen
gruß konstantin
-
@konstantin
Also wenn du es noch ausführlicher haben willst, dann hätte ich da noch ne Lösung