Пины ардуино: как назначить на вход-выход, чтение и запись

Содержание

Пины Ардуино: как назначить на вход-выход, чтение и запись

В уроке узнаем структуру, функциональные возможности, электрические характеристики портов ввода-вывода общего назначения. Изучим регистры микроконтроллера для управления портами.

Предыдущий урок Список уроков Следующий урок

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

Не пропускайте этот урок, прочитайте внимательно. По опыту уроков Ардуино знаю, что много вопросов возникает из-за незнания всего того, что я описываю в этой статье.

И про аппаратное устройство портов и их электрические характеристики я пишу не для того, чтобы набрать объем урока. Это очень важный вопрос. Знание его необходимо для подключения к микроконтроллеру различных электронных компонентов. Микроконтроллер сам по себе никогда не работает. К нему всегда что-то подключается.

Через порты ввода-вывода микроконтроллер управляет и связывается со всем, что к нему подключено. Есть еще коммуникационные интерфейсы, но о них в последующих уроках. Хотя интерфейсы также используют порты, только в режиме альтернативных функций.

В системе STM32 применяется общепринятое название портов ввода-вывода общего назначения, а именно GPIO (General purpose input-output).

Под “общим назначением” имеется в виду, что состояние выводов устанавливается или считывается программно, т.е. вывод не является входным или выходным сигналом какого-либо аппаратного узла микроконтроллера.

В системе STM32:

  • Порты обозначаются GPIOA, GPIOB, GPIOC и т.д. На схеме микроконтроллера соответствующие портам выводы обозначаются PA0-PA15, PB0-PB15, PC0-PC15…
  • Порты 16ти разрядные, т.е. у каждого порта 16 выводов.
  • Режим и состояние каждого вывода могут быть установлены отдельно, независимо от других выводов.
  • Каждый вывод может использоваться в режиме:
  • Input floating – вход без подтягивающего резистора, брошенный в воздухе вход.
  • Input pull-up – вход с подтягивающим резистором, подключенным к питанию микроконтроллера.
  • Input pull-down — вход с подтягивающим резистором, подключенным к общему проводу (земле).
  • Analog – аналоговый вход ( вход АЦП, компараторов и т.п.).
  • Output open-drain – выход с открытым стоком. Функционально аналогичен выходу с открытым коллектором. При низком логическом уровне замыкает вывод на землю, при высоком – бросает в воздухе.
  • Output push-pull – обычный активный выход. При низком логическом уровне напряжение на выводе равно 0, при высоком – напряжение близко к напряжению питания микроконтроллера, обычно + 3 В.
  • Alternate function push-pull – альтернативная функция вывода в обычном (активном) режиме.
  • Alternate function open-drain – альтернативная функция вывода в режиме открытый сток.
  • GPIOA – 16 выводов: PA0-PA15;
  • GPIOB – 16 выводов: PB0-PB15;
  • GPIOC – 3 вывода: PC13-PC15;
  • GPIOD – 2 выводов: PD0, PD1.

Пины Ардуино: как назначить на вход-выход, чтение и запись

Порты STM32 с аппаратной точки зрения.

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

Пины Ардуино: как назначить на вход-выход, чтение и запись

  • В документации приводится базовая схема вывода порта.
  • Нас интересует правая, выходная часть.
  • Режим входов.

При использовании вывода в качестве входа, к нему могут быть подключены подтягивающие резисторы сопротивлением порядка 40 кОм. Либо к питанию Vdd, либо к земле Vss.

Основные для нас входные параметры портов.

Параметр Значение
Напряжение низкого уровня Не более 0,35 VDD
При питании 3,3 В не более 1,16 В
Напряжение высокого уровня Не менее 0,65 VDD
При питании 3,3 В не менее 2,15 В
Ток утечки ± 1 мкА
Сопротивление подтягивающих резисторов 30 – 50 кОм,
типовое значение 40 кОм
Емкость 5 пкФ

Обратите внимание, какая небольшая разница между входными напряжениями низкого и высокого уровня. За это я и не люблю 3-вольтовые контроллеры.

Согласно схеме к выводу подключены 2 защитных диода. Один на землю Vss, другой на шину питания Vdd. Первый замыкает через себя входное напряжение отрицательной полярности, другой ограничивает его на уровне Vdd, у нас на плате это 3,3 В.

Сигналы с напряжением, превышающим эти пределы должны подключаться через ограничительные резисторы. Входной ток не должен превышать ± 5 мА. Это предельный ток защитных диодов.

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

Но большая часть входов микроконтроллера допускает подачу напряжения 5 В. Это, так называемые, толерантные к 5 В входы. В схеме для таких выводов верхний защитный диод подключен не к питанию Vdd, а к ограничителю напряжения Vdd_ft.

Толерантные выводы обозначаются FT (five volt tolerant). Напряжение ограничевается до уровня на 4 В выше Vdd. Сделано это для подключения сигналов с 5 В уровнями.

На схеме распределения выводов STM32F103C8T6 толерантные к 5 В выводы отмечены закрашенными точками.

Предельно-допустимые входные параметры портов.

Параметр Значение
Напряжение на толерантных входах Не менее — 0,3 В, не более Vdd + 4 В
При питании 3,3 В — 0,3 … 7,3 В
Напряжение на остальных входах Не менее — 0,3 В, не более 4 В
Максимальный втекающий ток через защитные диоды ± 5 мА

Режим выходов.

В режиме выхода порта работают 2 комплементарных транзистора.

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

Выходные параметры портов.

Параметр Значение
Напряжение низкого уровня при втекающем токе 8 мА Не более 0,4 В
Напряжение низкого уровня при втекающем токе 20 мА Не более 1,3 В
Напряжение высокого уровня при вытекающем токе 8 мА Не менее Vdd – 0,4 В
Напряжение высокого уровня при вытекающем токе 20 мА Не менее Vdd – 1,3 В

Предельно-допустимые выходные параметры портов.

Параметр Значение
Максимальный вытекающий ток вывода 25 мА
Максимальный втекающий ток вывода — 25 мА
Общий вытекающий или втекающий ток портов Не более 150 мА.

Получается, что к каждому выводу порта можно подключать нагрузку до 25 мА. Но при этом уровень логического сигнала выйдет за допустимые значения логических уровней. Чтобы этого не произошло нельзя нагружать вывод током свыше 8 мА.

Программное управление портами STM32.

Для каждого порта (16 выводов) есть два 32х разрядных регистра конфигурации. Они образуют 64 битный регистр конфигурации порта.

  1. Младший регистр конфигурации портов GPIOx_CRL (Port configuration register low)
  2. Пины Ардуино: как назначить на вход-выход, чтение и запись
  3. Старший регистр конфигурации портов GPIOx_CRH (Port configuration register high)
  4. Пины Ардуино: как назначить на вход-выход, чтение и запись
  5. На каждый вывод отводится 4 бита, которые делятся на 2 битные поля режима и конфигурации.

Поле режима определяет направление работы вывода – вход или выход. В случае выхода оно задает максимальную частоту передачи выходного сигнала. Очевидно, это влияет на энергопотребление микроконтроллера.

Поле режима (биты Mode).

Биты режима MODE [1 : 0] Режим
0 0 Вход
0 1 Выход, синхронизация 10 мГц
1 0 Выход, синхронизация 2 мГц
1 1 Выход, синхронизация 50 мГц

Поле режима дополняют биты конфигурации.

Конфигурация Биты конфигурации
CNF [1 : 0]
Биты режима
MODE [1 : 0]
Бит в регистре вывода данных
PxODR
Выход общего назначения Активный выход 0 0 0 1
1 0
1 1
0 или 1
Открытый сток 0 1 0 или 1
Выход альтернативной функции Активный выход 1 0 —
Открытый сток 1 1 —
Вход Аналоговый вход 0 0 0 0 —
Свободный вход 0 1 —
Вход, подтяжка к земле 1 0
Вход, подтяжка к питанию 1

Состояние регистров конфигурации можно защитить от непредусмотренных изменений. Для этого существует регистр блокировки конфигурации.

Регистр блокировки конфигурации порта GPIOx_LCKR (Port configuration lock register)

Пины Ардуино: как назначить на вход-выход, чтение и запись

Каждому выводу порта соответствует бит блокировки LCK0 – LCK15. При установке бита в 1 запрещается изменение соответствующих битов режима и конфигурации.

После задания всех нужных битов регистра блокировки необходимо активизировать защиту. Для этого надо в 16й бит регистра блокировки (LCKK) последовательно записать 1, 0, 1.

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

Проверить установлена ли защита конфигурации можно чтением этого же 16-го бита (LCKK). При активированной защите два подряд чтения бита должны дать результат 0, 1.

  • Доступ к портам происходит через регистры ввода и вывода данных.
  • Регистр ввода данных порта GPIOx_IDR (Port input data register)
  • Пины Ардуино: как назначить на вход-выход, чтение и запись
  • Регистр вывода данных порта GPIOx_ODR (Port output data register)
  • Пины Ардуино: как назначить на вход-выход, чтение и запись

Первый доступен только для чтения. Биты IDR0 – IDR15 содержат состояние соответствующих выводов порта.

Пины Ардуино: как назначить на вход-выход, чтение и запись

  1. Запись данных во второй регистр устанавливает состояние выводов порта (ODR0 – ODR15).
  2. Если задан режим вывода – вход, то состояние соответствующего бита ODR0 – ODR15 определяет, куда подключен подтягивающий резистор, к шине питания или земле.
  3. Для управления состоянием отдельных выводов можно воспользоваться регистрами битовой обработки.
  4. Регистр установки/сброса битов GPIOx_BSRR (Port bit set/reset register)

Регистр установки/сброса битов разделен на 2 равные части(0-15 и 16-31). Первая предназначена для установки выводов в состояние 1, вторая – в состояние 0.

  • Запись данного с 1 в битах BS0 – BS15 устанавливает соответствующие выводы в состояние высокого уровня.
  • Запись данного с 1 в битах BR0 – BR15 переводит соответствующие выводы в состояние низкого уровня.

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

Пины Ардуино: как назначить на вход-выход, чтение и запись

  • Регистр сброса битов GPIOx_BRR (Port bit reset register)
  • Это 16ти разрядный регистр, который работает точно так, как младшая половина предыдущего регистра установки/сброса.
  • Запись слова с 1 в битах BR0 – BR15 переводит соответствующие выводы в состояние низкого уровня.
  • Конфигурация портов с помощью STM32CubeMX.

Здесь все просто и понятно. Мы это уже делали.

Давайте настроим вывод PB12 на вход с подтягивающим резистором к шине питания, а PB13 на активный выход.

Закладка System Core -> GPIO.

Правой кнопкой мыши нажимаем на вывод PB12. Выбираем GPIO_Input.

В поле Configuration выбираем строку PB12 и задаем Pull-up и имя вывода. Я написал Button.

Выбираем строку PB13 и задаем:

  • высокий уровень при включении (High);
  • активный выход (Output Push Pull);
  • имя Led.
  • Я не буду описывать режимы, они очевидны.
  • Давайте настроим систему тактирования и вывод PC13, как в уроке 3, и создадим проект Lesson6_1.
  • Проект будем использовать в следующем уроке.

В нем научимся работать с портами через регистры библиотеки CMSIS.

Предыдущий урок Список уроков Следующий урок

AVR. Учебный курс. Устройство и работа портов ввода-вывода

С внешним миром микроконтроллер общается через порты ввода вывода. Схема порта ввода вывода указана в даташите:

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

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

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

Конденсатор, нарисованный пунктиром, это паразитная емкость вывода. Хоть она и крошечная, но присутствует. Обычно ее не учитывают, но она есть. Не забивай голову, просто знай это, как нибудь я тебе даже покажу как её можно применить 😉

Дальше идут ключи управления. Это я их нарисовал рубильниками, на самом деле там стоят полевые транзисторы, но особой сути это не меняет. А рубильники наглядней.
Каждый рубильник подчинен логическому условию которое я подписал на рисунке. Когда условие выполняется — ключ замыкается. PIN, PORT, DDR это регистры конфигурации порта.

Есть в каждом контроллере AVRPIC есть тоже подобные регистры, только звать их по другому).

Например, смотри в даташите на цоколевку микросхемы:

Видишь у каждой почти ножки есть обозначение Pxx. Например, PB4 где буква «B» означает имя порта, а цифра — номер бита в порту. За порт «B» отвечают три восьмиразрядных регистра PORTB, PINB, DDRB, а каждый бит в этом регистре отвечает за соответствующую ножку порта. За порт «А» таким же образом отвечают PORTA, DDRA, PINA.

PINх
Это регистр чтения. Из него можно только читать. В регистре PINx содержится информация о реальном текущем логическом уровне на выводах порта. Вне зависимости от настроек порта.

Так что если хотим узнать что у нас на входе — читаем соответствующий бит регистра PINx Причем существует две границы: граница гарантированного нуля и граница гарантированной единицы — пороги за которыми мы можем однозначно четко определить текущий логический уровень. Для пятивольтового питания это 1.4 и 1.8 вольт соответственно.

То есть при снижении напряжения от максимума до минимума бит в регистре PIN переключится с 1 на 0 только при снижении напруги ниже 1.4 вольт, а вот когда напруга нарастает от минимума до максимума переключение бита с 0 на 1 будет только по достижении напряжения в 1.8 вольта.

То есть возникает гистерезис переключения с 0 на 1, что исключает хаотичные переключения под действием помех и наводок, а также исключает ошибочное считывание логического уровня между порогами переключения.

При снижении напряжения питания разумеется эти пороги также снижаются, график зависимости порогов переключения от питающего напряжения можно найти в даташите.

DDRx
Это регистр направления порта. Порт в конкретный момент времени может быть либо входом либо выходом (но для состояния битов PIN это значения не имеет. Читать из PIN реальное значение можно всегда).

  • DDRxy=0 — вывод работает как ВХОД.
  • DDRxy=1 вывод работает на ВЫХОД.

PORTx
Режим управления состоянием вывода. Когда мы настраиваем вывод на вход, то от PORT зависит тип входа (Hi-Z или PullUp, об этом чуть ниже).

Когда ножка настроена на выход, то значение соответствующего бита в регистре PORTx определяет состояние вывода. Если PORTxy=1 то на выводе лог1, если PORTxy=0 то на выводе лог0.

Когда ножка настроена на вход, то если PORTxy=0, то вывод в режиме Hi-Z. Если PORTxy=1 то вывод в режиме PullUp с подтяжкой резистором в 100к до питания.

Есть еще бит PUD (PullUp Disable) в регистре SFIOR он запрещает включение подтяжки сразу для всех портов. По дефолту он равен 0.

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

Мало ли, вдруг будешь чужую прошивку ковырять и увидишь что у тебя подтяжка не работает, а вроде как должна. Тогда слазаешь и проверишь этот бит, вдруг автор прошивки заранее где то его сбросил.

Общая картина работы порта показана на рисунке:

Теперь кратко о режимах:

  • Режим выхода
    Ну тут, думаю, все понятно — если нам надо выдать в порт 1 мы включаем порт на выход (DDRxy=1) и записываем в PORTxy единицу — при этом замыкается верхний ключ и на выводе появляется напряжение близкое к питанию. А если надо ноль, то в PORTxy записываем 0 и открывается уже нижний вентиль, что дает на выводе около нуля вольт.
  • Вход Hi-Z — режим высокоимпендансного входа.
    Этот режим включен по умолчанию. Все вентили разомкнуты, а сопротивление порта очень велико. В принципе, по сравнению с другими режимами, можно его считать бесконечностью. То есть электрически вывод как бы вообще никуда не подключен и ни на что не влияет. Но! При этом он постоянно считывает свое состояние в регистр PIN и мы всегда можем узнать что у нас на входе — единица или ноль. Этот режим хорош для прослушивания какой либо шины данных, т.к. он не оказывает на шину никакого влияния. А что будет если вход висит в воздухе? А в этом случае напряжение будет на нем скакать в зависимости от внешних наводок, электромагнитных помех и вообще от фазы луны и погоды на Марсе (идеальный способ нарубить случайных чисел!). Очень часто на порту в этом случае нестабильный синус 50Гц — наводка от сети 220В, а в регистре PIN будет меняться 0 и 1 с частотой около 50Гц
  • Вход PullUp — вход с подтяжкой.
    При DDRxy=0 и PORTxy=1 замыкается ключ подтяжки и к линии подключается резистор в 100кОм, что моментально приводит неподключенную никуда линию в состояние лог1. Цель подтяжки очевидна — недопустить хаотичного изменения состояния на входе под действием наводок. Но если на входе появится логический ноль (замыкание линии на землю кнопкой или другим микроконтроллером/микросхемой), то слабый 100кОмный резистор не сможет удерживать напряжение на линии на уровне лог1 и на входе будет нуль.

Также почти каждая ножка имеет дополнительные функции. На распиновке они подписаны в скобках. Это могут быть выводы приемопередатчиков, разные последовательные интерфейсы, аналоговые входы, выходы ШИМ генераторов. Да чего там только нет.

По умолчанию все эти функции отключены, а вывод управляется исключительно парой DDR и PORT, но если включить какую-либо дополнительную функцию, то тут уже управление может полностью или частично перейти под контроль периферийного устройства и тогда хоть запишись в DDR/PORT — ничего не изменится. До тех пор пока не выключишь периферию занимающую эти выводы.
Например, приемник USART. Стоит только выставить бит разрешения приема RXEN как вывод RxD, как бы он ни был настроен до этого, переходит в режим входа.

  • Совет:
    С целью снижения энергопотребления и повышения надежности рекомендуется все неиспользованные пины включить в режим PullUp тогда их не будет дергать туда сюда помехой, а если на порт свалится грубая сила (например, монтажник отвертку уронит и коротнет на землю) то линия не выгорит.
  • Как запомнить режимы, чтобы не лазать каждый раз в справочник:
    Чем зазубривать или писать напоминалки, лучше понять логику разработчиков, проектировавших эти настройки, и тогда все запомнится само.
  • Итак:
  • Самый безопасный для МК и схемы, ни на что не влияющий режим это Hi-Z.
  • Очевидно что этот режим и должен быть по дефолту.
  • Значения большинства портов I/O при включении питания/сбросе = 0х00, PORT и DDR не исключение.
  • Соответственно когда DDR=0 и PORT=0 это High-Z — самый безопасный режим, оптимальный при старте.
  • Hi-Z это вход, значит при DDR=0 нога настроена на вход. Запомнили.
  • Однако, если DDR=0 — вход, то что будет если PORT переключить в 1?
  • Очевидно, что будет другой режим входа. Какой? Pullup, другого не дано! Логично? Логично. Запомнили.
  • Раз дефолтный режим был входом и одновременно в регистрах нуль, то для того, чтобы настроить вывод на выход надо в DDR записать 1.
  • Ну, а состояние выхода уже соответствует регистру PORT — высокий это 1, низкий это 0.
  • Читаем же из регистра PIN.

Есть еще один способ, мнемонический:
1 похожа на стрелку. Стрелка выходящая из МК — выход. Значит DDR=1 это выход! 0 похож на гнездо, дырку — вход! Резистор подтяжки дает в висящем порту единичку, значит PORT в режиме Pullup должен быть в единичке!

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

Уровень напряжения на выводе словно планка, которая может двигаться вертикально вверх или вниз. В режиме Hi-Z мы можем на эту планку только смотреть, а двигать или как то на нее воздействовать мы не можем. Поэтому любая помеха может ее дрыгать как угодно, но зато если мы ее куда прицепим, то ее уровень будет зависеть только от другой цепи и ей мы не помешаем.

В режиме PullUp эту планку мы пружиной подтянули кверху. Слабые помехи не смогут больше ее дрыгать как угодно. С другой стороны шине она может помешать, но не факт что заблокирует ее работу. От шины зависит и ее силы. А еще мы можем отслеживать тупую внешнюю силу, вроде кнопки, которая может взять и придавить ее к земле. Тогда мы узнаем что кнопка нажата.

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

Arduino — функции — цифровой вход/выход

Arduino IDE имеет набор стандартных функций для управления входом/выходом. Вы можете легко обрабатывать как цифровые сигналы, так и аналоговые. Ниже приведен список функций с кратким описанием и примерами использования.

Цифровой вход/выход

Цифровые выводы Arduino могут быть использованы как входы или как выходы. Поэтому необходимы функции, которые позволят установить (настроить) выводы на запись или чтение данных.

Функция pinMode()

Функция pinMode() позволяет определить работу отдельных контактов. Ее синтаксис выглядит следующим образом:

  • pin — код — это указать номера контакта системы Arduino
  • mode — это одна из предопределенных констант: INPUT, OUTPUT или INPUT_PULLUP
  • Предназначение данных констант описано в другой статье. Примеры режим работы выводов:

pinMode(13,OUTPUT);
pinMode(8,INPUT);
#define ledPin 10
pinMode(ledPin,OUTPUT);
const byte button=4;
pinMode(button,INPUT_PULLUP);
int button2=5;
pinMode(button2,INPUT_PULLUP);

Как вы можете видеть, конфигурирование контактов не такой уж сложный процесс. Стоит обратить внимание на тот факт, что тот же эффект можно получить несколькими способами.

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

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

Определение — название для конкретного контакта (имя), которое определяет его использование. Безусловно, легче запомнить, что ledPin это вывод, к которому подключен светодиод, чем просто светодиод подключен к контакту 10.

Стоит помнить, что при объявлении соответствующего имени, мы так же будем ссылаться на него и в программе, а не только при определении режима работы вывода. Определение имен с помощью директивы define или const совпадает с практической точки зрения. Компилятор заменит данное имя на присвоенное ему значение.

Разработчики Arduino IDE рекомендуют использовать const. Мы в отношении контактов рекомендуем использовать define как четкое отличительное назначение контактов для имени.

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

В последнем примере показано использование переменной в качестве имени контакт. Такое определение приведено на официальном сайте документации Arduino.

На наш взгляд, это не лучший вариант, так как переменная займет ценное место в памяти.

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

Иногда в каком-либо проекте нет необходимости в аналоговых входах, тогда эти выводы можно использовать в качестве цифрового входа или выхода. В этом случае с помощью функции pinMode() можно установить необходимый режим для контактов A0 — A5.

#define power A0
void setup()
<
pinMode(power,OUTPUT);
>

Использование одного или нескольких контактов из A0… A5 как цифровых не приведет к невозможности использования оставшихся в качестве аналоговых входов. Можно использовать, например, 2 аналоговых входа и 4 цифровых выходов из A0… A5.

Функция digitalWrite()

Функция digitalWrite() позволяет установить состояние вывода как цифровой выход. Ее синтаксис (как и в pinMode()) требует двух параметров: первый — это номер контакта, второй — логическое значение LOW или HIGH.

Установка значения LOW приведет к тому, что напряжение на выходе будет 0В (короткое замыкание на массу), значение HIGH около 3,3В или 5В в зависимости от напряжения питания Arduino. Ниже приведен пример использования функции digitalWrite():

#define ledPin 13
void setup()
<
pinMode(ledPin,OUTPUT);
>
void loop()
<
digitalWrite(ledPin,HIGH); //включить LED
delay(500); //подождать 500ms (0,5 сек)
digitalWrite(ledPin,LOW); //выключить LED
delay(500); //подождать 500ms (0,5 сек)
>

В примере видно как можно установить соответствующее состояние вывода. Использованная в примере функция delay() позволяет выполнять задержку исполнения кода. Подробнее об этом будет обсуждаться далее.

При использование функции digitalWrite() в случае, когда вывод настроен как вход, необходимо включить или выключить режим PULLUP, то есть подключить подтягивающий резистор. В более поздних версиях Arduino IDE, безусловно, лучше использовать pinMode() с параметром INPUT_PULLUP.

Функция digitalRead()

Функция digitalRead() позволяет считывать состояние с вывода, определенного как цифровой вход. Эта функция возвращает значение LOW или HIGH. Необходимо указать номер контакта, с которого мы хотим прочитать состояние.

Если вывод, с которого мы считываем состояние в данный момент не подключен к схеме («висит в воздухе»), то функция может возвратить случайное значение — LOW или HIGH. Следует помнить об этом во время проектирования электронного оборудования. Для предотвращения такой ситуации необходимо использовать подтягивающий резистор. Ниже приведены примеры чтения состояния цифрового входа:

#define ledPin 13 // светодиод подключен к контакту 13
#define inPin 7 // кнопка подключена к контакту 7
int val = 0; // переменная, хранящая состояние входа
void setup()
<
pinMode(ledPin, OUTPUT); // pin 13 как выход
pinMode(inPin, INPUT_PULLUP); // pin 7 как вход
>
void loop()
<
val = digitalRead(inPin); // считываем состояние с контакт 7
digitalWrite(ledPin, val);// состояние светодиода зависит от состояния входа
>

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

Переменная val может содержать значение LOW или HIGH, в зависимости от состояния входа. Функция digitalWrite() задает состояние выхода в зависимости от переменной val.

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

#define ledPin 13 // светодиод подключен к контакту 13
#define inPin 7 // кнопка подключена к контакту 7
void setup()
<
pinMode(ledPin, OUTPUT); // pin 13 как выход
pinMode(inPin, INPUT_PULLUP); // pin 7 как вход
>
void loop()
<
if(digitalRead(inPin)) //более явный способ: if(digitalRead(inPin)==HIGH)
digitalWrite(ledPin, HIGH);
else
digitalWrite(ledPin, LOW);
>

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

Цифровые и аналоговые пины Ардуино

Назначение и описание пинов Arduino Uno, Nano, Mega 2560 ► важная информация, для тех кто только начал свое знакомство с микроконтроллерами этого семейства.

Назначение пинов Arduino плат: Uno, Nano, Mega 2560 — важная информация, для тех кто начал свое знакомство с микроконтроллерами этого семейства. Мы решили в этом обзоре максимально подробно описать аналоговые, цифровые и шим пины Arduino, также вы узнаете, как сделать аналоговые пины цифровыми. Еще мы рассмотрим назначение пинов с дополнительными функциями: SDA и SCL, TX и RX, и другие.

Аналоговые, цифровые и шим пины Ардуино

Все пины можно разделить на несколько видов, различие будет только в количестве данных выводов на различных платах. Например, на Arduino Mega 2560 цифровых и аналоговых портов, значительно больше, чем на Uno или Nano из-за большего размера платы и производительности микроконтроллера. В остальном характеристики и способы программирования пинов не отличаются друг от друга.

  1. Power Pins — порты питания, режим их работы нельзя запрограммировать или изменить. Они выдают стабилизированное напряжение 5V или 3,3V, Vin выдает напряжение от источника питания, а GND — это заземление (общий минус);
  2. PWM Pins — порты с ШИМ модуляцией, которые можно запрограммировать, как цифровой выход/вход. Данные порты обозначены на плате знаком тильда (˜);
  3. Analog In — порты, принимающие аналоговый сигнал от датчиков, работают на вход. Данные порты тоже можно запрограммировать, как цифровой вход/выход. Данные пины не поддерживают ШИМ модуляцию.

Режим пинов назначается в процедуре void setup с помощью pinMode(), например:

Пояснения к коду:

  1. к выходу 10 и A2 можно подключить светодиод, который будет включаться и выключаться при вызове команды в программе;
  2. пин 10 может использоваться для ШИМ сигнала, например, чтобы плавно включить светодиод, а пин A2 может выдавать только цифровой сигнал (0 или 1);
  3. к входу 12 и A1 можно подключить цифровой датчик и микроконтроллер будет проверять наличие сигнала на этих пинах (логический нуль или единицу);
  4. к входу A1 можно подключить аналоговый датчик тогда микроконтроллер будет получать не только сигнал но и узнавать характеристику сигнала.

Мы не случайно разделили пины с ШИМ модуляцией (PWM Pins) и аналоговые. PWM пины создают аналоговый сигнал, к ним подключают сервопривод, шаговый двигатель и другие устройства, где требуется подавать сигнал с разными характеристиками. Аналоговые пины (Analog In) используются для подключения аналоговых датчиков, с них входящий сигнал преобразуется в цифровой с помощью встроенного АЦП.

Ардуино Uno пины: шим, аналоговые, цифровые

Arduino UNO распиновка платы на русском

ШИМ (PWM) порты
(Analog Out)
3, 5, 6, 9, 10, 11
Аналоговые порты
(Analog In)
A0, A1, A2, A3, A4, A5
на некоторых платах: A6, A7
Цифровые порты
(Digital In/Out)
все порты со 2 по 13 пин
можно использовать: A0 — A7

Из таблицы видно, какие пины на Arduino UNO поддерживают шим. Аналоговые пины (Analog In) используют, как цифровые если недостаточно портов общего назначения, например, вы хотите подключить к плате 15 светодиодов. Кроме того, на плате Arduino Uno и Nano порты A4 и A5 используются для I2C протокола (SDA и SCL пины) — они работают параллельно с пинами A4 и A5. Об этом мы расскажем чуть позже.

Ардуино Nano пины: шим, аналоговые, цифровые

Arduino Nano распиновка платы на русском

ШИМ (PWM) порты
(Analog Out)
3, 5, 6, 9, 10, 11
Аналоговые порты
(Analog In)
A0, A1, A2, A3, A4, A5
на некоторых платах: A6, A7
Цифровые порты
(Digital In/Out)
все порты со 2 по 13 пин
можно использовать: A0 — A7

Если вы заметили, то пины на Arduino Nano и Uno имеют одинаковое количество и назначение. Платы отличаются лишь своими габаритами. Nano — более компактная и удобная плата, для экономии места на нее не ставят разъем питания, для этого используются пины Vin и GND на которое подается питание от источника.

Ардуино Mega пины: шим, аналоговые, цифровые

Схема распиновки платы Arduino Mega 2560 r3

ШИМ (PWM) порты
(Analog Out)
все порты со 2 по 13 пин
дополнительно: 44, 45, 46 пин
Аналоговые порты
(Analog In)
с A0 до A15
Цифровые порты
(Digital In/Out)
все порты со 2 по 13, со 22 по 52 пин
можно использовать: A0 — A15

Пины коммуникации нежелательно использовать, как обычные цифровые порты. Особенно при таком количестве портов общего назначения, как на Mega 2560. Более подробную информацию о рассмотренных платах, а также о других микроконтроллерах семейства Arduino (Pro Mini, Leonardo, Due и пр.): характеристики, описание пинов, габариты и т.д. можно узнать в разделе Микроконтроллеры на нашем сайте.

Делаем аналоговые пины Ардуино, как цифровые

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

Также можно использовать не буквенное, а цифровое обозначение выходов, т.е. A0 — это 14 пин, A1 — это 15 пин и т.д. (работает только на Uno или Nano).

В следующем примере две строчки имеют одинаковое значение.

Пины коммуникации на плате Arduino

Назначение пинов SDA, SCL Arduino

Данные пины используются для приема/передачи информации по протоколу I2C. Например, при подключении жк дисплея с модулем I2C или GPS модуля. С помощью специальной библиотеки микроконтроллер может обмениваться информацией с подключенным периферийным устройством, поддерживающим данный протокол. На Ардуино Мега, в отличии от Уно и Нано, имеется целых три пары пинов SDA, SCL.

Назначение пинов TX, RX Arduino

Пины TX/RX также используются для коммуникации, но уже по протоколу UART. На платах Уно и Нано пины TX/RX подключены параллельно USB разъему для связи с компьютером. Поэтому, если вы подключите к данным портам устройство, например, блютуз модуль, то вы не сможете загрузить в Ардуино скетч, так как плата автоматически переключается на чтение данных с устройства, а не с компьютера.

(3 votes, average: 5,00

Программирование Arduino &#8212; аналоговый ввод/вывод

1. Программирование Arduino — введение 2. Программирование Arduino — структура программы, константы 3. Программирование Arduino — цифровой ввод/вывод

4. Аналоговый ввод/вывод сигнала

теперь рассмотрим специфичные функции Arduino для аналогового ввода-вывода.

int analogRead(uint8_t);

Вызов: value = analogRead(порт); Описание:

Считывает значение с указанного аналогового порта. Arduino/Freeduino содержит 6 каналов аналого-цифрового преобразователя на 10 битов каждый. Это означает, что входное напряжения от 0 до 5В преобразовывается в целочисленное значение от 0 до 1023.

Разрешающая способность считывания составляет: 5V/1024 значений = 0,004883 В/значение (4,883 мВ). Требуется приблизительно 100 нсек (0.

0001 сек), чтобы считать значение аналогового ввода, так что максимальная скорость считывания — приблизительно 10000 раз в секунду.

Параметры: порт: номер опрашиваемого аналогового входа Возвращаемое значение: возвращает число типа int в диапазоне от 0 до 1023, считанное с указанного порта. Пример:
int val;
val = analogRead(0); // считываем значение на 0м аналоговом входе
Примечание:

Аналоговые порты, по-умолчанию, определенны на ввод сигнала и в отличие от цифровых портов их не требуется конфигурировать с помощью вызова функции pinMode.

void analogWrite(uint8_t, int);

Вызов: analogWrite(порт, значение); Описание:

Выводит на порт аналоговое значение. Эта функция работает на: 3, 5, 6, 9, 10, и 11 цифровых портах Arduino/Freeduino/CraftDuino. На старых версиях плат Arduino на основе микроконтроллера ATmega8 функция analogWrite() работает только на портах 9, 10 и 11.

Может применяться для изменения яркости светодиода, для управления двигателем и т.д. После вызова функции analogWrite, соответствующий порт начинает работать в режиме ШИМ (Широтно-Импульсная Модуляция) напряжения до тех пор, пока не будет следующего вызова функции analogWrite (или функций digitalRead / digitalWrite на том же самом порте).

Параметры: порт: номер опрашиваемого аналогового входа значение: целочисленное между 0 и 255. Значение 0 генерирует 0 В на указанном порте; значение 255 генерирует +5В на указанном порте. Для значений между 0 и 255, порт начинает быстро чередовать уровень напряжения 0 и +5 В — чем выше значение, тем, более часто порт генерирует уровень HIGH (5 В). Пример:
analogWrite(9, 128); // устанавливаем на 9 контакте значение эквивалентное 2,5В
Примечание: Нет необходимости вызвать функцию pinMode, чтобы установить порт на вывод сигналов перед вызовом функции analogWrite.

  • Частота генерирования сигнала – приблизительно 490 Гц.
  • void analogReference(uint8_t mode);
  • Определяет Источник Опорного Напряжения (ИОН) для АЦП.
  • DEFAULT: по-умолчанию 5V

Описание: Функция analogRead()вернёт 1023 для Опорного Напряжения. Параметры: INTERNAL: внутренний — используется внутренний источник в МК: 1.1V на ATmega168 и 2.56V на ATmega8. EXTERNAL: внешний – использует, источник, подключённый к порту AREF.

По-умолчанию используется 5V (DEFAULT) см. код.

Код ( функция объявлена в hardwarecoresarduinowiring.h , а реализована в hardwarecoresarduinowiring_analog.c):
uint8_t analog_reference = DEFAULT;

void analogReference(uint8_t mode)
<
// can't actually set the register here because the default setting
// will connect AVCC and the AREF pin, which would cause a short if
// there's something connected to AREF.
analog_reference = mode;
>
Вызов:analogReference(DEFAULT); Возвращаемое значение: Ничего Примечание: Внешний ИОН, нужно подключать к порту AREF через резистор в 5k, чтобы избежать повреждения МК.

читать далее: 5. дополнительные функции ввода/вывода

http://arduino.cc/en/Reference/HomePage (или же в каталоге ArduinoIDE
eferenceHomePage.html ) http://www.arduino.cc/en/Reference/AnalogReference http://freeduino.ru/arduino/lang.html

Цифровые входы/выходы

В уроке про распиновку платы мы обсуждали такое понятие, как GPIO: с англ. General Purpose Input-Output, входы-выходы общего назначения. Теперь надо разобраться с такими понятиями, как пин и порт. Пин – это конкретная нога микроконтроллера, имеющая свой номер, по которому к ней можно обратиться. Порт – это совокупность пинов. Микроконтроллер спроектирован так, чтобы обеспечить хорошее быстродействие, поэтому например пины объединены в порты, в одном порте обычно до 8 пинов (потому что в байте 8 бит). Работая с микроконтроллером напрямую, мы можем за одно действие установить состояние для всех пинов одного порта. Это очень быстро. Уроки у нас базовые, поэтому сегодня поговорим о функциях для работы с пинами, которые нам предлагает Ардуино. Но сначала давайте разберёмся, какие из пинов являются цифровыми. Взглянем на распиновку платы Нано:

Все пины, имеющие название PD*, PC*, PB*, являются GPIO. D, С и B указывает на номер порта, которому принадлежит пин. На плате пины подписаны по-другому, просто по порядку.

Таким образом мы видим, что все пины с D0-D13 и A0-A5 являются GPIO, то есть цифровыми входами-выходами. Многие называют пины A0A7 аналоговыми, на некоторых неофициальных распиновках они прям подписаны как analog pin, и это вводит новичков в заблуждение, потому что A0-A5 являются такими же цифровыми пинами, как D0-D13.

Но у этих пинов есть дополнительная функция в виде чтения аналогового сигнала. Об этом поговорим в следующем уроке. А вот пины A6 и A7 являются именно аналоговыми, потому что у них есть только выход на АЦП, эти пины не являются GPIO, и с ними нельзя работать функциями для цифровых пинов.

Если вы посмотрите на распиновку Arduino UNO, то вообще не найдёте там пинов A6 и A7, то есть УНО хоть и больше НАНО, но возможностей у неё меньше =)

Нумерация пинов

Пины пронумерованы на плате как “цифровые” D* пины и аналоговые A* пины. К цифровым пинам мы будем обращаться просто по их номеру, т.е. D3 это просто 3. С аналоговыми пинами чуть сложнее:

  • Обратиться можно с буквой A (A3, A5)
  • Можно цифрой по порядку после цифровых, так например у Нано последний цифровой – D13, следующий за ним “аналоговый” А0 имеет номер 14, а например A5 имеет номер 19, по которому к нему тоже можно обратиться, что позволяет управлять всеми пинами при помощи циклов

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

Цифровой пин может находиться в двух состояниях, вход и выход. В режиме входа пин может считывать напряжение от 0 до напряжения питания МК, а в режиме выхода – выдавать такое же напряжение. Режим работы выбирается при помощи функции pinMode(pin, mode), где pin это номер пина, а mode это режим:

  • mode – режим работы
  • INPUT – вход
  • OUTPUT – выход
  • INPUT_PULLUP – подтянутый к питанию вход

Если со входом/выходом всё понятно, то с подтяжкой давайте разберёмся. В режиме входа пин микроконтроллера не подключен никуда и ловит из воздуха всякие наводки, получая практически случайное значение.

Для задания пину “состояния по умолчанию” используют подтяжку резистором к земле или питанию. Вот режим INPUT_PULLUP включает встроенную в микроконтроллер подтяжку пина к питанию.

Подробнее об этом, со схемами и примерами я рассказывал в начале вот этого видео урока.

По умолчанию все пины сконфигурированы как входы (INPUT)
Используя информацию из предыдущего пункта и урока о циклах, можно изменить режим работы например для всех пинов с D2 по A5:

for (byte i = 2; i

AVR GCC :: УПРАВЛЕНИЕ ПОРТАМИ МИКРОКОНТРОЛЛЕРА

Управление портами в AVR GCC. Регистры DDRx и PORTx. Представление чисел. Побитные операции.

Функция задержки. Безусловный переход в программе.

Порты микроконтроллера &#8212; это устройства ввода/вывода, позволяющие микроконтроллеру передавать или принимать данные. Стандартный порт микроконтроллера AVR имеет восемь разрядов данных, которые могут передаваться или приниматься параллельно. Каждому разряду (или биту) соответствует вывод (ножка) микроконтроллера. Ножки микроконтроллера также называют пинами. Для обозначения портов используются латинские буквы А, В, С и т.д. Количество портов ввода/вывода варьируется в зависимости от модели микроконтроллера.

Любой порт микроконтроллера можно сконфигурировать как вход или как выход. Для того чтобы это сделать, следует записать в соответствующий порту регистр DDRx необходимое значение.

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

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

DDRx &#8212; регистр направления передачи данных. Этот регистр определяет, является тот или иной вывод порта входом или выходом. Если некоторый разряд регистра DDRx содержит логическую единицу, то соответствующий вывод порта сконфигурирован как выход, в противном случае &#8212; как вход. Буква x в данном случае должна обозначать имя порта, с которым вы работаете. Таким образом, для порта A это будет регистр DDRA, для порта B &#8212; регистр DDRB и т. д.

Используя AVR GCC, записать в необходимый регистр то или иное значение можно одним из следующих способов.

Для всего порта сразу.

Все выводы порта D будут сконфигурированы как выходы.

0xff &#8212; шестнадцатиричное представление числа ff, где 0x является префиксом, используемым для записи шестнадцатиричных чисел. В десятичном представлении это будет число 255, а в двоичном виде оно будет выглядеть как 11111111. То есть во всех битах регистра DDRD будут записаны логические единицы.

В AVR GCC для представления двоичных чисел используется префикс 0b. Таким образом, число 11111111 должно представляться в программе как 0b11111111. Мы можем записать предыдущую команду в более читабельном виде.

  • DDRD = 0b11111111;
  • DDRD = 0x00;
  • DDRD = 0xb3;

Хотя такая запись и выглядит более наглядной, при конфигурировании портов принято использовать шестнадцатиричное представление чисел. Для того чтобы сконфигурировать все выводы порта D как входы, следует записать во все биты регистра DDRD логические нули. В регистр DDRD можно записать и другие числа. Например:

0xb3 &#8212; шестнадцатиричное представление числа 179. В двоичном виде оно будет выглядеть как 10110011. То есть часть выводов порта D будет сконфигурирована как выходы, а часть &#8212; как входы.

_BV(PD1); // установить 0 (низкий уровень) на выводе PD1 > // закрывающая скобка основной программы

Теперь попробуем мигнуть светодиодом, подключенным так, как это изображено на левом рисунке. Для этого используем функцию задержки _delay_ms().

Функция _delay_ms() формирует задержку в зависимости от передаваемого ей аргумента, выраженного в миллисекундах (в одной секунде 1000 миллисекунд). Максимальная задержка может достигать 262.14 миллисекунд.

Если пользователь передаст функции значение более 262.14, то произойдет автоматическое уменьшение разрешения до 1/10 миллисекунды, что обеспечивает задержки до 6.5535 секунд.

(О формировании более длительных задержек можно прочитать в статье Циклы в языке Си. Формирование задержки.)

Функция _delay_ms() содержится в файле delay.h, поэтому нам будет необходимо подключить этот файл к программе. Кроме того, для нормальной работы этой функции необходимо указать частоту, на которой работает микроконтроллер, в герцах. /************************************* ПРИМЕР МИГАНИЯ СВЕТОДИОДОМ Пример подключения на рисунке 1 **************************************/ #define F_CPU 1000000UL // указываем частоту в герцах #include #include int main(void) < // начало основной программы DDRD = 0xff; // все выводы порта D сконфигурировать как выходы PORTD |= _BV(PD1); // установить 1 (высокий уровень) на выводе PD1, //зажечь светодиод _delay_ms(500); // ждем 0.5 сек. PORTD &#038;=

_BV(PD1); // установить 0 (низкий уровень) на выводе PD1, //погасить светодиод _delay_ms(500); // ждем 0.5 сек. PORTD |= _BV(PD1); // установить 1 (высокий уровень) на выводе PD1, //зажечь светодиод _delay_ms(500); // ждем 0.5 сек. PORTD &#038;=

_BV(PD1); // установить 0 (низкий уровень) на выводе PD1, //погасить светодиод > // закрывающая скобка основной программы
Серия миганий светодиодом будет очень короткой. Для того чтобы сделать мигание непрерывным, можно организовать бесконечный цикл с помощью оператора безусловного перехода goto. Оператор goto осуществляет переход к месту программы, обозначенному меткой. Имя метки не должно содержать пробелов. После имени метки ставится знак двоеточия. Между именем метки и двоеточием не должно быть пробелов. /******************************************************* ПРИМЕР БЕСКОНЕЧНОГО МИГАНИЯ СВЕТОДИОДОМ Пример подключения на рисунке 1 ********************************************************/ #define F_CPU 1000000UL // указываем частоту в герцах #include #include int main(void) < // начало основной программы DDRD = 0xff; // все выводы порта D сконфигурировать как выходы start: // метка для команды goto start PORTD |= _BV(PD1); // установить 1 (высокий уровень) на выводе PD1, //зажечь светодиод _delay_ms(250); // ждем 0.25 сек. PORTD &#038;=

_BV(PD1); // установить 0 (низкий уровень) на выводе PD1, //погасить светодиод _delay_ms(250); // ждем 0.25 сек. goto start; // перейти к метке start > // закрывающая скобка основной программы


Источник: xn—-dtbchbawj2amueleii7b6i.xn--p1ai