Lesen von GPIO-Zuständen mit C.

8

Ich habe dieses Beispiel implementiert, um mich mit der grundlegenden GPIO-Programmierung in C vertraut zu machen. Der Code zeigt, wie auf GPIO-Pins geschrieben wird, gibt jedoch nicht explizit an, wie der Status von Pins gelesen wird. Ich vermute, dass WiringPi letztendlich eine bessere Lösung sein wird, da ich irgendwann den Status eines Ausgangs-Pins lesen möchte , aber in der Zwischenzeit möchte ich meine Wanderung durch Dom und Gerts Code abschließen. Wie könnte ich dann den Wert eines Pins lesen?

Bobthechemist
quelle
Möchtest du die Ablehnung erklären?
Bobthechemist
2
Die Abstimmungen sind lächerlich, vielleicht haben Sie irgendwann jemanden verärgert. +1 von mir nur zum Ausgleich.
Goldlöckchen

Antworten:

6

Das Beispiel aus elinux verwendet Memory-Mapped IO . Der Kernel exportiert auch eine Userspace - Schnittstelle über /sys/class/gpio, 1 , die ebenfalls auf elinux dokumentiert . Wenn Sie in C arbeiten, würden Sie natürlich low level read()/ write()anstelle von verwenden echo. Verwenden Sie keine Stream-basierten Funktionen auf höherer Ebene.

Einige Programmierer sind etwas verärgert, wenn sie aufgefordert werden, eine Dateischnittstelle für Dinge zu verwenden, von denen sie glauben, dass sie mit Systemaufrufen erledigt werden sollten. Dies ist nur eine Frage des Stils - sie sind genau dasselbe . In diesem Fall gibt es keinen "zusätzlichen E / A-Overhead" usw., der auf eine Datei zugreift, da es sich nicht um eine echte Datei handelt, sondern um eine Kernelschnittstelle. Genau wie jedes andere System-ABI, das Sie jemals verwendet haben, nur anders. Die Verwendung von /procund /sysKnoten wurde von den Kernel-Entwicklern seit langem bevorzugt, aber ich sehe immer noch Leute, die entschlossen sind, Systemaufrufe zu verwenden, wo sie können - z. B. sysfs()trotz der Tatsache, man 2 sysfsdass klar gesagt wird:

Dieser von System V abgeleitete Systemaufruf ist veraltet. benutze es nicht. Auf Systemen mit / proc können dieselben Informationen über / proc / filesystems abgerufen werden. Verwenden Sie stattdessen diese Schnittstelle.

Dies ist eine Manpage der C-Bibliothek, in der Sie aufgefordert werden , die /procBenutzeroberfläche zu verwenden . Wenn das nicht gut genug ist, um Sie zu überzeugen, ist nichts. /sysist das Gleiche. Der Punkt ist: Nur weil Sie einen Dateiknoten anstelle einer C-spezifischen API verwenden, heißt das nicht, dass Sie keine echte Programmierung durchführen oder dass die Leistung darunter leidet usw. usw. Einige Leute könnten sagen, dass dies tatsächlich eine nette Funktion ist. Dies ist auch die Methode, die von den Leuten empfohlen wird, die den Betriebssystemkern geschrieben haben.

Eine kurze Einführung in die GPIO-Schnittstelle finden Sie in [kernel-src]/Documentation/ABI/testing/sysfs-gpio:

  GPIOs are only made available to userspace by an explicit
  "export" operation.  If a given GPIO is not claimed for use by
  kernel code, it may be exported by userspace (and unexported later).
  Kernel code may export it for complete or partial access.

  GPIOs are identified as they are inside the kernel, using integers in
  the range 0..INT_MAX.  See Documentation/gpio.txt for more information.

    /sys/class/gpio
        /export ... asks the kernel to export a GPIO to userspace
        /unexport ... to return a GPIO to the kernel
        /gpioN ... for each exported GPIO #N
            /value ... always readable, writes fail for input GPIOs
            /direction ... r/w as: in, out (default low); write: high, low
            /edge ... r/w as: none, falling, rising, both
        /gpiochipN ... for each gpiochip; #N is its first GPIO
            /base ... (r/o) same as N
            /label ... (r/o) descriptive, not necessarily unique
            /ngpio ... (r/o) number of GPIOs; numbered N to N + (ngpio - 1)

Es scheinen verschiedene Tutorials und solche online neben dem elinux zu sein. Ich habe nur I2C verwendet, sonst würde ich Ihnen eine direktere Antwort geben.

Wenn Sie daran interessiert sind, Kernel-Space-Code zu schreiben, der auf GPIO zugreift, können Sie hier einen Blick darauf werfen , obwohl ich denke, dass dies nur dann wirklich nützlich ist, wenn Sie einen Treiber für ein bestimmtes Gerät schreiben und Ihre eigene User-Space-API erstellen möchten.


1. Da mem-mapped IO auch Lesen / Schreiben verwenden muss, bin ich mir nicht sicher, ob eine Methode hier einen signifikanten Vorteil gegenüber der anderen bietet. Die Verwendung der /sysBenutzeroberfläche ist sicherlich portabler, wenn Sie nach Code suchen, der auf anderen Dingen als einem Himbeer-Pi ausgeführt werden kann.

Goldlöckchen
quelle
Vielen Dank. Meine Sprache war Mathematica. Als sie auf das RPi portiert wurde, bin ich gesprungen. Der GPIO-Zugriff über native Wolfram-Befehle ist im Moment etwas träge, daher versuche ich, genug c zu lernen, um Probleme zu vermeiden. (
Also
read()/ write()und die zugehörigen Funktionen auf der Basis von Dateideskriptoren (im Gegensatz zu Dateistreams ) sind eigentlich nicht Standard C, aber sie sind POSIX und Standard unter Linux. Hier gibt es eine Einführung: gnu.org/software/libc/manual/html_node/… Standarddateistreams funktionieren möglicherweise, aber meiner Erfahrung nach waren sie auch problematisch für WRT /sysund /proc; Die Verwendung der Deskriptoren der unteren Ebene ist ohnehin nicht mehr umständlich oder schwierig. Viel Glück!
Goldlöckchen