Ströme lenken



  • hi, ich muß euch leider mal wieder nerven, aber ich habe eine Frage, die mich beschäftigt.(Ich weiß zwar net ganzs, obs hier reinpasst, aber ich fand auch nichts anderes).
    Wie kann man eine Win32-Anwendung schreiben, mit der man die elektrischen Impulse an einer Schnittstelle, beispielsweise COM1 oder COM2 steuern und regulieren kann. Mein Plan ist es, einen Motor an den PC anzuschließen, und ich bräuchte dann halt einen kleinen Impuls, um über Verstärker(extern) den Motor zum laufen zu bringen. Geht das überhaupt? Andererseits ist es doch auch so, dass beispielsweise ein Drucker auch Impulse über bestimmte Pole der Schnittstelle erhält, warum sollte man die dann nicht auch einzeln ansteuern können? Bin über jeden Hinweis überaus dankbar,
    Gruß und FROHE PFINGSTEN, konstantin



  • schau dir meine klasse an

    CPORT.H

    /******************************************/
    /*             made by                    */
    /*                                        */
    /*mm   mm y   y n nnn    oo   n nnn    a  */
    /*m m m m  y y  nn   n  o  o  nn   n  a a */
    /*m  m  m   y   n    n  o  o  n    n aaaaa*/
    /*m     m   y   n    n   oo   n    n a   a*/
    /*                                        */
    /*           www.mynona.de.vu              */
    /******************************************/
    
    #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);
    };
    

    CPORT.CPP

    /******************************************/
    /*             made by                    */
    /*                                        */
    /*mm   mm y   y n nnn    oo   n nnn    a  */
    /*m m m m  y y  nn   n  o  o  nn   n  a a */
    /*m  m  m   y   n    n  o  o  n    n aaaaa*/
    /*m     m   y   n    n   oo   n    n a   a*/
    /*                                        */
    /*           www.mynona.de.vu              */
    /******************************************/
    
    #include <windows.h>
    #include "CPORT.H"
    
    HANDLE hCom;
    DWORD COMStatus;
    
    int ComPort::SetOPEN(int PORT)
    {
        if(PORT<=0||PORT>4)
        {
            return WRONG_PORT;
        }
        char*CP[]={"COM1","COM2","COM3","COM4"};
        hCom = CreateFile(CP[PORT-1],
        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);
    }
    


  • @mynona
    Nicht schlecht. Wobei ich TxD nicht ständig auf Impuls setzen würde ;). Zumindest nicht bei normalen Gebrauch der COM-Schnittstellen.



  • also erst einmal vielen dank für diese umfangreiche antwort, aber ich hab noch ein paar fragen dazu:
    wieso die funktion CreateFile() ?
    was bedeutet SetDTR,SetRTS und SetTXD ? Was macht man damit ?
    Was macht GetDTS? bzw GetCommModemStatus?
    Was macht GetDSR ?
    Die COM-Schnittstellen sind doch 25-polig,oder?
    Wie kann ich gezielt zwei Pole ansteuern?
    Liegt dann an jedem Pol, der einen Impul gibt, Plus an oder kann man die Polung des Pols auch bestimmen ?
    So, ich glaub das reicht erstmal. Nochmals vielen Dank für eure umfangreiche Hilfe, das find ich echt sehr nett...



  • @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



  • @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