Com-Port ansteuern mit WinAPI unter C++



  • so in etwa:

    char relais_an[] = {2,1,1,1};
    DWORD bytes_written;
    ...
    WriteFile (hCom, relais_an, sizeof(relais_an), &bytes_written, NULL);
    ....
    


  • Aslo erstmal würde ich das Ganze mit einem externen Programm z.B. mit Hyperterminal (reicht dafür) testen. Das heisst einfach mal 1001 rüberschicken und schauen, ob was zurückkommt.

    Das gleiche sollte dann in Deinem Programm auch zu sehen sein.
    Was mir jetzt noch spontan einfällt, ist PurgeComm(). Sollte man gleich nach dem Erstellen des Handles aufrufen.

    Außerdem hast du vergessen, Deinen Port zu konfigurieren. Dazu musst Du nach dem CreateFile zunächst SetCommTimeouts() und dann SetCommState() aufrufen mit entsprechenden Parametern (Baudrate usw.). Danach dann wie gesagt das PurgeComm().



  • Sry, nochmal das ich soviel frage, hab jedoch vorher noch nie mit COM gearbeitet:(

    Also hab den Code jetzt mal wie folgt bearbeitet:

    // Lade Headers
    #include <windows.h> 
    #include <iostream.h> 
    
    // Starte die Windoof Hauptschleife
    WINAPI WinMain(HINSTANCE hInstance,
    			   HINSTANCE hPrevInstance,
    			   LPSTR lpCmdLine,
    			   int nCmdShow) 
    { 
    	// Initialisiere den Com-Port	
    	HANDLE hCom = CreateFile("COM1",
    							 GENERIC_WRITE|GENERIC_READ,
    							 0,
    							 0,
    							 OPEN_EXISTING,
    							 FILE_ATTRIBUTE_NORMAL,
    							 0);
    
    	// Checke ob Handle erstellt worden konnte
    	if(INVALID_HANDLE_VALUE==hCom)
    	{
    		MessageBoxA(NULL, "Handle konnte nicht erstellt werden", "Error", NULL);
    		return 0;
    	}
    
    	// Erstelle DCB Controldivice
    	DCB dcb;
    	ZeroMemory(&dcb, sizeof(DCB));
    	char buffer[100];
    	strcpy(buffer,"baud=19200 parity=n data=8 stop=1"); 
    	BuildCommDCB((char*)&buffer, &dcb);
    
    	dcb.BaudRate = CBR_19200;
    	dcb.ByteSize = 8;
    	dcb.Parity = 0;
    	dcb.StopBits = 1;
    	if(!SetCommState(hCom, &dcb))
    	{
    		MessageBoxA(NULL, "Fehler bei der DCB Kontrollstrukur", "Error", NULL);
    		return 0;
    	}
    
      DWORD numbytes_ok; 
    
      byte buf_out[4];
      buf_out[0]=1;
      buf_out[1]=1;
      buf_out[2]=1;
      buf_out[3]=1;
    WriteFile(hCom, &buf_out, 4, &numbytes_ok, NULL);
    
       Sleep(2000);
      buf_out[0]=3;
      buf_out[1]=1;
      buf_out[2]=1;
      buf_out[3]=1;
    WriteFile(hCom, &buf_out, 4, &numbytes_ok, NULL);
    
       Sleep(2000);
    

    Funzen tut das ganze noch nicht 😕
    PurgeComm weiß net wofür ich das nutzen soll und SetCommTimeouts weis ichs auch net 😕
    Außerdem balltert er mir ne Fehlermeldung raus, das ich SetCommState fehlgeschlagen ist 😞

    mfg
    Lord33



  • Probiers mal so:

    DCB dcb;           
    GetCommState( hCom, &dcb );
    dcb.BaudRate =  // deine Daten...
    dcb.ByteSize =  
    dcb.Parity =  
    dcb.StopBits =  
    SetCommState( hCom, &dcb );
    

    So ähnlich gehts auch mit den CommTimeouts, die du brauchst, um die timeouts für die Kommunikation zu setzen. PurgeComm solltest Du aufrufen, um alle Puffer zurückzusetzen. Sonst geht beim nächsten Start gar nichts mehr bzw. du kannst nichts mehr senden oder empfangen:

    PurgeComm( hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT );
    


  • Mir ist da nen kleiner dähmlicher Fehler unterlaufen 0 bei den stopbits heißt 1, d.h. der Code müssste so aussehen:
    [code]
    // Lade Headers
    #include <windows.h>
    #include <iostream.h>

    // Starte die Windoof Hauptschleife
    WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR lpCmdLine,
    int nCmdShow)
    {
    // Initialisiere den Com-Port
    HANDLE hCom = CreateFile("COM1",
    GENERIC_WRITE|GENERIC_READ,
    0,
    0,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_NORMAL,
    0);

    // Checke ob Handle erstellt worden konnte
    if(INVALID_HANDLE_VALUE==hCom)
    {
    MessageBoxA(NULL, "Handle konnte nicht erstellt werden", "Error", NULL);
    return 0;
    }

    // Erstelle DCB Controldivice
    DCB dcb;
    ZeroMemory(&dcb, sizeof(DCB));
    char buffer[100];
    strcpy(buffer,"baud=19200 parity=N data=8 stop=1");
    BuildCommDCB((char*)&buffer, &dcb);

    dcb.BaudRate = CBR_19200;
    dcb.ByteSize = 8;
    dcb.Parity = 0;
    dcb.StopBits = ONESTOPBIT;
    if(!SetCommState(hCom, &dcb))
    {
    MessageBoxA(NULL, "Fehler bei der DCB Kontrollstrukur", "Error", NULL);
    return 0;
    }

    DWORD numbytes_ok;

    char buf_out[]={"1001"};
    WriteFile(hCom, &buf_out, 4, &numbytes_ok, NULL);

    char buf_outs[]={"2111"};

    WriteFile(hCom, &buf_outs, 4, &numbytes_ok, NULL);

    Sleep(2000);

    return 0;
    }
    Nun kann man es zwar wieder kompilierne, jedoch funktionieren tut es immer nich nicht



  • "When lpFileName points to a communications resource to open, you must include a colon after the name. For example, specify "COM1: " to open that port. When using IrCOMM, specify "COM3:"." (MSDN)



  • So, habe den gesamten Code jetzt mal angepasst, aber es gibt immer noch keine Reaktion :(:

    // Lade Headers
    #include <windows.h> 
    #include <iostream.h> 
    
    // Starte die Windoof Hauptschleife
    WINAPI WinMain(HINSTANCE hInstance,
    			   HINSTANCE hPrevInstance,
    			   LPSTR lpCmdLine,
    			   int nCmdShow) 
    { 
    	// Initialisiere den Com-Port	
    	HANDLE hCom = CreateFile("COM1",
    							 GENERIC_WRITE|GENERIC_READ,
    							 0,
    							 0,
    							 OPEN_EXISTING,
    							 FILE_ATTRIBUTE_NORMAL,
    							 0);
    
    	// Checke ob Handle erstellt worden konnte
    	if(INVALID_HANDLE_VALUE==hCom)
    	{
    		MessageBoxA(NULL, "Handle konnte nicht erstellt werden", "Error", NULL);
    		return 0;
    	}
    
    	// Erstelle DCB Controldivice
    	DCB dcb;
    	ZeroMemory(&dcb, sizeof(DCB));
    	char buffer[100];
    	strcpy(buffer,"baud=19200 parity=N data=8 stop=1"); 
    	BuildCommDCB((char*)&buffer, &dcb);
    	GetCommState(hCom, &dcb); 
    	dcb.BaudRate = CBR_19200;
    	dcb.ByteSize = 8;
    	dcb.Parity = 0;
    	dcb.StopBits = ONESTOPBIT;
    	if(!SetCommState(hCom, &dcb))
    	{
    		MessageBoxA(NULL, "Fehler bei der DCB Kontrollstrukur", "Error", NULL);
    		return 0;
    	}
    
    	PurgeComm( hCom, PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT | PURGE_RXABORT );
    
      DWORD numbytes_ok; 
    
      char buf_out[]={"1111"};
    WriteFile(hCom, &buf_out, 4, &numbytes_ok, NULL);
    
    char buf_outs[]={"3111"};
    
    WriteFile(hCom, &buf_outs, 4, &numbytes_ok, NULL);
    
       Sleep(2000);
    
      return 0; 
    }
    

    Hmmm... was muss ich den jetzt machen, bin mit Com noch sehr unerfahren



  • 1.) Was soll FILE_ATTRIBUTE_NORMAL in CreateFile? Das Flag gilt für Diskfiles, lass es hier weg.

    2.) PurgeComm löscht Ausgangs- und/oder Eingangsbuffer, wüsste nicht, was der Aufruf dort bringen soll.

    3.) Mein vorheriger Hinweis auf die Doppelpunkte ("COM1:") ist wohl überflüssig, anscheinend gilt diese Anforderung nur für Windows CE.



  • mgs_ schrieb:

    1.)
    2.) PurgeComm löscht Ausgangs- und/oder Eingangsbuffer, wüsste nicht, was der Aufruf dort bringen soll.

    Richtig. Nun stell Dir mal vor Du emnpfängst was, Dein Programm stürzt ab und es sind noch Daten im Eingangsbuffer. Du startest Dein Programm neu und nichts geht mehr. So war es bei mir jedenfalls immmer.



  • Ein Problem können auch die Handshake-Einstellungen sein, ich weiß nicht mehr, was da die Default-Werte sind. Zuständige DCB-Parameter u. a.:

    *fOutxCtsFlow
    Specifies whether the CTS (clear-to-send) signal is monitored for output flow control. If this member is TRUE and CTS is turned off, output is suspended until CTS is sent again.

    fOutxDsrFlow
    Specifies whether the DSR (data-set-ready) signal is monitored for output flow control. If this member is TRUE and DSR is turned off, output is suspended until DSR is sent again.*



  • Für die serielle Schnittstelle verwendet man fertige und lang getestete Klassen... das Rad neu zu erfinden macht keinen Sinn und erzeugt nur unnötige Postings...
    http://www.codeproject.com/system/serial.asp



  • Jochen Kalmbach schrieb:

    Für die serielle Schnittstelle verwendet man fertige und lang getestete Klassen... das Rad neu zu erfinden macht keinen Sinn und erzeugt nur unnötige Postings...
    http://www.codeproject.com/system/serial.asp

    und wenn das immer noch nicht hilft - der beste tip des ganzen threads hier war wohl erstmal es mit einem seriellen terminal zu probieren: http://elmicro.com/files/occonsole_v30.zip
    wenn das immer noch nicht hinhaut, dann tur's einfach die schaltung nicht


Anmelden zum Antworten