24.1: Вступ
- Page ID
- 29385
Наступна дискусія стосується суворо двох станів високого/низького логічного рівня зондування. Для беззмінних аналогових сигналів див. запис Bits & Pieces, що охоплює AnaloRead (). За допомогою функції PinMode () або шляхом прямого доступу до відповідних бітів регістра напрямків даних (DDRx), з'єднання вводу-виводу загального призначення можуть бути налаштовані для читання стану зовнішніх комутаторів або логічних рівнів. З Arduino Uno 5 вольт представляє логіку високої, тоді як 0 вольт представляє логічний низький рівень. Додатковою ємністю ATMega 328P на Uno є можливість включати додатковий внутрішній підтягуючий резистор на вхідному контакті. Це дозволяє підключити простий пасивний вимикач короткого на землю (тобто вхідний штифт плаває високо, коли вимикач відкритий і знижується, коли перемикач включений).
Для читання окремих контактних входів система Arduino пропонує функцію DigitalRead (). Кілька контактів можна прочитати одночасно, безпосередньо звернувшись до відповідного реєстру, який ми розглянемо згодом. Нижче наведено копію онлайн-документації для функції DigitalRead ():
Цифрове читання (1)
Опис
Зчитує значення з вказаного цифрового контакту, HIGH або LOW.
Синтаксис
Цифровий зчитування (pin)
Параметри
pin: номер цифрового контакту, який ви хочете прочитати (int)
Приклад
int ledPin = 13; // LED connected to digital pin 13
int inPin = 7; // pushbutton connected to digital pin 7
int val = 0; // variable to store the read value
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin 13 as output
pinMode(inPin, INPUT); // sets the digital pin 7 as input
}
void loop()
{
digitalWrite(ledPin, val); // read the input pin
val = digitalRead(inPin); // sets the LED to the button's value
}
Встановлює контакт 13 на те ж значення, що і штифт 7, який є входом.
Примітка
Якщо штифт ні до чого не підключений, DigitalRead () може повернути HIGH або LOW (і це може змінюватися випадковим чином).
Аналогові вхідні штифти можуть використовуватися як цифрові штифти, іменовані як A0, A1 тощо.
Див. також
Злегка очищена версія вихідного коду наступна (знайдена в файлі wiring_digital.c):
int digitalRead( uint8_t pin )
{
uint8_t timer, bit, port;
timer = digitalPinToTimer( pin );
bit = digitalPinToBitMask( pin );
port = digitalPinToPort( pin );
if (port == NOT_A_PIN) return LOW;
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
if (*portInputRegister(port) & bit) return HIGH;
return LOW;
}
static void turnOffPWM( uint8_t timer )
{
switch ( timer )
{
case TIMER0A: cbi( TCCR0A, COM0A1 ); break;
case TIMER0B: cbi( TCCR0A, COM0B1 ); break;
// and so forth for all available timers, not shown
}
}
Перші три рядки перетворюють позначення контактів Arduino у відповідний порт ATMega 328P, номер розряду і таймер. Якщо порт недійсний, функція виходить.
timer = digitalPinToTimer( pin ); bit = digitalPinToBitMask( pin ); port = digitalPinToPort( pin ); if (port == NOT_A_PIN) return LOW;
Таймер важливий, оскільки система Arduino попередньо налаштовує три бортові таймери Uno для використання з функцією AnalogWrite () за допомогою схеми широтно-імпульсної модуляції. Це впливає на шість можливих штифтів. Для правильної роботи цифрового зчитування ці таймери потрібно вимкнути. Ми бачили цей самий біт коду всередині функції DigitalWrite ().
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
У цей момент читається вміст вхідного регістра (пряма назва вхідного регістра - PinX), а потім додається запитуваним бітом. Це видаляє всі інші біти, так що ми можемо повернути або простий високий або низький.
if (*portInputRegister(port) & bit) return HIGH; return LOW;
Функція, яка використовується для відключення таймерів широтно-імпульсної модуляції, трохи більше, ніж оператор перемикача/випадку. Якщо вказаний контакт Arduino підключений до таймера внутрішньо, цей таймер знаходиться в операторі switch і cbi () виклик виконується на відповідному регістрі управління таймер-лічильник. Функція cbi () перекладається на одну інструкцію мови збірки, щоб очистити вказаний біт у контрольному регістрі, таким чином вимикаючи цей таймер.
static void turnOffPWM( uint8_t timer )
{
switch (timer)
{
case TIMER0A: cbi(TCCR0A, COM0A1); break;
case TIMER0B: cbi(TCCR0A, COM0B1); break;
case TIMER1A: cbi(TCCR1A, COM1A1); break;
case TIMER1B: cbi(TCCR1A, COM1B1); break;
case TIMER2A: cbi(TCCR2A, COM2A1); break;
case TIMER2B: cbi(TCCR2A, COM2B1); break;
}
}
У деяких додатках потрібно читати відразу кілька бітів, наприклад при читанні паралельних даних. Це можна виконати через прямий доступ до відповідного реєстру PinX. PinX скоріше схожий на братського близнюка реєстру PortX. Хоча PortX використовується для запису цифрових даних на зовнішнє з'єднання, PinX - це місце, де ви читаєте цифрові дані із зовнішнього з'єднання. Так само, як є чотири регістри вихідних портів, від A до D, є чотири регістри вхідних контактів, від А до D. Не всі мікроконтролери налаштовані таким чином. Деякі з них використовують один і той же регістр як для читання, так і для запису (функція контролюється пов'язаним регістром напрямків даних).
Ось як безпосередньо отримати доступ до одного біта на підключеному штифті без таймера. Спочатку очистіть потрібний напрямок даних регістр біт, щоб активувати режим введення. По-друге, за бажанням встановіть той самий біт у відповідному регістрі портів, щоб увімкнути додатковий резистор підтягування. Якщо ви не хочете підтягування, залиште це трохи ясно. Нарешті, прочитайте потрібний біт у контактному регістрі і і його з бітовою маскою, щоб видалити інші біти. Наприклад, щоб прочитати біт 4 (0x10 або 00010000 у двійковому) на порту B:
DDRB &= (~0x10); // activate input mode
PORTB |= 0x10; // enable pull-up or use the bitSet macro
// bitSet( PORTB, 4 );
value = PINB & (~0x10); // retrieve data
Це лише незначна робота, щоб змінити це для декількох бітів. Щоб прочитати обидва біти 0 і 4, але без підтягуючих резисторів (бітовий малюнок 00010001 або 0x11):
DDRB &= (~0x11); // activate input mode PORTB &= (~0x11); // disable pull-up value = PINB & (~0x11); // retrieve data bits
або якщо ви хочете біти окремо:
value0 = PINB & (~0x01); // retrieve data bit 0 value4 = PINB & (~0x10); // retrieve data bit 4
