Lectura de estados GPIO usando C

8

He implementado este ejemplo para familiarizarme con la programación básica de GPIO en C. El código muestra cómo escribir en pines GPIO, pero no establece explícitamente cómo leer el estado de los pines. Sospecho que WiringPi será en última instancia una mejor solución ya que eventualmente querré leer el estado de un pin de salida , pero mientras tanto me gustaría completar mi recorrido a través del código de Dom y Gert. Entonces, ¿cómo podría leer el valor de un pin?

bobthechemist
fuente
¿Te importaría explicar el voto negativo?
bobthechemist
2
Los votos negativos son ridículos, quizás hayas molestado a alguien en algún momento. +1 de mí solo para compensar.
Ricitos de oro

Respuestas:

6

Ese ejemplo de elinux usa IO mapeado en memoria . El núcleo también exporta una interfaz de espacio de usuario a través de 1/sys/class/gpio , que también está documentada en elinux . Trabajando en C usarías bajo nivel / en lugar de , obviamente. No use funciones basadas en flujos de nivel superior.read()write()echo

Algunos programadores se molestan un poco cuando se les dice que usen una interfaz de archivo para cosas que creen que deberían hacerse con las llamadas al sistema. Esto es puramente una cuestión de estilo : equivalen exactamente a lo mismo . No hay "gastos generales de E / S adicionales", etc., accediendo a un archivo en este caso porque no es un archivo real, es una interfaz del núcleo. Exactamente como cualquier otro sistema ABI que hayas usado, solo que diferente. El uso de /procy /sysnodos ha sido preferido durante mucho tiempo por los desarrolladores del kernel, pero todavía veo personas decididas a usar llamadas al sistema donde pueden, por ejemplo sysfs(), a pesar del hecho de que man 2 sysfsdice claramente:

Esta llamada al sistema derivada de System-V es obsoleta; no lo uses En sistemas con / proc, se puede obtener la misma información a través de / proc / filesystems; use esa interfaz en su lugar.

Esa es una página de manual de la biblioteca C que le dice que use la /procinterfaz . Si eso no es lo suficientemente bueno como para convencerte, nada lo es. /sysEs el mismo tipo de cosas. El punto es: solo porque esté usando un nodo de archivo en lugar de alguna API específica de C no significa que no esté haciendo una programación real, o que el rendimiento se verá afectado, etc. etc. Algunas personas podrían decir que en realidad es una buena característica. También es el método recomendado por las personas que escribieron el núcleo del sistema operativo.

Se puede encontrar una introducción rápida a la interfaz GPIO en [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)

Parecen varios tutoriales y otros en línea además del elinux. Solo he estado usando I2C, de lo contrario te daría una respuesta más directa.

Si está interesado en escribir código de espacio del kernel para acceder a GPIO, puede echar un vistazo aquí , aunque creo que eso realmente solo es útil si desea escribir un controlador para un dispositivo específico y crear su propia API de espacio de usuario.


1. Dado que IO mapeado por mem también debe usar lectura / escritura, no estoy seguro si un método proporciona una ventaja significativa sobre el otro aquí. El uso de la /sysinterfaz ciertamente será más portátil, si está buscando código que se ejecute en otras cosas que no sean una frambuesa pi.

Ricitos de oro
fuente
Gracias. Mi preferencia por el lenguaje ha sido Mathematica, así que cuando fue portado al RPi, salté. El acceso a GPIO a través de comandos nativos de Wolfram es un poco lento en este momento, por lo que estoy tratando de aprender suficiente c para mantenerme fuera de problemas. (¡así que no hay código de espacio del kernel escrito para mí!)
bobthechemist
read()/ write()y las funciones basadas en el descriptor de archivo asociado (a diferencia de la secuencia de archivos ) en realidad no son Estándar C, pero son POSIX y estándar en Linux. Aquí hay una introducción: gnu.org/software/libc/manual/html_node/… Las secuencias de archivos estándar pueden funcionar, pero en mi experiencia también han sido problemáticas para WRT /sysy /proc; usar los descriptores de nivel inferior ya no es incómodo o difícil de todos modos. ¡Buena suerte!
Ricitos de oro