COM-port ansprechen
-
Hallo
Mein Ziel ist es über den Com1 -port abzufragen ob ein Schalter geschlossen oder offen ist. Meine Überlegung: Über RTS sende ich ständig ein TRUE. RTS mit CTS über den Schalter kurzschließen und wenn CTS TRUE ist weiß ich das der Schalter geschlossen wurde.
Ich habe es geschafft den RTS zu setzen kann aber nicht den CTS abfragen. Bzw CTS ist immer 0.
Findet irgendwer einen Fehler in meinen Code, oder weiß was ich falsch mache ?Das ist mein (zusammengesuchter)
Code:cport.h
#define WRONG_PORT 100 #define ON true #define OFF false class ComPort { public: int SetOPEN (int PORT); int SetCLOSE (void); int SetDTR (bool mode); int SetRTS (bool mode); int SetTXD (bool mode); bool GetCTS (); bool GetDSR (); void SetAll (bool mode); };main.cpp
#include "CPORT.H" #include <stdio.h> #include <conio.h> #include <windows.h> #include <atlbase.h> HANDLE hCom; DWORD COMStatus; LPWSTR foo(const char* s) { USES_CONVERSION; LPWSTR p = A2W(s); // ANSI to WIDE return p; } int ComPort::SetOPEN(int PORT) { if(PORT<=0 || PORT>4) { return WRONG_PORT; } LPCSTR ansistr = "COM1"; LPWSTR neuerStr = foo(ansistr); hCom = CreateFile(neuerStr, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); return 0; } int ComPort::SetCLOSE() { CloseHandle(hCom); return 0; } int ComPort::SetDTR(bool mode) { if(mode==ON) { EscapeCommFunction(hCom, SETDTR); // setzen } else { EscapeCommFunction(hCom, CLRDTR); // Loeschen } return 0; } int ComPort::SetRTS(bool mode) { if(mode==ON) { EscapeCommFunction(hCom, SETRTS); // setzen } else { EscapeCommFunction(hCom, CLRRTS); // Loeschen } return 0; } int ComPort::SetTXD(bool mode) { if(mode==ON) { EscapeCommFunction(hCom, SETBREAK); // setzen } else { EscapeCommFunction(hCom, CLRBREAK); // Loeschen } return 0; } bool ComPort::GetCTS() { GetCommModemStatus(hCom, &COMStatus); if(COMStatus & MS_CTS_ON) { return ON; } return OFF; } bool ComPort::GetDSR() { GetCommModemStatus(hCom, &COMStatus); if(COMStatus & MS_DSR_ON) { return ON; } return OFF; } void ComPort::SetAll (bool mode) { SetRTS(mode); SetTXD(mode); SetDTR(mode); } void main(void){ BOOL Loop = TRUE; ComPort comp; while(Loop){ if( _kbhit() ){ Loop = FALSE; } if (comp.SetOPEN(1)!=100){ comp.SetRTS(true); if (comp.GetCTS()== true){ printf ("schalter geschlossen\n"); } }else{ printf("Wrong comport\n"); } } comp.SetCLOSE(); }Gruß Eisenschlumpf
-
Ich hatte auch mal so etwas vor...
Ich habe dann auch eine entsprechende Klasse geschrieben, welche ich schlussendlich aber nie so richtig getestet habe, weil ich dann doch den LPT benutzte. Kurz: Da du scheinbar so oder so einfach Codeschnipsel aneinander gereiht hast, kannst du vielleicht einfach einmal ausprobieren ob's mit meinem Code evtl. tatsächlich funktioniert.//main.cpp #include <iostream> #include <conio.h> #include "mjserial.h" int main(void) { MasterJimmy::Serial com1; bool loop=true; com1.open(); com1.setrts(); while(loop){ if(kbhit()) loop=false; bool cts_state=false; com1.getcts(&cts_state); if(cts_state==true) std::cout<<"\rSchalter geschlossen "; else std::cout<<"\rSchalter nicht geschlossen"; } std::cin.get(); }////////////////////////////////////////////////////////////// // Documentname: mjserial.h // Version: 1.0 // Author: Master-Jimmy (transistornet.de) #ifndef ___MJSERIAL___ #define ___MJSERIAL___ #include <windows.h> namespace MasterJimmy{ class Serialparameters{ public: std::string portname; unsigned short baudrate; unsigned short charlength; unsigned short stopbits; unsigned short parity; Serialparameters(void){ this->portname="COM1"; this->baudrate=9600; this->charlength=8; this->stopbits=1; this->parity=0; } Serialparameters(std::string _portname){ this->portname=_portname; this->baudrate=9600; this->charlength=8; this->stopbits=1; this->parity=0; } }; class Serial{ private: HANDLE handle; Serialparameters params; public: Serial(void); Serial(Serialparameters _params); ~Serial(void); HANDLE gethandle(void); bool open(void); bool close(void); bool write(std::string _buffer); bool read(std::string *_buffer,long _numberofchars); bool setdtr(void); bool cleardtr(void); bool setrts(void); bool clearrts(void); bool setbreak(void); bool clearbreak(void); bool getcts(bool *_state); bool getdsr(bool *_state); }; Serial::Serial(void){ this->handle=INVALID_HANDLE_VALUE; } Serial::Serial(Serialparameters _params){ this->handle=INVALID_HANDLE_VALUE; this->params.portname=_params.portname; this->params.baudrate=_params.baudrate; this->params.charlength=_params.charlength; this->params.stopbits=_params.stopbits; this->params.parity=_params.parity; } Serial::~Serial(void){ this->close(); } HANDLE Serial::gethandle(void){ return this->handle; } bool Serial::open(void){ if(this->handle==INVALID_HANDLE_VALUE){ this->handle=CreateFileA( this->params.portname.c_str(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(this->handle!=INVALID_HANDLE_VALUE){ DCB paramstruct; GetCommState(this->handle,¶mstruct); paramstruct.DCBlength=sizeof(paramstruct); paramstruct.BaudRate=this->params.baudrate; paramstruct.ByteSize=(BYTE)this->params.charlength; paramstruct.StopBits=(BYTE)this->params.stopbits; paramstruct.Parity=(BYTE)this->params.parity; SetCommState(this->handle,¶mstruct); COMMTIMEOUTS timeoutstruct; timeoutstruct.ReadIntervalTimeout=100; timeoutstruct.ReadTotalTimeoutMultiplier=100; timeoutstruct.ReadTotalTimeoutConstant=100; timeoutstruct.WriteTotalTimeoutMultiplier=100; timeoutstruct.WriteTotalTimeoutConstant=100; SetCommTimeouts(this->handle,&timeoutstruct); return true; } else{ return false; } } else{ return false; } } bool Serial::close(void){ if(this->handle!=INVALID_HANDLE_VALUE){ CloseHandle(this->handle); this->handle=INVALID_HANDLE_VALUE; return true; } else{ return false; } } bool Serial::write(std::string _buffer){ if(this->handle!=INVALID_HANDLE_VALUE){ for(unsigned long pos=0;pos<_buffer.length();pos++){ DWORD writtenchars; WriteFile( this->handle, &_buffer[pos], 1, &writtenchars, NULL); } return true; } else{ return false; } } bool Serial::read(std::string *_buffer,long _numberofchars){ if(this->handle!=INVALID_HANDLE_VALUE&&_numberofchars>0){ _buffer->clear(); while(_buffer->length()!=_numberofchars){ DWORD readchars; char buffer[]={"0"}; ReadFile( this->handle, &buffer[0], 1, &readchars, NULL); if(readchars==1){ *_buffer=_buffer->append(buffer); } } return true; } else{ return false; } } bool Serial::setdtr(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,SETDTR); return true; } else{ return false; } } bool Serial::cleardtr(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,CLRDTR); return true; } else{ return false; } } bool Serial::setrts(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,SETRTS); return true; } else{ return false; } } bool Serial::clearrts(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,CLRRTS); return true; } else{ return false; } } bool Serial::setbreak(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,SETBREAK); return true; } else{ return false; } } bool Serial::clearbreak(void){ if(this->handle!=INVALID_HANDLE_VALUE){ EscapeCommFunction(this->handle,CLRBREAK); return true; } else{ return false; } } bool Serial::getcts(bool *_state){ DWORD state; if(!GetCommModemStatus(this->handle,&state)) return false; if(state&MS_CTS_ON) *_state=true; else *_state=false; return true; } bool Serial::getdsr(bool *_state){ DWORD state; if(!GetCommModemStatus(this->handle,&state)) return false; if(state&MS_DSR_ON) *_state=true; else *_state=false; return true; } } #endif
-
Vielen Dank für deinen Code.
Hab den auch gleich mal hergenommen und getestet. Jedoch sagt er mir auch "schalter nicht geschlossen". -->Selber Fehler.
Das setzen vom RTS funktioniert einwandfrei ( die spannung hüpft von -V auf +V).
Nach ein bischen herumgooglen habe ich hier: http://www.eiit.de/v2/index.php?showtopic=3499
ein tolles kleines Tool gefunden das mir den derzeitigen Status alles Pins grafisch darstellt. und wenn ich da RTS auf CTS kurzschließe funktionierts einwandfrei. warum also ned auch in dem Programm....?
-
Keiner mehr eine Idee ?
-
Code von eisenschlumpf:
void main(void){ BOOL Loop = TRUE; ComPort comp; while(Loop){ if( _kbhit() ){ Loop = FALSE; } if (comp.SetOPEN(1)!=100){ comp.SetRTS(true); if (comp.GetCTS()== true){ printf ("schalter geschlossen\n"); } }else{ printf("Wrong comport\n"); } } comp.SetCLOSE(); }Schon mal genau angeguckt, was Deine (Haupt-)Schleife macht?
Du versuchst mit jedem Schleifendurchlauf jedesmal den COM-Port zu öffnen. Das ist Schmarrn.Martin
-
VIELEN DANK.
Hab das jetzt umgeändert, dass ich nur einmal den Port öffne und den RTS setze und es funktioniert!!Weiß vielleicht jemand in welchen intervallen der CTS-pin jetzt pro Sekunde abgefragt wird?
Erkenne ich mit der methode auch, wenn der Schalter nur ein paar µs geschlossen ist?gruß Eschlumpf
-
Die Häufigkeit der Intervalle liegt an Dir bzw. Deiner Schleife.
Ich würde z.B. mit einem Timer alle 300ms..500ms den Portpin abfragen. Das ist für heutige PC-Systeme nicht zu schnell.eisenschlumpf schrieb:
Erkenne ich mit der methode auch, wenn der Schalter nur ein paar µs geschlossen ist?
Nein, Du fragst mit Deiner Funktion GetCTS() nur den momentan gerade vorherrschenden Signalzustand ab.
Windows (oder die Treiber für serielle Schnittstelle) merkt sich nicht, daß ein doppelter Signalwechsel (also Schalter ein und wieder aus) vorlag.Also mußt Du mit dem Schalter dafür sorgen, daß der Kontakt, sagen wir mal, mindestens 2 Sekunden lang ansteht (natürlich muß Deine Applikation oder diese eine Schleife in dieser Zeit bereit sein).
Alternativ könntest Du (wenn Du des Hardware-Bastelns mächtig bist) mit einem Monoflop oder mit einem NE555-Timerbaustein die Schalterkontakt-Zeit künstlich verlängern oder je nach Situation für immer speichern.Martin