Verwendung von GPIO Ports unter Windows 11



  • Hallo,

    ich bin relativ neu in der C++ Welt (komme von Java).
    Ich versuche nun seit 3 Tagen die GPIO's zu verwenden und scheitere kläglich. Vielleicht könnt ihr mir helfen.

    Der Hersteller des PC's hat mir ein Beispiel-Programm zur verfügung gestellt wo ich aber immer über die Meldung stolpere:
    "Failed to initialize WinIo."

    Hir einmal der Quellcode:

    // DEMO.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung.
    //
    
    // demo.cpp : Diese Datei enthält die Hauptfunktion. Hier wird die Programmausführung gestartet und beendet.
    //
    
    
    #include <iostream>
    #include <tchar.h>
    #include <Windows.h>
    
    typedef bool(_stdcall* INITIALIZEWINIO)(void);
    typedef void(_stdcall* SHUTDOWNWINIO)(void);
    typedef bool(_stdcall* GETPORTVAL)(WORD, PDWORD, BYTE);
    typedef bool(_stdcall* SETPORTVAL)(WORD, DWORD, BYTE);
    SHUTDOWNWINIO ShutdownWinIo;
    GETPORTVAL GetPortVal;
    SETPORTVAL SetPortVal;
    INITIALIZEWINIO InitializeWinIo;
    
    VOID SafeGetNativeSystemInfo(__out LPSYSTEM_INFO lpSystemInfo)
    {
    	if (NULL == lpSystemInfo)    return;
    	typedef VOID(WINAPI* LPFN_GetNativeSystemInfo)(LPSYSTEM_INFO lpSystemInfo);
    	LPFN_GetNativeSystemInfo fnGetNativeSystemInfo =
    		(LPFN_GetNativeSystemInfo)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetNativeSystemInfo");
    	if (NULL != fnGetNativeSystemInfo)
    	{
    		fnGetNativeSystemInfo(lpSystemInfo);
    	}
    	else
    	{
    		GetSystemInfo(lpSystemInfo);
    	}
    }
    
    int GetSystemBits()
    {
    	SYSTEM_INFO si;
    	SafeGetNativeSystemInfo(&si);
    	if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
    		si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64)
    	{
    		return 64;
    	}
    	return 32;
    }
    
    #define GETPROC(n, d) 						\
        n = (d) GetProcAddress(lib, #n); 				\
        if (!n) {					\
          fprintf(stderr, "Failed to load " #n " function.\n");	\
          return 1; 						\
        }
    
    //==========================================================WatchDogTimer=========================================================//
    #define SIO_CONFIG_INDEX 0x2E
    #define SIO_CONFIG_DATA 0x2F
    void WatchDogTimer(WORD TimerValue) // 1 < TimerValue < 65535 , Unit = Second
    {
    	// Enter Configuration Mode.
    	SetPortVal(SIO_CONFIG_INDEX, 0x87, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x01, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x55, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x55, 1);
    
    	//=====================LDN 07====================================//
    	SetPortVal(SIO_CONFIG_INDEX, 0x07, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x07, 1);
    
    	//=====================WDT====================================//   
    	SetPortVal(SIO_CONFIG_INDEX, 0x72, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x90, 1);	//Enable WDT
    
    	SetPortVal(SIO_CONFIG_INDEX, 0x74, 1);
    	SetPortVal(SIO_CONFIG_DATA, (BYTE)((TimerValue & 0xFF00) >> 8), 1);	//MSB
    
    	SetPortVal(SIO_CONFIG_INDEX, 0x73, 1);
    	SetPortVal(SIO_CONFIG_DATA, (BYTE)(TimerValue & 0x00FF), 1);	//LSB
    }
    
    void DisableWdt()
    {
    	// Enter Configuration Mode.
    	SetPortVal(SIO_CONFIG_INDEX, 0x87, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x01, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x55, 1);
    	SetPortVal(SIO_CONFIG_INDEX, 0x55, 1);
    
    	//=====================LDN 07====================================//
    	SetPortVal(SIO_CONFIG_INDEX, 0x07, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x07, 1);
    
    	//=====================WDT====================================//   
    	SetPortVal(SIO_CONFIG_INDEX, 0x72, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x00, 1);	//Disable WDT
    
    	SetPortVal(SIO_CONFIG_INDEX, 0x74, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x00, 1);	//MSB
    
    	SetPortVal(SIO_CONFIG_INDEX, 0x73, 1);
    	SetPortVal(SIO_CONFIG_DATA, 0x00, 1);	//LSB
    }
    
    //================================================================================================================================//
    //GPIO0 Input------------------0xA06.bit0
    int IsGpio0Set()
    {
    	DWORD PortValue;
    	GetPortVal(0xA06, &PortValue, 1);
    	if (PortValue & 0x01)
    		return 1;
    	else
    		return 0;
    }
    
    //GPIO1 Input------------------0xA06.bit1
    int IsGpio1Set()
    {
    	DWORD PortValue;
    	GetPortVal(0xA06, &PortValue, 1);
    	if (PortValue & 0x02)
    		return 1;
    	else
    		return 0;
    }
    
    //GPIO1 Output------------------0xA06.bit1
    void Gpio1Set(int outputvalue)
    {
    	DWORD PortValue;
    	GetPortVal(0xA06, &PortValue, 1);
    	if (outputvalue == 0)
    		SetPortVal(0xA06, (PortValue & 0xFD | 0x00), 1);
    	else
    		SetPortVal(0xA06, (PortValue & 0xFD | 0x02), 1);
    }
    
    int main() {
    
    	HMODULE lib = NULL;
    	DWORD PortValue;
    
    	std::cout << "Hier läuft ein: " << GetSystemBits() << "-Bit System" << std::endl;
    	// 32-Bit System
    	if (GetSystemBits() == 32) {
    		lib = LoadLibrary(TEXT("WinIo32.dll"));
    	}
    	// 64-Bit System
    	else if (GetSystemBits() == 64) {
    		//lib = LoadLibrary(_T("C:\\\\Users\\\\LokalAdmin\\\\Downloads\\\\H6 GPIO\\\\Windows\\\\WinIo64.dll"));
    		lib = LoadLibraryA("C:\\\\Users\\\\LokalAdmin\\\\Downloads\\\\H6 GPIO\\\\Windows\\\\WinIo64.dll");
    	}
    
    	GETPROC(InitializeWinIo, INITIALIZEWINIO);
    	GETPROC(ShutdownWinIo, SHUTDOWNWINIO);
    	GETPROC(GetPortVal, GETPORTVAL);
    	GETPROC(SetPortVal, SETPORTVAL);
    
    	if (!InitializeWinIo()) {
    		std::cout << "Failed to initialize WinIo.\n";
    		return 0;
    	}
    	else {
    
    		std::cout << "Initialize WinIo OK.\n";
    
    		//WatchDogTimer(50); // Füttern Sie den Hund 50 Sekunden lang
    
    		if (IsGpio1Set())
    		{
    
    			//GPIO1 Eingang = TRUE
    		}
    		else
    		{
    
    			//GPIO1 EINGANG = FALSE
    		}
    
    		Gpio1Set(1);// GPIO1 Ausgabe TRUE
    		Gpio1Set(0);// GPIO1 AUSGABE FALSE
    	}
    	// Wenn das Programm beendet wird, führen Sie diese Funktion aus
    	ShutdownWinIo();
    }
    

    Ich habe die restlichen GPIO'S mal rausgelöscht da es immer das selbe ist und so der Code um einiges kürzer wird.



  • @Knausbär sagte in Verwendung von GPIO Ports unter Windows 11:

    Failed to initialize WinIo.

    Hast du die Anwendung auch als Administrator gestartet?



  • Hallo,

    ja ich habe VisualStudio als Administrator gestartet und ebenfalls unter Windows folgenden Befehl ausgeführt (und neu gestartet): bcdedit.exe /set testsigning on

    Alles ohne Erfolg...



  • Wenn du die genaue interne Funktion herausfinden möchtest, warum InitializeWinIo() fehlschlägt, könntest du dir die Sourcen unter WinIO dazu ziehen und selber ein Testprogramm aufsetzen, das direkt diese Sourcen einbindet und InitializeWinIo() aufruft (und dann mittels Breakpoint in der Funktion step-by-step den Code durchdebuggen).

    Laut Source von InitializeWinIo() gibt es mehrere Codestellen, an denen false zurückgegeben wird.



  • Wie gesagt ich bin relativ frisch in C++.
    Mit den Brakpoints bekomme ich hin aber ich kann nichts mit WinIO und InitializeWinIo() anfangen.

    Wäre über jede Hilfe dankbar



  • Du verstehst schon, daß die Fehlermeldung durch den Aufruf von InitializeWinIo() in deinem gezeigten Code in den Zeilen 160 - 162 kommt, oder?

    Und diese Funktion (wenn du auf diesen Link InitializeWinIo() klickst, um die Sourcen davon zu sehen) ruft intern 4 weitere Funktionen auf, die eben fehlschlagen können und alle geben dann false zurück (leider weiß man daher nur bei Auswertung des Rückgabewertes eben nicht, was genau die korrekte Initialisierung verhindert).

    Ziehe dir daher den Source Code unter WinIo 3.0. Die Samples sind leider für C#/.NET und helfen dabei nicht weiter.

    Erstelle daher im Visual Studio eine neue Solution (auf deutsch: Projektmappe) und füge dann das Projekt WinIo.vcproj hinzu (also das bei dir dann lokal abgelegte Projekt aus dem WinIO Source Code).
    Nun fügst du ein weiteres C++ Konsolenprojekt zu dieser Projektmappe hinzu mit folgendem Code:

    #include "../WinIO/Source/Dll/winio.h" // <- hier mußt du evtl. den Pfad auf die Headerdatei noch anpassen!
    
    int main()
    {
    	if (!InitializeWinIo()) {
    		std::cout << "Failed to initialize WinIo.\n";
    		return -1;
    	}
    	else {
    		std::cout << "Initialize WinIo OK.\n";
    	}
    
    	return 0;
    }
    

    Als letztes muß noch die lokale WinIO-Lib in den Linkeroptionen angegeben werden (evtl. recherchieren bzw. nachfragen).

    Dann die gesamte Projektmappe bauen (kompilieren). Achte darauf, daß als Konfiguration "Debug" in der oberen ComboBox ausgewählt ist!
    Nun setzt du 2 Breakpunkte in dem Konsolenprojekt beim Aufruf von InitializeWinIo() als auch im WinIO-Projekt in der Datei "Source/Dll/WinIo.cpp" in der Funktion InitializeWinIo() selbst.
    Wenn du dann das Programm im VS startest, dann sollte es beim ersten Breakpoint halten und du kannst dann mit der Taste F11 in die Funktion springen und dann mit F10 jeweils die einzelnen Codezeilen durchgehen, solange bis einer der internen Funktionen fehlschlägt und eines der return false-Zeilen ausgeführt wird. Nun weißt du welche der 4 Funktionen dadrin fehlgeschlägt.

    PS: Was dein gezeigter Code etwas komplizierter macht, ist, daß je nach Rechnerarchitektur entweder die WinIO-DLL für 32 oder 64bit dynamisch geladen wird.
    Was wird denn für dich bei dem Testprogramm ausgegeben: "Hier läuft ein: " ??? "-Bit System".
    Ich nehme mal an, du hast ein 64bit Windows und es wird 64 ausgegeben!?


Anmelden zum Antworten