GPIO для чайников (Часть 2)
-
Hi, мое имя Александр Антонович. Я отношу себя к профи. Поэтому, позвольте я дам несколько советов и чуть-чуть покритикую.
-
Пожалуйста, замените варажения типа "питание для кнопки". Во первых, это режет слух, во вторых, это в корне не правильно, а в третьих Вы дуроно воспитаете своих пионеров.
-
К вопросу -- почему разработчики рекомендуют делать так:
bcm2835_gpio_fsel(PIN_IN, BCM2835_GPIO_FSEL_OUTP);
bcm2835_gpio_fsel(PIN_IN, BCM2835_GPIO_FSEL_INPT);Зайду из далека. Несложно ответить на вопрос -- какое напряжение будет на GPIO4, когда кнопка нажата? Ответ -- такое напряжение, какое в этот момент будет присутствовать на GPIO1. На GPIO1 присутствует (всегда) логическая единица (далее -- "1"), значит, на прои нажатии на кнопку на выводе порта GPIO4 будет присутствовать "1".
Ответь на вопрос -- "какое напряжение будет присутствовать на GPIO4, когда кнопка не нажата?" -- очень сложно. Дело в том, что высокоомный вход микросхемы практически остается брошенным на произвол судьбы и помехам. В граммотно спректированных схемах вывод ВСЕГДА "поддтягивают" к земле или к питанию с помощью высокоомных резисторов. В нашем случае, мы должны "подтягивать" вывод к земле.
Сопротивление резисторов обычно берут в пределах от 10 до 100 кОм. Но в редких случаях, можно увидеть и 1 кОм и 1 МОм. Подтягивающие резисторы могут внутренними (если таковые имеются в микроконтроллере и удовлетворяют требованиям подтяжки), либо внешние.
Когда кнопка не нажата, высокоомный резистор подтягивает вход. В нашем случае -- тянет его к земле. Иначе говоря, на выводе формируется лог."0". Причем следует заметить, формируется весьма слабыми токами -- ведь резистор-то -- относительно высокоомный. Поэтому, как только произойдет нажатие на кнопк, на выводе тут же сформируется лог."1", так как выход порта микросхемы -- это более сильный источник сигнала, чем подтягивающий резистор. Когда кнопку отпустят, на входе снова сформируется лог."0". Поддягивающий резистор делает свое дело.
Наша задача, выбрать сопротивление подтягивающего резистора такое, чтобы он, с одной стороны, не сильно нагружал выход порта, когда нажимается кнопка, а с другой -- не слишком большим, чтобы он мого шунтировать наведенные на провода помехи.
Далее. Что происходит в нашей схем, ведь в ней нет подтягивающих резисторов? Для ответа на этот вопрос нужно вспмнить, что на входе порта стоят полевые транзисторы. Полевые транзисторы характеризуются тем, что они практически не имеют входных токов, но зато имеют ощутимую входную емкость.
Таким образом, выполняя последовательность команд:
bcm2835_gpio_fsel(PIN_IN, BCM2835_GPIO_FSEL_OUTP); bcm2835_gpio_fsel(PIN_IN, BCM2835_GPIO_FSEL_INPT);
мы сначала переводим вывод порта в режим выхода, тем самым формируем на выводе микросхемы напряжение, соответствующее состоянию порта, а это значит -- ЗАРЯЖАЕМ или РАЗРЯЖАЕМ входные емкости (емкости переходов у входных полевых транзисторов), а потом переводим вывод порта в режим ввода. После этих опрераций на входной емкости порта КАКОЕ-ТО ВРЕМЯ будет сохраняться полученный заряд. Потом, через несколько секунд, а может быть десятков минут, токи утечек разрядят входные емкости и схема (а, следовательно, и программа) начнет вести себя непредсказуемо.
В нашем случае всё это вроде бы работает. Во первых, при переводе вывода порта на выхд, мы предполагаем, что на выходе порта у нас лог."0". На самом деле это так: после сброса микроконтроллера состояние портов обычно равно нулю. Но если перед запуском нашей проги, кто-то выведет в порт GPIO1 лог."1", то мы вместо того чтобы сообщить входным емкостям напряжение лог."0", зарядим их. Как поведет себя в этом случае прога, думаю, вы легко сообразите самостоятельно.
К стати, проведите эксперимент -- предварительно выведите в порт единичку, а потом выполните эти две команды, и посмотрите, сработает-ли "рекомендации специалистов".
Я с большим удовольствием хочу отметить, что не смотря на незначительные огрехи (а укого их нет!) автор цикла статей старается сделать мир лучше.
Если мы не будем делиться своими знаниями и опытом, а будем делать на этом деле деньги, мы не станем богаче. Возможно, у нас лично будет больше денег, чем у других окружающих нас людей, но как нация в целом, мы будем беднее и духовно и материально.
Автор статей, видимо, познал эту истину, за что ему огромной респект!
-
-
2.5 Совсем забыл! Я хотел бы порекомендовать сменить наименования портов. Например, следующие имена сделают программу более прозрачной для восприятия:
#define LED (RPI_GPIO_P1_03) #define UPPER (RPI_GPIO_P1_05) #define BUTTON (RPI_GPIO_P1_07)
-
У меня такой вопрос, в RPi версии rev.V2
не работает вот это: bcm2835_gpio_pud(PIN_IN, 1);
на этой строчке компилятор останавливается и рукается, что слишком много параметров.Немного залез в мануалы, глянул там такие команды как:
bcm2835_gpio_pudclc
bcm2835_gpio_set_pud
Может как-то через гих реализовать? -
Небольшая поправка:
"Компилируем и запускаем:
gcc -o button button.c -lrt -lbcm283"
Нужно:
gcc -o button button.c -lrt -lbcm2835 -
Просто удалите. Автор писал.
-
Для RPI rev.V2 вместо строчки
bcm2835_gpio_pud(PIN_IN, 1);
нужно написать
bcm2835_gpio_set_pud(PIN_IN, BCM2835_GPIO_PUD_DOWN); -
Еще до того как увидел данную статью поигрался с бесконечным циклом и разным временем работы светодиода. Как будто мысли ваши читал.
Почему-то программа с кнопкой у меня не компилируется. Пробовал так как тут и с исправленными пинами и для второй и для первой ревизии. И библиотеку уже установил старую - 1.17, а до этого была самая новая, думал в этом дело... и компилировать пробовал по разному... никак не хочет... не пойму в чем дело...
Вот такие ошибки:
button.c: In function ‘main’: button.c:23:23: error: ‘RPI_V2_GPIO_P1_06’ undeclared (first use in this function) button.c:23:23: note: each undeclared identifier is reported only once for each function it appears in button.c:24:5: error: too many arguments to function ‘bcm2835_gpio_pud’ /usr/local/include/bcm2835.h:723:17: note: declared here button.c:38:5: error: too many arguments to function ‘bcm2835_gpio_pud’ /usr/local/include/bcm2835.h:723:17: note: declared here
-
[quote]
Вот такие ошибки:
button.c: In function ‘main’:
[/quote]
В начале кода:
#include <bcm2835.h>
#include <stdio.h>
Например для ошибки button.c:23:23 можно так для :#define PIN RPI_V2_GPIO_P1_06
для button.c:24:5:
ругается что много аргументов которые заданы в скобках () после -- bcm2835_gpio_pud
надо было их здесь олицетворить...
но наверное должно быть что-то типа этого:bcm2835_gpio_set_pud(PIN, BCM2835_GPIO_PUD_UP)
В скобках 2 аргумента, это PIN задефайнен см. вверху и макрос BCM2835_GPIO_PUD_UP для Pull-up/down resistor....
-
Использование bcm2835_gpio_set_pud() выдавало сообщение: ошибка сегментации. В итоге в схему добавил подтягивающий резистор на 10к, как и говорил Александр Антонович. Все заработало. Работаю на RaspberryPi 3.
-
Всем привет.
есть raspberry pi3 нужно собрать монтажную плату и подключить пару кнопок.
за вознаграждение.
пишите если у кого есть желание. -
Подскажите как будет выглядеть подключение если кнопка будет иметь внешнее питание 3,3в, а не внутреннее. Например батарейка. Как в таком случае считать сигнал нажатия?
-
Кнопка в принципе не имет питания. Она механически замыкает/размыкает цепь
-
Ок, я не много не так выразился. Есть два провода(с внешнего устройства) плюс и минус. Как мне с них снять сигнал? То-есть там либо есть ток, либо нету. По сути таже кнопка, только питание идет не с пина gpio.