Чтение состояний GPIO с использованием C

8

Я реализовал этот пример, чтобы познакомиться с базовым программированием на GPIO на языке C. Код демонстрирует, как записывать на контакты GPIO, но не указывает явно, как считывать состояние контактов. Я подозреваю, что WiringPi в конечном итоге будет лучшим решением, так как в конечном итоге я захочу прочитать состояние выходного вывода , но пока что я хотел бы завершить свой поход через код Dom и Gert. Как тогда, я мог прочитать значение булавки?

bobthechemist
источник
Не хочешь объяснить отрицательный голос?
bobthechemist
2
Отрицательные голоса - это просто смешно, возможно, вы в какой-то момент расстроили кого-то. +1 от меня просто чтобы компенсировать.
Златовласка

Ответы:

6

Этот пример из elinux использует отображенный в память ввод -вывод . Ядро также экспортирует пространство интерфейса пользователя через /sys/class/gpio, 1 , который также документированной на elinux . Работая в C, вы бы использовали низкий уровень read()/ write()вместо echo, очевидно. Не используйте потоковые функции более высокого уровня.

Некоторые программисты немного расстраиваются, когда им говорят, что нужно использовать файловый интерфейс для вещей, которые, по их мнению, следует делать с помощью системных вызовов. Это чисто вопрос стиля - это одно и то же . В этом случае нет необходимости в «дополнительных затратах на ввод-вывод» и т. Д., Потому что это не настоящий файл, а интерфейс ядра. Точно так же, как любая другая система ABI, которую вы когда-либо использовали, только другая. Разработчики ядра давно предпочитают использовать узлы /procи /sys, но я все еще вижу людей, решивших использовать системные вызовы там, где они могут, например sysfs(), несмотря на то, man 2 sysfsчто ясно сказано:

Этот производный системный вызов System-V устарел; не используйте это. В системах с / proc ту же информацию можно получить через / proc / filesystems; используйте этот интерфейс вместо.

Это справочная страница библиотеки C, рассказывающая вам об использовании /procинтерфейса . Если этого недостаточно, чтобы убедить вас, ничего не значит. /sysэто то же самое. Дело в том, что то, что вы используете файловый узел вместо какого-то специфичного для C API, не означает, что вы не занимаетесь реальным программированием, что производительность снижается и т. Д. И т. Д. Некоторые люди могут сказать, что это действительно хорошая функция. Это также метод, рекомендованный людьми, которые написали ядро ​​ОС.

Краткое введение в интерфейс GPIO можно найти в [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)

Там, кажется, различные учебники и такие онлайн, в дополнение к Elinux. Я только использовал I2C, иначе я бы дал вам более прямой ответ.

Если вы заинтересованы в написании кода пространства ядра для доступа к GPIO, вы можете посмотреть здесь , хотя я думаю, что это действительно полезно, только если вы хотите написать драйвер для конкретного устройства и создать свой собственный API пространства пользователя.


1. Поскольку мем-сопоставленный ввод-вывод также должен использовать чтение / запись, я не уверен, что один метод дает здесь существенное преимущество перед другим. Использование /sysинтерфейса, безусловно, будет более переносимым, если вы ищете код, который будет работать не только на Raspberry Pi.

Златовласка
источник
Спасибо. Я перешел на язык Mathematica, поэтому, когда он был перенесен на RPi, я прыгнул. Доступ к GPIO через нативные команды Wolfram в настоящее время немного замедлен, поэтому я пытаюсь выучить достаточно c, чтобы избежать неприятностей. (так что мне не нужно писать код ядра!)
bobthechemist
read()/ write()и связанные функции файлового дескриптора (в отличие от файлового потока ) на самом деле не являются стандартом C, но являются POSIX и стандартом для linux. Здесь есть введение: gnu.org/software/libc/manual/html_node/… Стандартные файловые потоки могут работать, но, по моему опыту, они также были проблематичными для WRT /sysи /proc; использование дескрипторов более низкого уровня больше не является неловким или трудным. Удачи!
Златовласка