Lecture des états GPIO à l'aide de C

8

J'ai implémenté cet exemple pour me familiariser avec la programmation GPIO de base en C. Le code montre comment écrire sur les broches GPIO mais n'indique pas explicitement comment lire l'état des broches. Je soupçonne que WiringPi sera finalement une meilleure solution car je voudrai éventuellement lire l'état d'une broche de sortie , mais en attendant, j'aimerais terminer ma randonnée à travers le code de Dom et Gert. Comment puis-je lire la valeur d'une épingle?

bobthechemist
la source
Vous voulez expliquer le downvote?
bobthechemist
2
Les votes négatifs sont ridicules, vous avez peut-être bouleversé quelqu'un à un moment donné. +1 de moi juste pour compenser.
goldilocks

Réponses:

6

Cet exemple d'Elinux utilise des E / S mappées en mémoire . Le noyau exporte également une interface espace utilisateur via /sys/class/gpio, 1 qui est également documentée sur elinux . En travaillant en C, vous utiliseriez de bas niveau read()/ write()au lieu de echo, évidemment. N'utilisez pas de fonctions basées sur des flux de niveau supérieur.

Certains programmeurs deviennent un peu contrariés lorsqu'on leur dit d'utiliser une interface de fichier pour les choses qui, selon eux, devraient être effectuées avec les appels système. C'est purement une question de style - ils équivalent exactement à la même chose . Il n'y a pas de "surcharge d'E / S supplémentaire", etc., accéder à un fichier dans ce cas car ce n'est pas un vrai fichier, c'est une interface noyau. Exactement comme n'importe quel autre système ABI que vous ayez jamais utilisé, seulement différent. L'utilisation des nœuds /procet /sysa été longtemps préférée par les développeurs du noyau, mais je vois toujours des gens déterminés à utiliser les appels système là où ils le peuvent - par exemple sysfs(), malgré le fait qu'il le man 2 sysfsdit clairement:

Cet appel système dérivé de System-V est obsolète; ne l'utilisez pas. Sur les systèmes avec / proc, les mêmes informations peuvent être obtenues via / proc / filesystems; utilisez plutôt cette interface.

Il s'agit d'une page de manuel de la bibliothèque C vous indiquant d' utiliser l' /procinterface . Si ce n'est pas assez bon pour vous convaincre, rien ne l'est. /sysc'est le même genre de chose. Ce qui est important: ce n'est pas parce que vous utilisez un nœud de fichier au lieu d'une API spécifique à C que vous ne faites pas de véritable programmation, ou que les performances en souffriront, etc. etc. Certaines personnes pourraient dire que c'est en fait une fonctionnalité intéressante . C'est également la méthode recommandée par les personnes qui ont écrit le noyau du système d'exploitation.

Une introduction rapide à l'interface GPIO se trouve dans [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)

Il existe différents tutoriels et autres en ligne en plus de celui d'elinux. Je n'utilise que I2C, sinon je vous donnerais une réponse plus directe.

Si vous êtes intéressé à écrire du code d'espace noyau accédant à GPIO, vous pouvez jeter un œil ici , bien que je pense que ce n'est vraiment utile que si vous voulez écrire un pilote pour un périphérique spécifique et créer votre propre API d'espace utilisateur.


1. Étant donné que les E / S mappées mem doivent également utiliser la lecture / écriture, je ne sais pas si une méthode offre un avantage significatif par rapport à l'autre ici. L'utilisation de l' /sysinterface sera certainement plus portable, si vous recherchez du code qui fonctionnera sur autre chose qu'un Raspberry Pi.

Boucles d'or
la source
Merci. Mon passage à la langue a été Mathematica, donc quand il a été porté sur le RPi, j'ai sauté. L'accès au GPIO via les commandes natives de Wolfram est un peu lent pour le moment, donc j'essaie d'apprendre suffisamment de c pour m'éviter des ennuis. (donc pas de code d'espace noyau pour moi!)
bobthechemist
read()/ write()et les fonctions basées sur le descripteur de fichier associé (par opposition au flux de fichiers ) ne sont en fait pas Standard C, mais elles sont POSIX et standard sur Linux. Il y a une introduction ici: gnu.org/software/libc/manual/html_node/… Les flux de fichiers standard peuvent fonctionner, mais d'après mon expérience, ils ont également posé problème pour WRT /syset /proc; utiliser les descripteurs de niveau inférieur n'est plus gênant ni difficile de toute façon. Bonne chance!
goldilocks