категории: Микроконтролер вериги
Брой преглеждания: 41940
Коментари към статията: 5

Методи за четене и управление на Arduino I / O портове

 

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

Методи за четене и управление на Arduino I / O портове

Първи метод - стандартният език за ID на Arduino

Всеки знае това Arduino Той се програмира в C ++ с известна адаптация и опростявания за начинаещи. Нарича се окабеляване. Първоначално всички портове arduino са дефинирани като входове и не е необходимо да се уточнява това в кода.

Портовете обикновено се записват във функцията за инициализация на променлива:

настройка за невалидност ()
{
// код
}

За това се използва командата pinMode, тя има доста прост синтаксис, първо се посочва номерът на порта, след това ролята му се разделя със запетаи.

pinMode (nomer_porta, naznachenie)

С тази команда вътрешната схема на микроконтролера е конфигурирана по специфичен начин.

Има три режима, в които портът може да работи: INPUT - вход, в този режим става четене на данни от сензори, състояние на бутон, аналогов и цифров сигнал. Пристанището е разположено в т.нар състояние с висок импеданс, с прости думи - входът има висока устойчивост. Тази стойност е зададена, например, 13 пина на платката, ако е необходимо, както следва:

pinMode (13, INPUT);

ИЗХОД - изход, в зависимост от командата, предписана в кода, портът приема стойност една или нула. Изходът се превръща в един вид контролиран източник на енергия и произвежда максимален ток (в нашия случай 20 mA и 40 mA на върха), свързан към товара. За да зададете порт като изход на Arduino, трябва да въведете:

pinMode (13, изход);

INPUT_PULLUP - портът работи като вход, но така нареченият се свързва с него. 20 kΩ издърпващ резистор.

Условната вътрешна схема на пристанището в това състояние е показана по-долу. Характерна особеност на този вход е, че входният сигнал се възприема като обърнат ("единицата" на входа се възприема от микроконтролера като "нула"). В този режим не можете да използвате външни издърпващи резистори когато работите с бутони.

pinMode (13, INPUT_PULLUP);

Входен издърпащ резистор

Данните се получават от портовете и се предават към тях от командите:

  • digitalWrite (пин, стойност) - преобразува изходния щифт в логично 1 или 0, съответно 5V напрежение се появява или изчезва на изхода, например digitalWrite (13, HIGH) - доставя 5 волта (логическа единица) до 13 пина и digitalWrite (13, ниско ) - превежда 13 пина в състояние на логическа нула (0 волта);

  • digitalRead (pin) - чете стойността от входа, например digitalRead (10), чете сигнала от 10 пина;

  • analogRead (pin) - чете аналогов сигнал от аналогов порт, получавате стойност в диапазона от 0 до 1023 (в рамките на 10-битов ADC), пример е analogRead (3).


Метод втори - управление на пристанищата чрез Atmega регистри и ускоряване на кода

Подобен контрол разбира се е прост, но в този случай има два недостатъка - по-голяма консумация на памет и лоша производителност при работа с портове. Но помнете какво е Arduino, независимо от опционната дъска (uno, micro, nano)? На първо място това микроконтролер AVR семейство ATMEGA, наскоро използван MK atmega328.

В Arduino IDE можете да програмирате на родния език за това семейство от C AVR, сякаш работите с отделен микроконтролер. Но първо първо. За да управлявате Arduino портове по този начин, първо трябва внимателно да разгледате следната илюстрация.

Портове за микроконтролери Atmega168

Може би някой по-ясно ще разгледа портовете в тази форма (същата на фигурата, но в различен дизайн):

Портове за микроконтролери Atmega328

Тук виждате съответствието на заключенията на Ардуино и имената на пристанищата на Атмега. И така, имаме 3 порта:

  • PORTB;

  • PORTC;

  • PORTD.

Въз основа на показаните изображения съставих таблица за кореспонденция между пристанищата на Ардуино и Атмега, тя ще ви бъде полезна в бъдеще.

Таблица на съответствие на пристанищата Arduino и Atmega

Atmega има три 8-битови регистъра, които контролират състоянието на портовете, например, порт B ще разбере тяхното предназначение чрез изтегляне на аналогии със стандартните инструменти за окабеляване, описани в началото на тази статия:

  • PORTB - Управление на състоянието на изхода. Ако щифтът е в режим "Изход", тогава 1 и 0 определят наличието на едни и същи сигнали на изхода. Ако щифтът е в режим "Вход", тогава 1 свързва издърпващ резистор (същият като INPUT_PULLUP, обсъден по-горе), ако 0 е състояние с висок импеданс (аналог на INPUT);

  • PINB е регистър за четене. Съответно, тя съдържа информация за текущото състояние на щифтовете на порта (логическа единица или нула).

  • DDRB - регистър на посоката на порта. С него посочвате на микроконтролера какъв е портата като вход или изход, с "1" изход и "0" вход.

Вместо буквата "B" може да има всяка друга според имената на портовете, например PORTD или PORTC другите команди работят по подобен начин.

Мигаме светодиода, заместваме стандартната функция digitalWrite (). Първо, нека си припомним как изглежда оригиналният пример от библиотеката ID на Arduino IDE.

Arduino LED мигащ код

Това е кодът на добре познатото „мигане“, което показва мигането на вградения в платката светодиод.

Управление на пин

Коментарите обясняват кода. Логиката на тази работа е следната.

Командата PORTB B00100000 поставя PB5 в състояние на логическа единица, вижте, и тези снимки и таблицата по-долу са разположени и виждаме, че PB5 съответства на 13 пина на Arduina.

Буквата "B" пред числата показва, че записваме стойностите в двоичен вид. Номерирането в двоично отива от дясно на ляво, т.е. тук единицата е в шестия бит от десния ръб на бита, който казва на микроконтролера за взаимодействието със състоянието на шестия бит на регистър B порт (PB5). Таблицата по-долу показва структурата на порт D, тя е подобна и е дадена като пример.

Структура на порт D

Можете да зададете стойността не в двоична, а в шестнадесетична форма, например за това отваряме калкулатора на прозорците и в режим „ВИЖТЕ“ избираме опцията „Програмист“.

Windows калкулатор

Въведете желания номер:

Режим на калкулатор на програмист

И кликнете върху HEX:

Превод на номера на калкулатор

В този случай прехвърляме всичко това на Arduino IDE, но вместо префикса "B" ще бъде "0x".

Прехвърляне на номер в Arduino IDE

Но с този вход има проблем. Ако имате нещо свързано с други пинове, тогава въведете команда като B00010000 - ще нулирате всички пинове с изключение на 13 (PB5). Можете да въведете данни за всеки пин поотделно. Ще изглежда така:

Въвеждане на данни във всеки пин

Такъв запис може да изглежда неразбираем, нека да го разберем.

Разбор на запис

Това е логична операция за добавяне, | = означава добавяне на нещо към съдържанието на порта.

Логическа операция за добавяне

Това означава, че трябва да добавите дума от 8 бита в регистъра с единица, изместена с 5 бита - в резултат, ако 11000010 се окаже 110 1101010. В този пример може да се види, че само PB5 се е променил, останалите битове от този регистър са останали непроменени, както и Състоянието на щифтовете на микроконтролера остана непроменено.

Но с логическото добавяне възниква проблем - не можете да превърнете устройството в нула, защото:

0+0=1

1+0=1

0+1=1

Логическото умножение и инверсия ще ни помогнат:

Логическо умножение и обръщане

& = означава да умножим съдържанието на порта с конкретно число.

 

Умножение на съдържанието на порта на число

И това е числото, с което се умножаваме. Знакът "~" показва инверсия. В нашия случай обърнатата единица е нула. Тоест, умножаваме съдържанието на пристанището по нула, изместено с 5 бита. Например беше 10110001, стана 10100001. Останалите битове останаха непроменени.

Умножете съдържанието на порта с нула, изместена с 5 бита

Същото може да се направи с помощта на операцията за инвертиране (^):

Четенето от портове, аналогът на digitalRead () се извършва с помощта на регистъра на ПИН, на практика изглежда така:

Четете от пристанищата

Тук проверяваме дали изразът в скоби е равен на реалното състояние на портовете, т.е. подобно, ако написахме if (digitalRead (12) == 1).


заключение

Защо има такива трудности с управлението на пристанищата, ако можете да използвате стандартни удобни функции? Всичко е в скоростта и размера на кода. При използване на втория метод, разгледан в статията, размерът на кода е значително намален и скоростта се увеличава с няколко порядъка. Стандартният digitalWrite () беше изпълнен в 1800 μs и запис директно към порта в 0.2 μs, а digitalRead () в 1900 μs, а също така стана в 0.2 μs. Този метод на управление е открит в откритите пространства на мрежата и често се намира в код. готови проекти.

Вижте също на e.imadeself.com:

  • Свързване и програмиране на Arduino за начинаещи
  • Как да свържете инкрементален енкодер към Arduino
  • PIC микроконтролери за начинаещи
  • Дистанционно управление на микроконтролер: IR дистанционно, Arduino, ESP8266, 433 ...
  • Измерване на температура и влажност на Arduino - селекция от начини

  •  
     
    Коментари:

    # 1 написа: Kipovets | [Цитиране]

     
     

    „Но с логическото добавяне възниква проблем - не можете да превърнете устройството в нула, защото:

    0 + 0 = 1 "(в)

    Малък надзор: 0 + 0 = 0.

     
    Коментари:

    # 2 написа: chugou | [Цитиране]

     
     

    Киповец, той вероятно е искал да каже:

    1 + 1 = 1

     
    Коментари:

    # 3 написа: | [Цитиране]

     
     

    Kipovets,
    Банална печатна грешка! Виждате колко е хубаво, че на нашия портал седят специалисти! Трябва да направите само подходящо съдържание!

     
    Коментари:

    # 4 написа: Сердж | [Цитиране]

     
     

    В последната част пише PORTB | = 1 << 5 ... if (digitalRead (12) == 1). Но 5 пинов порт B, това е 13 пина на arduino. Или греша ?!

     
    Коментари:

    # 5 написа: р-а-з-а | [Цитиране]

     
     

    Ако (PINB == B00010000) {} не еподобно на това, ако написахме if (digitalRead (12) == 1)
    по-скоро аналогов
    (digitalRead (12) == 1) &&(digitalRead (13) == 1) &&(digitalRead (14) == 1) &&(digitalRead (15) == 1) &&(digitalRead (11) == 1) ... и така 8 пина на порта

    Тук имате нужда или от това:
    ако (
    ! (~ PORTB & (1 << PB4))) {} //постъпления0 или 1
    или така:
    ако (PORTB & (1 << PB4)) {} // връща изместената единица = 16, DEC
    или така:
    ако (
    bit_is_set (PORTB, 4)) {}// връща изместената единица = 16, DEC