В этой статье (перевод [1]) рассматривается базовое управление GPIO с помощью интерфейса sysfs, предоставляемого ядром Linux. Фактически нам не понадобится ничего программировать, поскольку все описанные действия будут выполняться в строке команд (shell) операционной системы. Будут показаны некоторые примеры, как это работает на Raspberry Pi.
Существуют разные способы доступа к аппаратному обеспечению GPIO из программ [3, 4, 5]. Однако sysfs вероятно самый простой способ, который поддерживается ядром Linux и делает устройства видимыми в файловой системе, чтобы мы могли экспериментировать из командной строки без необходимости писать какой-либо код. Для простых приложений вы можете использовать его таким образом, либо интерактивно, либо поместив команды в скрипт.
Sysfs это псевдофайловая система ядра Linux, которая предоставляет информацию по различным подсистемам ядра, аппаратным устройствам, драйверам устройств, которые доступны в пространстве доступа пользователя (user space) через обращение к виртуальным файлам. Устройства GPIO появляются в системе как часть sysfs.
Следует отметить, что в настоящий момент этот интерфейс считается устаревшим в пользу замены его на новое GPIO character device API [3]. Это новое API решает определенные проблемы интерфейса sysfs. Однако оно не может быть также просто использовано из файловой системы, как sysfs, так что интерфейс sysfs некоторое время все еще будет поддерживаться.
Замечание: если вы будете пробовать команды sysfs на Raspberry Pi, то следует выполнить некоторую предварительную настройку. Например, необходимо добавить пользователя в группу gpio, чтобы у него была возможность выполнять команды доступа к GPIO без необходимости пользоваться привилегиями root (см. следующую врезку).
Текущие модели Raspberry Pi и Raspberry Pi Zero оборудованы 40-pin коннектором "папа", через который выводятся порты GPIO, напряжения питания и некоторые другие сигналы. Здесь имеются 26 выводов GPIO, напряжения +5V, +3.3V, общий провод земли (GND), а также некоторые специальные выводы для функции ID EEPROM.
26 портов GPIO можно индивидуально конфигурировать как входы или выходы с уровнями логики 3.3V. Без риска повреждения они не могут работать с более высокими уровнями логики (такими как 5V).
У неподключенных входов обычно может быть неопределенный логический уровень. Чтобы это исправить, могут использоваться подтягивающие резисторы - к +3.3V (pullup) или к GND (pulldown). Часто используют внешние подтягивающие резисторы, однако могут быть активированы программно внутренние подтягивающие резисторы. У GPIO2 и GPIO3 есть фиксированные pullup-резсторы на плате, в то время как остальные порты GPIO могут быть сконфигурированы для включения pullup или pulldown резисторов (или без таковых).
Также поддерживаются функции для базового цифрового ввода/вывода. Некоторые функциональные возможности доступны на всех выводах, и некоторые доступны только на определенных выводах:
PWM (pulse-width modulation, ШИМ). Аппаратно поддерживается на GPIO12, GPIO13, GPIO18, GPIO19. PWM может быть также реализована программно на любом порте GPIO.
SPI (Serial Peripheral Interface). Два порта SPI предоставлены на GPIO10, GPIO9, GPIO11, GPIO8, GPIO7 and GPIO20, GPIO19, GPIO21, GPIO18, GPIO17, GPIO16.
I2C. Интерфейс I2C (TWI) поддерживается выводами GPIO2 и GPIO3.
UART. На выводах GPIO14 и GPIO15 реализован последовательный интерфейс, работающий как консоль управления.
Важно понимать разницу между номерами портов GPIO (например GPIO14) и номерами выводов разъема, на которые они выведены. Например, GPIO14 выведен на вывод 8 разъема.
Для разрешения программного доступа к устройствам GPIO необходимо это делать с привилегиями суперпользователя (root), либо пользователь должен быть членом группы gpio. Для работы под суперпользователем можно использовать утилиту sudo.
По умолчанию пользователи Raspberry Pi работают под учетной записью pi. Чтобы не вводить каждый раз команду sudo, можно добавить пользователя pi в группу gpio следующей командой:
$ sudo adduser pi gpio
Adding user `pi' to group `gpio' ...
Adding user pi to group gpio Done.
Конечно, если вы используете другое имя пользователя, замените им имя pi из пример выше. Чтобы команда вступила в силу, необходимо перелогиниться. Проверить, в какой группе находится текущий пользователь, можно с помощью команды groups:
$ groups
pi adm dialout cdrom sudo audio video plugdev games users input netdev gpio i2c spi
Если вы планируете экспериментировать на Raspberry Pi с некоторыми более продвинутыми возможностями программирования GPIO, то можете разрешить это с помощью программы конфигурирования [9]. Утилита конфигурирования запускается следующей командой:
$ sudo raspi-config
После этого выберите "Interfacing Options":
Эти настройки касаются к таких функций GPIO, как SPI, I2C, Serial и 1-Wire. Вы можете просмотреть эти настройки и разрешить соответствующие опции, если планируете использовать их в будущем. Для базового программирования GPIO эти опции следует оставить запрещенными.
Если на вашей системе загружен подходящий драйвер sysfs, то вы увидите аппаратуру GPIO в папке /sys/class/gpio файловой системы.
$ ls /sys/class/gpio/
export* gpiochip0@ gpiochip100@ gpiochip504@ unexport*
Обратите внимание, что имена устройств, начинающиеся с gpiochip, обозначают контроллеры GPIO, и их нельзя использовать напрямую.
Базовые шаги для использования вывода GPIO из интерфейса sysfs заключаются в следующем:
1. Экспорт вывода (export pin). 2. Установка направления для pin - вход (input) или выход (output). 3. Если это выход, то можно установить его уровень в лог. 0 или лог. 1. 4. Если это вход, то можно прочитать его логический уровень. 5. Когда работа с выводом завершена, завершение экспорта (unexport pin).
Для экспорта вывода мы записываем имя/номер вывода в псевдофайл /sys/class/gpio/export. Это будет означать, что мы хотим использовать определенный вывод GPIO, и делаем его видимым в иерархии файловой системы sysfs. После того, как работа с выводом завершена, мы можем отменить экспорт вывода. Необходимо явно делать export/unexport вывода, чтобы предотвратить ошибки случайного нежелательного доступа к неправильному выводу.
Шаг 1. В качестве примера мы можем сделать export вывода GPIO24 (соответствующий выводу коннектора 18 платы Raspberry Pi) следующей командой:
$ echo 24 >/sys/class/gpio/export
Команда ls покажет изменения в каталоге /sys/class/gpio:
$ ls /sys/class/gpio
export* gpio24@ gpiochip0@ gpiochip100@ gpiochip504@ unexport*
Здесь gpio24 это символическая ссылка на директорию, где находится несколько файлов:
Шаг 2. На этом шаге мы будем настраивать вывод порта на вход или выход. Это осуществляется записью в файлы in или out. Например, для установки gpio24 в качестве входа выполните команду:
$ echo in >/sys/class/gpio/gpio24/direction
Для установки на выход команда следующая:
$ echo out >/sys/class/gpio/gpio24/direction
Этот файл можно прочитать, чтобы определить текущее состояние вывода порта:
$ cat /sys/class/gpio/gpio24/direction
out
Хотя это может быть неверно для всей аппаратуры, вывод GPIO будет по умолчанию настроен на вход, поскольку это наиболее безопасно на аппаратном уровне.
Шаг 3. Если вывод настроен на вывод, то мы можем установить его логический уровень. Для этого в файл value записывается 0 или 1. В следующем примере выход устанавливается в лог. 0:
$ echo 0 >/sys/class/gpio/gpio24/value
Для установки в лог 1:
$ echo 1 >/sys/class/gpio/gpio24/value
Если вывод сконфигурирован на вход, то попытка выполнения этих команд приведет к ошибке:
bash: echo: write error: Operation not permitted
Шаг 4. Если вывод сконфигурирован на вход, то мы можем прочитать его уровень чтением файла value:
$ cat /sys/class/gpio/gpio24/value
0
Можно ли прочитать правильное значение уровня вывода, когда он настроен на выход? Ответ - да, можно. Значение, которое будет прочитано, зависит от реальной аппаратуры. На Raspberry Pi вы должны увидеть то же самое значение, которое было выведено, но на некоторой аппаратуре прочитанный уровень может отражать реальный уровень сигнала, который может отличаться, если внешние схемы подтягивают уровень к лог. 1 или к лог. 0.
Шаг 5. Если использование вывода GPIO завершено, необходимо отменить его экспорт. Для этого нужно записать номер GPIO в файл unexport, например:
$ echo 24 >/sys/class/gpio/unexport
После этого символическая ссылка для gpio24 исчезнет в sysfs:
$ ls /sys/class/gpio
export* gpiochip0@ gpiochip100@ gpiochip504@ unexport*
[Пример подключения к GPIO]
Если вы хотите попробовать выполнить описанные выше действия на Raspberry Pi, то подключите цифровой мультиметр к контактам 18 (GPIO24) и 6 (GROUND) разъема GPIO. Переключите мультиметр в режим измерения постоянного напряжения (DC V).
Если запустить следующие команды, то вы должны увидеть напряжение около 3.3V (уровень лог. 1):
Следующая команда установит значение уровня лог. 0, и мультиметр покажет напряжение, близкое к 0:
$ echo 0 >/sys/class/gpio/gpio24/value
Вы можете также попробовать прочитать состояние вывода, настроенного на вход. Если вы соедините перемычкой контакт 18 (GPIO24) и контакт 6 (GND), то прочитанный уровень должен быть 0. Внимание! Не устанавливайте перемычку, пока не выполните команду настройки порта GPIO24 на ввод, потому что ранее этот порт был настроен на вывод.
$ echo in >/sys/class/gpio/gpio24/direction
$ cat /sys/class/gpio/gpio24/value
0
Теперь, если соединить перемычкой контакт 18 и контакт 1 (3.3V), то уровень будет прочитан как лог. 1:
$ cat /sys/class/gpio/gpio24/value
1
Будьте осторожны с подключением выводов, неправильное подключение может повредить Raspberry Pi.
Вместо испытаний на основе мультиметра и перемычек можно собрать простенькую платку gpio-board [6]. На ней отслеживать управление выходов можно с помощью трех светодиодов, а для тестирования чтения входа можно использовать кнопку.
Есть больше функций, которые можно выполнить с помощью контактов GPIO, которые нелегко сделать из интерфейса sysfs. Большинство контактов Raspberry Pi GPIO поддерживают включение внутренних подтягивающих резисторов pullup и pulldown, и вы можете получить прерывание при изменении уровня входного контакта.
[Утилита gpio]
На платформе Raspberry Pi есть удобная утилита gpio [7], которая может управлять выводами удобнее, чем это делается через интерфейс sysfs. Эта утилита может управлять экспортированием портов (export/unexport), устанавливать их направление (direction), устанавливать и считывать уровни, а также запускать более продвинутые функции наподобие PWM. Для установки утилиты gpio выполните команду sudo apt install wiringpi.
Следующая команда выведет подсказку по командной строке:
Запуск man gpio покажет документацию по команде. Одна из полезных опций - возможность прочитать и показать состояние всех выводов GPIO, с представлением номеров контактов и имен портов:
Или даже можно переключать в противоположное состояние уровень вывода, или выдавать на выводе короткий импульс:
$ gpio -g toggle 24
$ gpio -g blink 24
После завершения работы можно отменить экспорт вывода следующей командой:
$ gpio unexport 24
Обратите внимание на опцию -g, это говорит команде использовать номера контактов коннектора (BCM), а не номера по умолчанию, используемые библиотекой WiringPi [8]. Причуда команды заключается в том, что когда в ней применяется export и unexport, то всегда используются номера выводов BCM, так что в этом случае опция -g не нужна.
DESCRIPTION
Утилита GPIO это утилита командной строки, некий "швейцарский ножик" для упрощения
доступа пользователя к выводам GPIO на Raspberry Pi, а также SPI и преобразователям
ADC и DAC Gertboard. Утилита была разработана для упрощения тестирования систем
и диагностики, однако может использоваться в теле скриптов, если необходимо
некое медленное управление выводами GPIO.
Также утилита может управлять выводами платы PiFace IO board и загрузки при
необходимости модулей ядра SPI и I2C.
Дополнительно утилита может использоваться для экспорта в системную директорию
/sys/class/gpio, чтобы позволить позже запускаемым программам использовать
интерфейс /sys/class/gpio без необходимости исполнения с привилегиями root.
OPTIONS
-v Выведет текущую версию, включая ревизию платы Raspberry Pi.
-g Использовать выводы BCM_GPIO вместо номеров выводов библиотеки wiringPi.
Внимание: номера выводов BCM_GPIO всегда используются в командах export
и edge.
-1 Использовать физические номера выводов вместо номеров выводов библиотеки
wiringPi. Внимание: это применимо только к коннектору P1. Таким способом
нельзя использовать выводы коннектора Revision 2 P5, и с опцией -g
номера выводов BCM_GPIO всегда используются с командами export и edge.
-x extension
Приведет к инициализации именованного расширения extension. Расширения
включают в себя имя (например, mcp23017), за которым следует двоеточие,
затем pin-base, а затем дополнительные параметры в зависимости от типа
расширения.
-p Использовать плату интерфейса PiFace и её соответствующие имена выводов.
PiFace всегда появляется на номере вывода 200 в команде gpio. Вы можете
назначить любые номера выводов, которые захотите, в ваших собственных
программах.
read < pin>
Чтение цифрового значения на указанном выводе pin и печать 0 или 1
для представления соответствующего уровня логики.
write < pin> < value>
Запишет указанное значение value (0 или 1) в вывод pin. Предварительно
вам необходимо настроить ввод в режим вывода (output mode).
toggle < pin>
Меняет состояние вывода GPIO; если на выходе 0, то будет 1, и наоборот,
если была 1, то станет 0. Обратите внимание, что в отличие от команды
blink, вывод должен быть предварительно настроен на вывод.
blink < pin>
Выводит на вывод импульсы (on/off). Для завершения нажмите Ctrl-C.
Внимание: эта команда явно настроит вывод в режим вывода.
aread < pin>
Чтение аналогового значения на указанном выводе pin. Эта команда должна
использоваться совместно с флагом -x, чтобы добавить расширение,
которое обрабатывает аналоговые входы. Например, команда
gpio -x mcp3002:200:0 aread 200 прочитает первый аналоговый вход
на микросхеме mcp3002 SPI ADC.
awrite < pin> < value>
Запишет аналоговое значение value в указанный вывод pin. Эта команда
должна использоваться совместно с флагом -x, чтобы добавить расширение,
которое обрабатывает аналоговые выходы. Например, команда
gpio -x mcp4802:200:0 awrite 200 128 запишет значение 128 в первый
порт DAC микросхемы mcp4802 на шине SPI0 Raspberry Pi.
wb < value>
Запишет указанный байт value в 8 основных выводов GPIO. Вы можете
указать префикс 0x для значения байта, чтобы использовать hex формат.
Необходимо предварительно настроить эти выводы на вывод.
readall
Выведет таблицу всех значений выводов GPIO. Будут представлены
реальные прочитанные значения, если вывод настроен в режиме ввода,
или последнее записанное значение, если вывод настроен в режиме
вывода.
Команда readall полезна с модулем расширения (через параметр -x),
однако она не может определить режимы вывода или состояния, так
что поэтому будет выполнять как цифровое, так и аналоговое считывание
на каждом контакте по очереди.
pwm < pin> < value>
Выведет значение ШИМ (0-1023) на указанном выводе. Необходимо
предварительно настроить вывод в режим PWM.
clock < pin> < frequency>
Установит указанную частоту frequency на указанном выводе pin.
Вывод необходимо предварительно настроить в режиме тактирования
(clock mode).
mode < pin> < mode>
Настроит вывод pin в режим ввода (input), вывода (output) или
ШИМ (pwm). Также можно использовать литералы up, down или tri
для установки внутренних pull-up, pull-down резисторов или
режима третьего состояния (off).
Режимы ALT также могут быть установлены с использованием alt0,
alt1, ... alt5.
unexportall
Отменит экспорт всех выводов GPIO в директории /sys/class/gpio.
exports
Напечатает список всех экспортированных выводов GPIO (если таковые
есть) и их текущие значения.
export Экспортирует вывод GPIO в директорию /sys/class/gpio. Используется
наподобие упомянутой выше команды mode, однако поддерживаются
только литералы in, out, high и low. Обратите внимание, что номер
вывода это номер BCM_GPIO, но не номер wiringPi. Команды high и
low предустанавливают выходное значение одновременно с экспортом
в режиме вывода.
Как только вывод GPIO был экспортирован, программа gpio меняет
владельца /sys/class/gpio/gpioX/value, и если то присутствует
в последующих ядрах, псевдофайлы /sys/class/gpio/gpioX/edge
на пользователя, который запустил программу gpio. Это означает,
что вы можете получить маленький скрипт, которым gpio делает
экспорт для настройки выводов gpio, поскольку больше нет нужды
запускать скрипт от имени root, или применять команду sudo.
edge Экспортирует вывод GPIO в директорию /sys/class/gpio, установит
направление направление на input и установит метод прерывания
по перепаду (edge interrupt) в none, rising, falling или both.
Используется так же, как упомянутая выше команда export, и следует
иметь в виду, что используется нумерация выводов BCM_GPIO, но не
нумерация wiringPi.
Так же, как и команды экспорта, владелец псевдофайла будет замен
на пользователя, который запустил программу gpio, так что нет
необходимости использовать права root или sudo.
unexport
Отменяет экспорт вывода GPIO в директории /sys/class/gpio.
wfi < pin> < mode>
Установит указанный вывод pin в поддерживаемый режим прерывания:
rising, falling или both, затем запускается ожидание этого
прерывания. Ожидание осуществляется не по опросу (non-busy
wait), так что процессорное время CPU на ожидание не тратится.
drive group value
Меняет значение pad driver для указанной группы (pad group) на
поддерживаемое drive value. Значение для group могут быть 0, 1
или 2, и value 0 .. 7. Используйте это только если точно знаете,
что делаете.
usbp high | low
Меняет ограничитель тока USB на high (1.2A) или на low (ограничение
по умолчанию, 600 mA). Это применимо только для вариантов плат
Model B+ и Model B, v2.
pwm-bal/pwm-ms
Меняет режим PWM на balanced (по умолчанию), или на mark:space
ratio (традиционный режим).
pwmr Меняет регистр диапазона ШИМ (PWM range). Значение по умолчанию 1024.
gbr channel
Выполнит чтение преобразователя ADC на указанном канале channel
платы Gertboard. Для этой операции необходимо установить
соответствующие перемычки на плате.
gbw channel value
Запишет указанное значение value в выходной канал channel микросхемы
SPI DAC платы Gertboards. Для этой операции необходимо установить
соответствующие перемычки на плате.
Варианты нумерации выводов WiringPi, BCM_GPIO, Physical
Самый быстрый способ получить список выводов и их отличия - запуск
команды gpio readall.
ПРИМЕРЫ
gpio mode 4 output # установит вывод 4 на вывод
gpio -g mode 23 output # установит вывод GPIO 23 на вывод
# (соответствует WiringPi pin 4)
gpio mode 1 pwm # установит вывод 1 в режим ШИМ
gpio pwm 1 512 # установит на выводе 1 значение PWM 512,
# - половинная яркость
gpio export 17 out # настроит GPIO pin 17 на вывод
gpio export 0 in # настроит GPIO pin 0 (SDA0) на ввод.
gpio -g read 0 # чтение GPIO pin 0 (SDA0)
ПРИМЕЧАНИЕ
Когда используются команды export, edge или unexport, номера выводов всегда
указывают как native BCM_GPIO, и никогда как номера wiringPi.
Начиная с ядер 4.1.7 доступен механизм доступа к GPIO на уровне пользователя,
однако wiringPi по умолчанию это не использует - потому что в настоящее
время наблюдаются проблемы, когда делаются попытки запрограммировать
аппаратный режим вывода PWM или clock. Если вы можете обойтись без PWM
или GPIO clock, и вы хотите использовать GPIO из non-root программы, то
необходимо гарантировать, что модуль bcm2835_gpiomem загружен в процессе
запуска системы (boot time). Это должно произойти автоматически, когда вы
разрешили device tree в raspi-config [9]. Вам также может понадобиться
некоторая дополнительная информация в /etc/udev/rules.d/, чтобы поменять
режим и владельца файла /dev/gpiomem. И в завершение, вам необходимо
установить переменную окружения WIRINGPI_GPIOMEM. Это будет исправлено
в будущих релизах, как только интерфейс /dev/gpiomem будет полностью
введен в эксплуатацию.
СМ. ТАКЖЕ
Домашнюю страничку WiringPi http://wiringpi.com/
АВТОР Gordon Henderson
СООБЩЕНИЯ О БАГАХ
Направляйте в < projects@drogon.net>
COPYRIGHT
Copyright (c) 2012-2018 Gordon Henderson. Это бесплатное ПО; см. исходный
код для получения информации по условиям копирования. Не дается НИКАКИХ
гарантий - даже ни для коммерции, ни для пригодности для определенных
целей.
[Ссылки]
1. GPIO Programming: Using the sysfs Interface site:ics.com. 2. Using GPIO from a Linux Shell site:developer.technexion.com. 3. Stop using /sys/class/gpio – it’s deprecated site:thegoodpenguin.co.uk. 4. Linux kernel GPIO user space interface site:sergioprado.blog. 5. GPIO Driver Interface site:docs.kernel.org. 6. jefftranter / raspberrypi / gpio-board site:github.com. 7. The GPIO utility site:projects.drogon.net. 8. WiringPi / WiringPi site:github.com. 9. The raspi-config Tool site:raspberrypi.com. 10. Raspberry Pi 4 GPIO Pinout.