CreateFile schlägt fehl - serielle schnittstelle (kein zugriff)



  • Hallo,

    ich versuche grade mal auf die serielle Schnittstelle zugriff zu nehmen. Ich habe von winapi.net aus dem Tutorial den Code genommen, aber es funktioniert leider nicht. Hier der Code (CreateFile schlägt mit Fehlercode 5 fehl (ERROR_ACCESS_DENIED).

    bool init  (int nPort, int nBaud, int nBits, int nStopp, int nParity) 
    {
       char szPort[15];
       /*
       if (INVALID_HANDLE_VALUE != hComm)  
           return (TRUE);
    */
    
        // Aus einer "1" in nPort schreiben wir so "COM1" in szPort z.B..
       wsprintf (szPort, "\\\\.\\COM%d", nPort);
    
       hComm = CreateFile (szPort, // COM-Port ffnen
                           GENERIC_READ|GENERIC_WRITE, // wir wollen lesen und schreiben
                           0,
                           0,
                           OPEN_EXISTING,
                           0,
                           NULL); // nicht OVERLAPPED, wir holen uns den Port exclusiv
    
       if (hComm == INVALID_HANDLE_VALUE) // hat es geklappt? Bei Fehler ist hier Schluss!
       {
    		int lasterror = -1;
    		char error [200 +1];
    		lasterror = GetLastError ();
    		(void)sprintf (error, "Fehler beim ffnen des COM-Ports (%d)", lasterror);
    
          MessageBox (NULL, error, "CreateFile", NULL);
          //return false;
       }
    
       // Alte Timeouts merken. Bei Fehler ist hier Schluss!
       if (!GetCommTimeouts(hComm, &timeouts_alt)) 
       {
          //Close ();
          MessageBox (NULL, "Fehler beim ffnen des COM-Ports!\nGetCommTimeouts()", 
                      NULL, NULL);
          return false;
       }
    
       // Eine Struktur vom Typ COMMTIMEOUTS erzeugen und neue Timeouts setzen
       COMMTIMEOUTS timeouts; 
       timeouts.ReadIntervalTimeout         = 200;
       timeouts.ReadTotalTimeoutMultiplier  = 200;
       timeouts.ReadTotalTimeoutConstant    = 200;
       timeouts.WriteTotalTimeoutMultiplier = 200;
       timeouts.WriteTotalTimeoutConstant   = 200;
    
       // Neue Timeouts setzen. Bei Fehler ist hier Schluss!
       if (!SetCommTimeouts(hComm, &timeouts)) 
       {
          //Close ();
          MessageBox (NULL, "Fehler beim ffnen des COM-Ports!\nSetCommTimeouts()", 
                      NULL, NULL);
          return false;
       }
    
       DCB dcb; 
       memset (&dcb, 0, sizeof(dcb)); 
    
       // Die bestehenden Parameter holen. Bei Fehler ist hier Schluss!
       if (!GetCommState (hComm, &dcb)) 
       {
          //Close ();
          MessageBox (NULL, "Fehler beim ffnen des COM-Ports!\nGetCommState()", 
                      NULL, NULL);
          return false;
       }
    

    edit: cpp-Tags korrigiert.



  • fluxy schrieb:

    (CreateFile schlägt mit Fehlercode 5 fehl (ERROR_ACCESS_DENIED).

    Dieser Fehler tritt u.a. dann auf, wenn schon ein anderes Programm den COM-Port benutzt.



  • aha was mache ich denn wenn ich die daten von einem programm lesen will, welches auf den port von der gegenseite schreibt?



  • Wie ist das eigentlich mit WindowsXP und 2000? Ich habe gehört da soll der Zugriff geblockt werden oder so. Im C Standard gab es doch früher auch Funktionen für die Schnittstellen ich glaube die heisse _inp und _outp, die nur assamblercode ausführen....



  • fluxy schrieb:

    Im C Standard gab es doch früher auch Funktionen für die Schnittstellen ich glaube die heisse _inp und _outp, die nur assamblercode ausführen....

    Ich kenne den C-Standard nicht auswendig, aber die Unterstriche vor den Funktionsnamen sprechen stark dafür, dass es keine Standardfunktionen waren. Außerdem ist Standard-C plattformunabhängig, daher können _inp und _outp IMHO nicht im Standard gestanden haben.

    aha was mache ich denn wenn ich die daten von einem programm lesen will, welches auf den port von der gegenseite schreibt?

    Ein Port ist eine begrenzte Resource, die nur ein Programm gleichzeitig in Anspruch nehmen kann.

    Willst du die Daten mitschneiden, die über das Kabel gehen? Das kann z.B. Portmon.



  • nein ich will mich ein wenig mit Mikrocontroler arbeiten. Jemand den ich kenne macht nur eine Platine fertig, mit welcher man z.B. externe Schaltungen über einen Computer steuern kann. Das ganze verfügt über 8 analoge Ein-/Ausgänge und über eine serielle und eine parallele Schnittstelle, über die Daten zum PC gesendet werden können.

    ich wollte einfach mal eine Verbindung aufbauen und die Daten von der seriellen Schnittstelle lesen, aber wie es scheint ist das gar nicht so einfach.

    Ich habe also eigentlich 2 Programme. Einmal das Programm, welches den Mikrocontroler steuert (wird übertragen) und einmal mein Programm, welches von der Schnittstelle liest.

    Gruß Sebastian



  • @fluxy,

    "Access denied" kommt, wenn schon ein anderes Programm den Port hat (siehe posting von @cd9000).
    Außerdem fehlt in Deinem Prog noch die Baudrateneinstellung. Die Timeouts liegen auch völlig daneben, lies mal in der MSDN die Beschreibung.

    So klappts:

    // DOS32-Programm zum Senden/Empfangen von Bytes über COM (9600-8N1)
    // Alle empfangenen Bytes werden zurückgesendet.
    // OS: W95, W98, W98SE, WinME, WinNT, Win2000, WinXP
    // Note: Keine Fehlerbehandlung implementiert!
    #include <windows.h>
    #include <stdio.h>
    
    #define COM_BUFFER_SIZE 256       // Read- und Write-Buffer-Size
    #define BD_RATE         CBR_9600 // 9600 Baud
    #define HELP_STRING TEXT("Aufruf mit: progname <COM-Port-Nummer>\r\n")
    
    // Hauptprogramm: Aufruf mit: progname <COM-Port-Nummer>
    int main (int argc, char **argv)
    {
    	DCB           dcb;    
    	DWORD         iBytesWritten;
    	BOOL          bRet      = true;
    	DWORD         dwRead    = 0;
    	DWORD         dwSetMask = EV_RXCHAR | EV_ERR; 
    	DWORD         dwEvtMask; 
    	OVERLAPPED    o;
    	COMMTIMEOUTS  ct;
    	unsigned char InString[COM_BUFFER_SIZE + 1];
    	TCHAR         szCOM[6];
    
    	if (argc == 2 &&                              // progname + COM-Port-Nummer ?
    		  atoi (argv[1]) > 0 && atoi (argv[1]) < 5) // COM1 ... COM4?
    		wsprintf (szCOM, TEXT("COM%s"), argv[1]);   // String "basteln" ...
    	else
    	{ 
    		printf (TEXT("\r\nERROR:\t %s"), HELP_STRING);
    		return (1); // und tschüß ...
    	}
    
    	memset (&o, 0, sizeof (OVERLAPPED)); // Struktur mit 0en füllen
    	o.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL); // einen Event setzten
    
    	HANDLE hCom = CreateFile (szCOM, GENERIC_WRITE | GENERIC_READ, 0, NULL, 
    		                        OPEN_EXISTING, 0, NULL);                     
    
    	if (hCom == INVALID_HANDLE_VALUE)
    	{ // Fehlerausgabe:
    		LPVOID lpMsgBuf;
    		FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 
    										FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
    										MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
    		MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: CreateFile", MB_OK | MB_ICONINFORMATION);
    		LocalFree (lpMsgBuf);
    		return (1); // und tschüß ...
    	}
    
    	dcb.DCBlength = sizeof(DCB);  // Laenge des Blockes MUSS gesetzt sein!
    	GetCommState (hCom, &dcb);    // COM-Einstellungen holen und aendern
    	dcb.BaudRate  = BD_RATE;      // Baudrate
    	dcb.ByteSize  = 8;            // Datenbits
    	dcb.Parity    = NOPARITY;     // Parität
    	dcb.StopBits  = ONESTOPBIT;   // Stopbits
    	SetCommState (hCom, &dcb);    // COM-Einstellungen speichern
    
    	GetCommTimeouts (hCom, &ct);
    	// Warte-Zeit [ms] vom Beginn eines Bytes bis zum Beginn des nächsten Bytes 
    	ct.ReadIntervalTimeout         = 1000 / BD_RATE * (dcb.ByteSize + 
    		                                                 (dcb.Parity == NOPARITY ? 0 : 1) + 
    																										 (dcb.StopBits == ONESTOPBIT ? 1 : 2)) * 2;
    	ct.ReadTotalTimeoutMultiplier  = 0;  // [ms] wird mit Read-Buffer-Size multipliziert
    	ct.ReadTotalTimeoutConstant    = 50; // wird an ReadTotalTimeoutMultiplier angehängt
    	ct.WriteTotalTimeoutMultiplier = 0;
    	ct.WriteTotalTimeoutConstant   = 0;
    	SetCommTimeouts (hCom, &ct);
    
    	// Zwischenspeicher des serial-Drivers einstellen (für read und write):
    	SetupComm (hCom, COM_BUFFER_SIZE, COM_BUFFER_SIZE);
    	SetCommMask (hCom, dwSetMask); // Empfangssignale definieren
    
    	do  // in Endlos-Schleife auf Empfangssignale warten:
    	{
    		WaitCommEvent (hCom, &dwEvtMask, &o); // Event mit Empfangssignalen verknüpfen
    
    		if (WAIT_OBJECT_0 == WaitForSingleObject (o.hEvent, INFINITE)) // warten bis Event
    		{
    			if (dwEvtMask & EV_RXCHAR) // Zeichen an RxD empfangen:
    			{
    				bRet = ReadFile (hCom, &InString, sizeof (InString), &dwRead, NULL);
    
    				if (!bRet)
    				{ // Fehlerausgabe:
    					LPVOID lpMsgBuf;
    					FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | 
    													FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
    													MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    													(LPTSTR) &lpMsgBuf, 0, NULL);
    					MessageBox (NULL, (LPCTSTR)lpMsgBuf, "Error: ReadFile", 
    											MB_OK | MB_ICONINFORMATION);
    					LocalFree (lpMsgBuf);
    				}
    				else
    				{ // Ausgabe (oder Verarbeitung) der empfangenen Bytes:
    					InString[dwRead] = '\0'; // in "zero-ended"-String verwandeln
    					printf (TEXT("\r\n\tRxD (%d Byte(s)): %s"), dwRead, InString);
    					WriteFile (hCom, &InString, dwRead, &iBytesWritten, NULL); // Senden der Bytes
    				}
    			}
    
    			if (dwEvtMask & EV_ERR) 
    			{
    				MessageBox (NULL, "Error empfangen", "Error: ReadFile", MB_OK);
    				break; // Schleifen-Abbruch
    			}
    		}
    	}
    	while (1);
    
    	CloseHandle (hCom);     // COM schließen
    	CloseHandle (o.hEvent); // Event-Handle zurückgeben
    
    	return (0);
    }
    

    Die Quellcode-Teile kannst Du nach Belieben in Dein Prog einbauen.

    Blackbird


Anmelden zum Antworten