Raspberry Pi 3: GPIO (#1) — введение — Codius.ru

Помигаем светодиодом!

Поскольку микроконтроллеры STM32 — настоящие 32-битные ARM-ядра, сделать это будет непросто. Здесь всё сильно отличается от привычных методов в PIC или AVR, где было достаточно одной строкой настроить порт на выход, а второй строкой — вывести в него значение — но тем интереснее и гибче.

Содержание

Архитектура STM32

Подробно архитектура микроконтроллеров расписана в статье, однако напомню основные положения, интересные нам сейчас.

Ядро тактируется кварцем, обычно через ФАПЧ. Это — тактовая частота ядра, или SYSCLK. На плате STM32VLDiscovery установлен кварц на 8 МГц, а ФАПЧ в большинстве случаев настраивается как умножитель на 3 — т.е. SYSCLK на плате STM32VLDiscovery обычно равен 24 МГц.

От ядра отходит шина AHB, имеющая свою тактовую частоту — ей можно установить некий прескалер относительно SYSCLK, однако можно оставить его равным единице. Эта шина подобна шине между процессором и северным мостом компьютера — точно так же она служит для связи ARM ядра и процессора периферии, а также на ней висит память и конечно, контроллер DMA.

К шине AHB подключены две периферийных шины — APB1 и APB2. Они равнозначны, просто обслуживают разные контроллеры интерфейсов. Частоты обоих шин APB1 и APB2 можно задавать собственными прескалерами относительно AHB, но их тоже можно оставить равными единице. По умолчанию после запуска микроконтроллера вся периферия на шинах APB1 и APB2 отключена в целях экономии энергии.

Интересующие нас контроллеры портов ввода-вывода висят на шине APB2.

Модель периферии в STM32

Вся периферия микроконтроллеров STM32 настраивается по стандартной процедуре.

  1. Включение тактирования соответствующего контроллера — буквально, подача на него тактового сигнала от шины APB;
  2. Настройки, специфичные для конкретной периферии — что-то записываем в управляющие регистры;
  3. Выбор источников прерываний — каждый периферийный блок может генерировать прерывания по разным поводам. Можно выбрать конкретные «поводы»;
  4. Назначение обработчика прерываний;
  5. Запуск контроллера.

Если прерывания не нужны — шаги 3 и 4 можно пропустить.

Вот, к примеру, инициализация таймера (указаны шаги из последовательности):

Контроллер портов ввода-вывода

Наконец-то подобрались к основной теме статьи.

Так устроена одна нога ввода-вывода микроконтроллера STM32F100:

Выглядит сложнее, чем в PIC или AVR Но на самом деле, ничего страшного.

На входе стоят защитные диоды, не дающие опустить потенциал ножки ниже земли или поднять его выше напряжения питания. Следом установлены управляемые подтягивающие резисторы — по желанию ножку можно подтянуть к земле или к питанию. Однако нужно помнить что эти подтяжки довольно слабые.

Вход

Рассмотрим «вход». Сигнал напрямую идёт в линию «Analog», и если ножка настроена как вход АЦП или компаратора — и если эти блоки есть на этой ножке — сигнал напрямую попадает в них. Для работы с цифровыми сигналами установлен триггер Шмитта (это тот, который с гистерезисом), и его выход попадает в регистр-защёлку входных данных — вот теперь состояние ножки можно считать в программе, читая этот регистр (кстати, он называется IDR — input data register). Для обеспечения работы не-GPIO-периферии, висящей на этой ножке как на входе — сделан отвод под именем «Alternate function input». В качестве этой периферии может выступать UART/USART, SPI, USB да и очень многие другие контроллеры.

Важно понимать, что все эти отводы одновременно включены и работают, просто к ним может быть ничего не подключено.

Выход

Теперь «выход». Цифровые данные, записанные в порт как в выход, лежат в регистре ODR — output data register. Он доступен как на запись, так и на чтение. Читая из ODR, вы не читаете состояние ножки как входа! Вы читаете то, что сами в него записали.

Здесь же — выход от не-GPIO-периферии, под названием «Alternate function output», и попадаем в Output driver. Режим работы выхода с точки зрения схемотехники настраивается именно здесь — можно сделать пуш-пулл выход (линия жёстко притягивается к земле или питанию), выход с открытым коллектором (притягиваем линию к питанию, а землю обеспечивает что-то внешнее, висящее на контакте) или вовсе отключить выход. После драйвера в линию входит аналоговый выход от ЦАП, компаратора или ОУ, и попадаем снова в подтягивающие резисторы и диоды.

Драйвер цифрового выхода имеет также контроль крутизны, или скорости нарастания напряжения. Можно установить максимальную крутизну, и получить возможность дёргать ногой с частотой 50 МГц — но так мы получим и сильные электромагнитные помехи из-за резких звенящих фронтов. Можно установить минимальную крутизну, с максимальной частотой «всего» 2 МГц — но и значительно уменьшить радиопомехи.

На картинке можно заметить ещё один регистр, «Bit set/reset registers». Дело в том, что можно писать напрямую в регистр ODR, а можно использовать регистры BRR/BSRR. На самом деле, это очень крутая фича, о которой я расскажу дальше.

Возможности

Сейчас всё стало похоже на хаос — неясно, как управлять всеми этими возможностями. Однако нет, контроллер порта отслеживает возможные режимы работы выхода, и исключает неверные комбинации — например, он не даст одновременно работать в одну выходную линию и драйверу цифрового выхода, и аналоговому выходу. Зато наличие такого количества настроек даёт обширные возможности.

Например, в более старших сериях можно настроить выход с открытым коллектором, и включить подтяжку к земле. Получается именно то, что нужно для шины 1-Wire. Правда, в серии STM32F1xx такой возможности нет, и нужно ставить внешний резистор подтяжки.

Атомарные операции

В старых микроконтроллерах часто возникала ситуация — если мы хотим изменить какие-то биты в порту (а на самом деле просто включить или выключить ножку) — нам приходилось читать весь регистр порта, устанавливать/сбрасывать в нём нужные биты и записывать обратно. Всё было хорошо до того момента, когда эту операцию посередине не прерывало прерывание. Если обработчик этого прерывания тоже что-то делал с этим же портом — возникала крайне трудноуловимая ошибка. С этим боролись разными средствами, например глобально запрещали прерывания на время обработки порта — но согласитесь, это какой-то костыльный вариант.

В STM32 эта проблема решена аппаратным путём — у вас есть регистры установки и сброса битов (BSRR и BRR), и здесь убиты сразу три зайца:

  1. не нужно читать порт для работы с ним
  2. для воздействия на конкретные пины нужно работать с конкретными битами, а не пытаться изменять весь порт
  3. эти операции атомарны — они проходят за один цикл, и их невозможно прервать посередине.

Подробнее про «конкретные биты» — каждый такт APB2 читаются регистры BSRR и BRR, и сразу же их содержимое применяется на регистр ODR, а сами эти регистры очищаются.Таким образом, если нужно установить 3 и 5 биты в порте — пишем в BSRR слово 10100, и всё успешно устанавливается.

Блокирование конфигурации

При желании, можно заблокировать конфигурацию любого пина от дальнейших изменений — любая попытка записи в регистр конфигурации окончится неуспехом. Это подойдёт для ответственных применений, где случайное переключение к примеру, выхода из режима open drain в push-pull выжжет всё подключенное к этому пину, или сам пин. Для включения блокирования предназначен регистр LCKR, только он снабжён защитой от случайной непреднамеренной записи — чтобы изменения вступили в силу, нужно подать специальную последовательность в бит LCKK.

Управляющие регистры

Всё управление контроллером GPIO сосредоточено в 32-битных регистрах GPIOx_RRR, где x — номер порта, а RRR — название регистра.

Младший конфигурационный регистр GPIOx_CRL

Настраивает первые 8 ножек, с номерами 0..7. У каждой ножки два параметра, MODE и CNF.

MODE отвечает за режим вход/выход и скорость нарастания сигнала.

00 — вход (режим по умолчанию)

01 — выход со скоростью 10 МГц

10 — выход со скоростью 2 МГц

11 — выход со скоростью 50 МГц

CNF отвечает за конфигурацию пина.

  • В режиме входа (MODE=00):

    00 — аналоговый режим

    01 — плавающий вход (дефолт)

    10 — вход с подтяжкой к земле или питанию

    11 — зарезервирован

  • В режиме выхода (MODE=01, 10 или 11):

    00 — выход GPIO Push-pull

    01 — выход GPIO Open drain

    10 — выход альтернативной функции Push-pull

    11 — выход альтернативной функции Open drain

Старший конфигурационный регистр GPIOx_CRH

Настраивает вторые 8 ножек, с номерами 8..15. Всё аналогично GPIOx_CRL.

Регистр входных данных GPIOx_IDR

Каждый бит IDRy содержит в себе состояние соответствующей ножки ввода-вывода. Доступен только для чтения.

Регистр входных данных GPIOx_ODR

Каждый бит ODRy содержит в себе состояние соответствующей ножки ввода-вывода. Можно записывать данные и они появятся на выходе порта, можно читать данные — читая предыдущее записанное значение.

Регистр атомарной установки/сброса битов выходных данных GPIOx_BSRR

Старшие 16 бит — для сброса соответствующих пинов в 0. 0 — ничего не делает, 1 — сбрасывает соответствующий бит. Младшие 16 бит — для установки битов в 1. Точно так же, запись «0» ничего не делает, запись «1» устанавливает соответствующий бит в 1.

Регистр только для записи — он сбрасывается в ноль на каждом такте APB2.

Регистр атомарного сброса битов выходных данных GPIOx_BRR

Младшие 16 бит — для сброса соответствующих пинов. 0 — ничего не делает, 1 — сбрасывает соответствующий бит.

Регистр только для записи — он сбрасывается в ноль на каждом такте APB2.

Регистр блокирования конфигурации GPIOx_LCKR

Каждый бит LCKy блокирует соответствующие биты MODE/CNF регистров CRL/CRH от изменения, таким образом конфигурацию пина невозможно будет изменить вплоть до перезагрузки. Для активации блокирования необходимо записать блокирующую последовательность в бит LCKK: 1, 0, 1, читаем 0, читаем 1. Чтение бита LCKK сообщает текущий статус блокировки: 0 — блокировки нет, 1 — есть.

Работа в разных режимах

Режим входа

  • Отключается драйвер выхода
  • Входной триггер Шмитта включен
  • Резисторы подтяжек включаются по вашим настройкам, одно из трёх состояний — «вход, подтянутый к земле», «вход, подтянутый к питанию», или «плавающий вход»
  • Входной сигнал семплируется каждый такт шины APB2 и записывается в регистр IDR, и чтение этого регистра сообщает состояние ножки.

Режим выхода

  • Драйвер выхода включен, и действует так:

    В режиме «Push-Pull» работает как полумост, включая верхний транзистор в случае «1» и нижний в случае «0»,

    В режиме «Open drain» включает нижний транзистор в случае «0», а в случае «1» оставляет линию неподключенной (т.е. в третьем состоянии).

  • Входной триггер Шмитта включен
  • Отключаются резисторы подтяжек
  • Выходной сигнал семплируется каждый такт шины APB2 и записывается в регистр IDR, и чтение этого регистра сообщает состояние ножки в режиме Open drain.
  • Чтение регистра ODR сообщает последнее записанное состояние в режиме Push-Pull.

Режим альтернативной функции (не-GPIO-периферия)

  • Выходной драйвер — в режиме Push-Pull (к примеру, так работает ножка TX модуля USART) или Open drain, в зависимости от требований контроллера
  • Выходной драйвер управляется сигналами периферии, а не регистром ODR
  • Входной триггер Шмитта включен
  • Резисторы подтяжки отключены
  • Выходной сигнал семплируется каждый такт шины APB2 и записывается в регистр IDR, и чтение этого регистра сообщает состояние ножки в режиме Open drain.
  • Чтение регистра ODR сообщает последнее записанное состояние в режиме Push-Pull.

Аналоговый режим

  • Выходной драйвер выключен
  • Триггер Шмитта полностью отключается, чтобы не влиять на напряжение на входе
  • Резисторы подтяжки отключены
  • В регистре IDR — постоянно 0.

Вся внутренняя аналоговая периферия имеет высокий входной импеданс, поэтому и сама ножка по отношению к остальной схеме будет иметь высокий входной импеданс.

Наконец-то включаем светодиод

Теперь мы знаем всё, чтобы включить этот светодиод! Пойдём с самого начала.

Нужно включить тактирование GPIO порта. Поскольку мы используем светодиод на плате Discovery, выберем зелёный — он подключен к порту PC9. То есть, необходимо включить тактирование GPIOC.

RCC->APB2ENR = RCC_APB2ENR_IOPCEN;

Супер, теперь настраиваем порт на Push-pull выход со скоростью 2 МГц. Сначала выбираем режим, «Output mode, max speed 2 MHz» это 10 в регистре MODE. Достаточно просто установить второй бит.

GPIOC->CRH = GPIO_CRH_MODE9_1;

Теперь говорим про Push-pull выход. Это соответствует 00 в регистре CNF.

GPIOC->CRH &= !(GPIO_CRH_CNF9_0 GPIO_CRH_CNF9_1);

Устанавливаем долгожданный бит в регистре BSRR!

GPIOC->BSRR = GPIO_BSRR_BS9;

Ну вот, честно говоря и всё. Напоследок — листинг мигающего светодиода

Библиотека itacone

И всё-таки ещё не всё. Ради упрощения всяческих настроек я делаю библиотеку itacone. На текущий момент в ней реализована работа с GPIO-пинами и пара функций общего применения — но работа продолжается.

Raspberry Pi Zero

Видеообзор платформы

Установка и настройка

Аналоговый вывод звука (PWM-Audio)

Из коробки звук транслируется через HDMI. Кроме этого можно назначить вывод звука через пины GPIO с помощью ШИМ. Для этого нужно собрать простую схему для обвязки из резисторов на 150 и 270 Ом, электролитических конденсаторов на 10 мкФ и керамических конденсаторов на 10 нФ. Собрать схему проще всего на Bredboard-e, но при необходимости можно распаять схему на протобордах. После сборки и подключения, нужно добавить в конец файла config.txt пару строк настройки вывода звука через аналоговые пины.

dtparam=audio=on dtoverlay=pwm-2chan,pin=18,func=2,pin2=13,func2=4

Теперь перезагрузив плату достаточно нажать правой кнопкой мыши пиктограммку настройки звука на рабочем столе Rasbian OS и выбрать аналоговый источник воспроизведения.

Вывод звука через внешнюю звуковую карту

Подключите внешнюю USB-звуковую карту для вывода звука через разъем 3,5 мм расположенный на карте. Для этого выберите карту в списке устройств воспроизведения.

Вывод изображения через композитный видео выход RCA

На плате есть выход композитного видео сигнала. Для его активации в файле внесите изменения.

  1. Закомментируйте строкуhdmi_force_hotplug=1

    чтобы строка приняла вид

    #hdmi_force_hotplug=1

  2. Раскомментируйте строку#sdtv_mode=2

    чтобы получилось

    sdtv_mode=2

  3. Отсоедините HDMI-кабель.

  4. Подключите RCA-разъем и перезагрузите плату.

Элементы платы

Чип BCM2835

На Raspberry Pi Zero установлен одноядерный процессор Broadcom BCM2835 с ядром ARM1176JZ-F разогнанным до частоты 1 ГГц и модулем оперативной памяти на 512 МБ. Процессор и память расположены по технологии «package-on-package» — снизу процессор, а сверху на нем модуль памяти. BCM2835 включает в себя графический сопроцессор Broadcom VideoCore IV с поддержкой Open GL.

USB On-the-Go

Для подключения устройства со стандартным USB-разъёмом понадобится переходник . Для нескольких устройств, вам понадобится USB-хаб.

STM32 → Порты GPIO

Питание

Питание обеспечивается через разъем . Напряжение должно быть строго 5 Вольт.

Cлот для карт памяти microSD

RUN

Контакты Run подключены к выводу сброса микропроцессора. При замыкании:

  • Перезагрузит систему.

  • Выведет из режима сна.

Композитный видео выход

Используется для подключения телевизоров через разъем .

mini-HDMI

Для вывода цифрового изображения и звука на PI Zero расположен разъем .

Разъём камеры (CSI)

Разъём для подключения камеры Raspberry Pi.

Разъем Pi Zero отличается от стандартного, он имеет 22 контакта с шагом 0,5 мм. Для подключения камеры к Pi Zero используйте другой шлейф.

Пины ввода-вывода (GPIO)

Внимание! В отличие от плат Arduino, напряжение логических уровней Raspberry Pi является 3,3 В. Максимальное напряжение, которое могут выдержать вход/выходы составляет 3,3 В а не 5 В. Подав напряжение, например 5 В, можно вывести одноплатник из строя.

Pi Zero имеет 40-контактный разъем , который соответствует расспиновке Pi 3. Припаяйте провода или колодки к разъему для доступа к контактам .

  • Physical Pin: нумерация, отвечающая за физическое расположение контакта на гребенке.

  • GPIO: нумерация контактов процессора Broadcom. Может пригодиться при работе с пакетом .

  • WiringPi Pin: нумерация контактов для пакета Wiring Pi. Это Arduino-подобная библиотека для работы с GPIO-контактами.

  • ШИМ: плата имеет два канала ШИМ по два потока в каждом.

  • I²C: SDA1, SCL1. Для общения с периферией по синхронному протоколу, через два провода.

  • SPI: К можно подключить два ведомых устройства, а к — три. Выбор осуществляется сигналом на пине CEx.

    • MOSI0 , MISO0 , SCLK0 , CE0 , CE1 ;

    • MOSI1 , MISO1 , SCLK1 , CE0 , CE1 , CE2 .

  • UART:, . Асинхронный протокол последовательной передачи данных по двум проводам и , который позволяет обойтись без тактового сигнала.

Характеристики

  • Процессор: одноядерный процессор Broadcom BCM2835 с ядром ARM1176JZ-F;

  • Тактовая частота: 1 ГГц

  • Оперативная память: 512 МБ;

  • Цифровой аудио/видео выход: HDMI;

  • Композитный аудио выход: 2 pin (TV);

  • USB-порты: 1 USB OTG;

  • Разъем видеокамеры: Camera Serial Interface (22 pin 0.5mm);

  • Карта памяти: MicroSD;

  • Порты ввода-вывода: 40;

  • Габариты: 66×32×5 мм.

Ресурсы

Выпуск 17. Июль 2014

← Асинхронный ввод/вывод с IO::AIO | Содержание | Обзор CPAN за июнь 2014 г. →


Использование портов GPIO в Raspberry Pi. Часть 1

В этой статье рассказано о том, как устроены универсальные порты ввода-вывода (GPIO) и о том, как работать с ними на перле.

Одноплатный компьютер Raspberry Pi примечателен не только своими размером и ценой, но и наличием порта ввода-вывода общего назначения (General Purpose Input-Output, GPIO). Эдакая современная версия параллельного LPT-порта, которая вместе с компьютером занимает меньше места, чем плата PCI с контроллером LPT.

Базовая информация о портах

В базовом комплекте второй версии Raspberry Pi установлен один 26-контактный разьем (он обозначен на плате как P1), в котором доступно 17 портов ввода-вывода (тех самых GPIO).

Остальные восемь контактов подключены к земле или к питанию +3,3 В и +5 В. Выводы, отданные под GPIO, могут быть программно переконфигурированы для работы в качестве последовательных портов, вывода с широтно-импульсной модуляцией и еще как-то (вот это все называется альтернативными режимами). Но по умолчанию после включения питания все контакты работают в режиме «один контакт — один бит». Каждый из них может быть либо входом, либо выходом (по умолчанию включен режим ввода).

Кроме упомянутого разъема P1 на плате есть отверстия для установки восьмиконтактного разъема P5, который дает возможность получить еще четыре порта GPIO. Итого в распоряжении программиста оказывается 21 бинарный порт.

Наличие GPIO позволяет относительно легко связывать компьютер с устройствами из реального мира и управлять ими программно. Разумеется, здесь потребуется знание не только программирования, но и хотя бы основ электроники (детям рекоменую книгу В. Т. Полякова «Посвящение в радиоэлектронику», взрослым — книгу П. Хоровица и У. Хилла «Искусство схемотехники»).

При работе с GPIO важно учитывать пару моментов:

  1. Рабочее напряжение всех выводов — 3,3 В. Случайная подача на вход GPIO большего напряжения (даже 5 В с соседнего штырька разъема) приводит к выходу из строя не только этого вывода, но и вообще всего Raspberry Pi (подтверждаю экспериментально).
  2. Контакты разъема P1 и нумерация портов GPIO не совпадает, поэтому при программировании надо всегда помнить, какая из нумераций используется.

    General-purpose input/output

    Еще более они не совпадают в первой версии Raspberry (надеюсь, сейчас, если не прилагать дополнительных усилий, купить удастся только новую модель).

  3. Дополнительным пунктом надо отметить, что нумерация самих GPIO в Raspberry Pi идет с пропусками.
  4. Raspberry Pi построен на ARM-процессоре BCM2835, поэтому иногда полезнее гуглить BCM2835, а не Raspberry GPIO (то же самое действительно для поиска на CPAN).

Хорошее практическое описание опубликовано на странице elinux.org/RPi_Low-level_peripherals.

Для справки, вот так разведены порты GPIO на контакты разъемов P1 и P5 (контакты традиционно обозначаются в формате PX-NN, где X — номер раъема, а NN — двузначный номер контакта):

  1. GPIO02 — P1-03
  2. GPIO03 — P1-05
  3. GPIO04 — P1-07
  4. GPIO07 — P1-26
  5. GPIO08 — P1-24
  6. GPIO09 — P1-21
  7. GPIO10 — P1-19
  8. GPIO11 — P1-23
  9. GPIO14 — P1-08
  10. GPIO15 — P1-10
  11. GPIO17 — P1-11
  12. GPIO18 — P1-12
  13. GPIO22 — P1-15
  14. GPIO23 — P1-16
  15. GPIO24 — P1-18
  16. GPIO25 — P1-22
  17. GPIO27 — P1-13
  18. GPIO28 — P5-03
  19. GPIO29 — P5-04
  20. GPIO30 — P5-05
  21. GPIO31 — P5-06

Каждый битовый порт способен работать в режиме ввода или вывода.

Кроме того, в режиме ввода может быть дополнительно включен подтягивающий резистор, что поможет максимально упростить способ подключения выключателей — их достаточно подключить между соответствующим выводом GPIO и общим проводом (если включен резистор pull up) или между GPIO и источником питания +3,3 В (если выход сконфигурирован в режиме pull down).

За более детальными продробностями о внутреннем устройстве портов GPIO я отсылаю читателя к шестой главе «General Purpose I/O (GPIO)» мануала по процессору BCM2835.

Регистры для работы с GPIO

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

Процессор BCM2835 имеет 41 32-разрядный регистр, которые полностью определяют режим и состояние портов GPIO. В частности, для установки единичного значения на выводе, запрограммированном на работу как выход, необходимо записать единичный бит в соответствующий разряд одного из двух регистров установки битов GPIO Pin Output Set Registers (GPSETn). Чтобы установить выход в ноль, следует выставить единичный бит в регистрах сброса битов GPIO Pin Output Clear Registers (GPCLRn). Такая на первый взгляд странная схема позволяет независимо устанавливать и сбрасывать любой бит GPIO без необходимости чтения текущего состояния выводов.

Аналогично, когда разряды GPIO работают на чтение, то узнать уровень входного сигнала можно, прочитав значение одного из двух портов GPIO Pin Level Registers (GPLEVn), каждый бит которого отображает текущее состояние входного разряда.

Программирование портов ввода-вывода

Регистры, отвечающие за работу с GPIO, расположены по адресам 0x7E200000—0x7E2000B0, которые отображаются на физическую память с адресами, начинающимися с 0x20200000. В принципе, в этом месте уже можно было бы начать управлять портами, программируя чтение и запись нужных битов в эти регистры (на перле это вполне возможно, если воспользоваться мапингом переменных на области памяти, используя модуль Sys::Mmap).

Но более практично еще немного усложнить систему, чтобы программировать стало легче.

Модуль Device::BCM2835

Для управления портами ввода-вывода на перле удобно воспользоваться модулем Device::BCM2835. Он является Perl-оберткой над C-библиотекой того же автора bcm2835 и один в один повторяет все ее функции (поэтому документацию может оказаться полезнее почитать в оригинале).

Установка библиотеки bcm2835 не вызывает сложностей:

Равно как и модуль со CPAN:

Библиотека (и модуль на перле) определяет огромное число констант, позволяющих выбирать нужные выводы разьъемов P1 и P5 и устанавливать режимы их работы, и довольно большое число функций для доступа к отдельным битам GPIO.

Все дальнейшие действия необходимо выполнять от имени суперпользователя.

Перед началом работы следует вызвать функцию :

(При инициализации происходит вызов функций и создание переменных, которые отображаются на нужные регистры процессора — ровно то, где прикладному программисту проще воспользоваться готовой библиотекой.)

Вызов теоретически может завершиться неудачой, хотя наиболее вероятная причина отказа — запуск скрипта не от рута:

Примечание ко всем примерам кода из документации. Модуль Device::BCM2835 разрешает экспортировать используемые константы, но при этом не хочет экспортировать имена функций (несмотря на то, что многие из них начинаются с префикса ).

Поэтому если подключить модуль с экспортом констант, то бесконечные повторы получится значительно, но все же не полностью, сократить и вместо:

записывать:

Вывод

Чтобы переключить один из разрядов порта GPIO для работы в режиме вывода, надо вызвать функцию установки режима и передать ей номер вывода (константу, соответствующую номеру физического вывода нужного разъема) и режим (другую определенную константу). Например, чтобы перевести выход P1-12 в режим вывода, следует выполнить следующее:

Запись нуля или единицы выполняют, либо вызывая функцию :

Либо используя пару функций и , которым достаточно передать номер вывода:

Обратите внимание, что в обоих примерах физический вывод P1-12 () является логическим выходом GPIO18. А еще обратите внимание на наличие в именах констант. Для первой версии Raspberry Pi следует использовать константы типа , которые за парой исключений совпадают с вариантами с . Но следует иметь в виду, что порт P5 доступен только во второй версии, например: для GPIO29.

Ввод

Чтение данных с портов ввода-вывода также прост, как и запись в них. Прежде всего, необходимо перевести соответствующие разряды GPIO в режим чтения (BCM2835_GPIO_FSEL_INPT):

По желанию и необходимости можно подключить один из подтягивающих резисторов:

В случае, если к выводу порта подключена кнопка, замыкающая вывод на землю, то будет полезен резистор, подключенный к источнику питания +3,3 В (BCM2835_GPIO_PUD_UP), что обеспечит на входе уровень логической единицы, когда кнопка не нажата. При нажатой кнопке на входе окажется логический нуль.

Чтобы прочитать значение со входа, достаточно вызвать функцию , передав ей номер нужного входа:

Функция возвращает либо нуль, либо единицу.

Примеры

Как видно из предыдущих разделов, работать с портами ввода-вывода в бинарном режиме очень просто. Для закрепления материала — два небольших примера, которые будет полезно выполнить, если вы соберетесь программировать порты GPIO.

Код из первого примера раз в секунду включает и выключает светодиод, подключенный (через резистор сопротивлением 300…1000 Ом) к выводу GPIO03 (контакт P1-05).

Обратите внимание на использование функции из того же модуля, которая выполняет задержку на миллисекунд. Доступна и функция для задержки в микросекундах. Обе, однако, не гарантируют точности отсчитанного времени. На практике следует быть осторожным, если требуется получить более или менее точные задержки меньше 20-50 миллисекунд.

Второй пример включает тот же светодиод при нажатии на кнопку, подключенную ко входу GPIO15 (P1-10).

Здесь интересно отметить, что в отличие от предыдущего примера удобнее воспользоваться функцией , а не парой и .

Андрей Шитов


← Асинхронный ввод/вывод с IO::AIO | Содержание | Обзор CPAN за июнь 2014 г. →

Комментарии к статье

В Wiren Board часть GPIO выведена на клеммники, часть выведена на разъёмы расширения, часть используется для служебных целей. GPIO также используются для управления транзисторами для коммутации низковольтной нагрузки.

Соответствие между номерами GPIO в Linux и их местоположением и функцией можно найти в табличке WB SH 3.5: Список GPIO или WB rev. 2.8: Список GPIO.

В Wiren Board rev. 2.8 8 GPIO на специальном разъёме подключены через MCP23S08 и временно не работают со стандартным Linux API.

Описание работы с ними есть на странице MCP23S08.

Все GPIO (как и остальные порты Wiren Board) работают с напряжением 3.3V. Ни в коем случае не подключайте к GPIO напрямую сигналы, напряжением больше 3.3V! В случае необходимости подключения устройств, работающих с более высоким напряжением, необходимо использовать схемы согласования или подключать (для 5V) через резистор в 20 кОм и более

На некоторых GPIO (в частности на 3х GPIO, выведенных на клеммники в Wiren Board rev. 2.8) можно программно установить 47к подтяжку к +3.3В. См. Pin_pull-up.

Интерфейс sysfs в Linux

GPIO в Linux поддерживаются через sysfs-интерфейс.

Для работы через sysfs c определённым GPIO его надо экспортировать:

Здесь и далее N — номер gpio

echo N > /sys/class/gpio/export

Экспортированные gpio появляются в каталоге /sys/class/gpio :

root@wirenboard:~# ls -1 /sys/class/gpio/ export gpio32 gpiochip0 gpiochip120 gpiochip32 gpiochip64 unexport

В директории /sys/class/gpioN теперь находятся файлы для работы с GPIO (где N — номер GPIO, как и было сказано ранее):

root@wirenboard:~# ls -1 /sys/class/gpio/gpioN/ active_low device direction edge power subsystem uevent value

Установка направления GPIO (ввод/вывод) производится с помощью записи в файл direction

echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод

Чтение и установка значения GPIO производится с помощью файла value.

Чтение:

echo in > /sys/class/gpio/gpioN/direction # установим GPIO номер N на ввод cat /sys/class/gpio/gpioN/value # вернёт 1 или 0

Запись:

echo out > /sys/class/gpio/gpioN/direction # установим GPIO номер N на вывод echo 0 > /sys/class/gpio/gpioN/value # установим логический 0 (низкое напряжение) на GPIO номер N echo 1 > /sys/class/gpio/gpioN/value # установим логический 1 (высокое напряжение) на GPIO номер N

Интерфейс sysfs и прерывания

Через интерфейс sysfs можно запросить прерывания по изменению состояния процессора.

Первое знакомство с GPIO в Raspberry PI

Установка прерывания производится путём записи значения в файл «edge». Значения могут быть:

  • «none» — отключить прерывание
  • «rising» — включить прерывание по нисходящему фронту
  • «falling» — включить прерывание по восодящему фронту
  • «both» — включить прерывание по обеим фронтам.

Пример:

root@wirenboard:~# echo 3 > /sys/class/gpio/export # экспортируем GPIO номер 3 (TB10 на WB3.3) root@wirenboard:~# cat /sys/class/gpio/gpio3/edge # проверяем состояние прерывания none root@wirenboard:~# echo falling > /sys/class/gpio/gpio3/edge # устанавливаем прерывание по нисходящему фронту root@wirenboard:~# cat /proc/interrupts | grep gpiolib # прерывание появилось в списке. 26 — внутренний номер прерывания, 0 — количество событий 26: 0 gpio-mxs 3 gpiolib root@wirenboard:~# cat /proc/interrupts | grep gpiolib # после нескольких собтий, 76 — количество событий 26: 76 gpio-mxs 3 gpiolib

Прерывания можно ловить из userspace с помощью системного вызова epoll() и select() на файл value. Пример работы см. [1]

См. также elinux.org

Прямое обращение через память процессора

Этот метод настоятельно НЕ РЕКОМЕНДУЕТСЯ для использования без достаточных оснований. Для работы из С/C++ стоит использовать работу через файлы в sysfs, как описано в предыдущем разделе.

Управлять GPIO можно с помощью прямого доступа к регистрам процессора, в обход Linux через интерфейс /dev/mem. При этом, по сравнению с работой через sysfs минимизуются наладные расходы. Этот метод можно использовать, если вам необходим очень быстрый доступ к GPIO, например bitbang протоколов или ШИМ. Стоит иметь в виду, что планировщик процессов всё ещё может вносить в работу программы значительные задержки. Рекомендуется выносить критичные ко времени задачи в ядро.

См. [2] , [3]

GPIO и Device Tree

Указывать GPIO в Device Tree необходимо для настройки GPIO для работы в режиме программного SPI, I2C, для использования GPIO в качестве источника прерываний и т.д. Так например на пин 10@UEXT1 (CS) и пины 5@UEXT2 (SCL), 6@UEXT2 (SDA), 10@UEXT2 (CS) выведены линии GPIO процессора. Их можно сконфигурировать для использования например в качестве chip-select для SPI или в качестве I2C.

GPIO процессора и периферийных устройств разбиты на банки (gpiochip). GPIO процессора разбиты на 3 банка по 32 GPIO: gpio0, gpio1, gpio2. Адресация GPIO в Device Tree происходит по номеру банка и номеру GPIO *внутри* банка.

Пример 1

Определим сигнал 6@UEXT2 (SDA) в качестве источника прерываний для драйвера mrf24j40. Согласно таблице Список GPIO, сигнал соответствует GPIO 53 процессора. 53 принадлежит второму банку gpio (от 32 до 63). Номер GPIO внутри банка 53-32=21 :

6lowpan@0 { compatible = «microchip,mrf24j40»; spi-max-frequency = <100000>; reg = <6>; interrupt-parent = <&gpio1>; interrupts = <21 0>; };

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *