22.1: Цифровий запис ()
- Page ID
- 29413
«Запис в порт» означає, що ми хочемо контролювати якийсь зовнішній пристрій. Це може включати встановлення або очищення одного біта для включення світлодіода або двигуна. Також може знадобитися набір бітів, наприклад, для надсилання коду ASCII байт-за байтом або для запису слів даних на зовнішній цифро-аналоговий перетворювач (ЦАП). Важливо пам'ятати, що мікроконтролер має обмежену кількість струму раковини/джерела, доступного на кожен контакт (40 мА на кожен контакт ATMega 328P, але не більше 200 мА всього для чіпа). Таким чином, можна прогнати жменьку світлодіодів до 10 мА кожен з прямим підключенням, що складається з струмообмежуючого резистора і світлодіода, але включити навіть відносно невеликий двигун постійного струму не представляється можливим. Більш високі струмові (або напруга) навантаження вимагатимуть певного способу драйвера або схеми інтерфейсу. Ми відмовимося від цієї дискусії і просто зосередимося на частині коду тут.
Оскільки висновки вихідного порту можуть бути лише у високому або низькому стані, вони називаються цифровими виходами. Хоча можна генерувати аналогові сигнали, або через широтно-імпульсну модуляцію або додаткову зовнішню схему, цифровий високий/низький характер портових штифтів - це все, що є. Взагалі кажучи, більшість мікроконтролерів не виробляють безступінчатих аналогових напруг на контактах своїх портів. Однак є винятки з цього. Наприклад, плата Arduino Due 1 використовує процесор Atmel SAM3X8E ARM Cortex-M3, який містить два внутрішніх 12-бітних ЦАП.
Перед написанням, порт повинен бути налаштований на належний напрямок. Це означає використання або PinMode () або пов'язаного регістра напрямків даних, DDRx, щоб встановити режим для виведення, перш ніж ми зможемо розглянути можливість запису даних на зовнішній пристрій. Якщо біт одного порту - це все, що потрібно, PinMode () дуже простий і надійний. Якщо потрібно керувати кількома бітами разом, може бути простіше перейти безпосередньо до DDRx.
Подібно до того, як існує два методи для встановлення режиму виведення, те саме вірно для запису самих даних; один ефективний метод для окремих бітів, а інший для наборів бітів.
Для запису одного біта функція DigitalWrite () є хорошим вибором. Ось он-лайн документація для нього, знайдена за адресою http://arduino.cc/en/Reference/DigitalWrite:
Цифровий запис ()
Опис
Запишіть значення HIGH або LOW на цифровий штифт.
Якщо контакт був налаштований як OUTPUT з PINMode (), його напруга буде встановлена на відповідне значення: 5V (або 3.3V на платах 3.3V) для HIGH, 0V (земля) для LOW.
Якщо контакт налаштований як ВХІД, запис HIGH значення за допомогою DigitalWrite () ввімкне внутрішній 20K pullup резистор (див. Підручник з цифрових контактів). Запис LOW призведе до відключення підтягування. Підтягуючого резистора досить, щоб світло світлодіода тьмяно, тому якщо світлодіоди здаються працювати, але дуже тьмяно, це ймовірна причина. Засіб полягає в тому, щоб встановити штифт на вихід за допомогою функції PinMode ().
ПРИМІТКА: Цифровий штифт 13 важче використовувати як цифровий вхід, ніж інші цифрові штифти, оскільки до нього прикріплений світлодіод та резистор, який припаяний до плати на більшості плат. Якщо ви включите його внутрішній 20k підтягування резистор, він буде висіти на позначці 1.7 В замість очікуваного 5V, тому що бортовий світлодіод і послідовний резистор тягнуть рівень напруги вниз, тобто він завжди повертається LOW. Якщо ви повинні використовувати контакт 13 в якості цифрового входу, використовуйте зовнішній тягнути вниз резистор.
Синтаксис
Цифровий запис (pin, значення)
Параметри
pin: номер штифта
значення: ВИСОКЕ або НИЗЬКЕ
Повертає
жоден
Приклад
int ledPin = 13; // LED connected to digital pin 13
void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop()
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
З прикладу коду, це досить простий у використанні. Просто встановіть напрямок спочатку, а потім напишіть до відповідного позначення штифтів Arduino. Пам'ятайте, що позначення штифтів - це цифри, написані поруч із заголовками на платі Uno, вони не є номерами бітів портів на ATMega 328P! Довідкову примітку щодо Arduino pin 13 варто перечитати. Pin 13 підключений до бортового сигнального світлодіода поверхневого кріплення, розташованого поруч із вказаним штифтом. Це також означає, що загальний струм джерела, доступний для контакту 13, дещо зменшується, оскільки світлодіодний струм також завжди застосовуватиметься. Ардуіно контактний 13 є PORTB біт 5 (іноді пишеться стенографія як PORTB.5).
Отже, тільки що робить функція DigitalWrite ()? Ось код для DigitalWrite (), трохи очищений для вашого задоволення від перегляду 2:
void digitalWrite( uint8_t pin, uint8_t val )
{
uint8_t timer, bit, port, oldSREG;
volatile uint8_t *out;
timer = digitalPinToTimer( pin );
bit = digitalPinToBitMask( pin );
port = digitalPinToPort( pin );
if (port == NOT_A_PIN) return;
if (timer != NOT_ON_TIMER) turnOffPWM( timer );
out = portOutputRegister( port );
oldSREG = SREG;
cli();
if (val == LOW) *out &= ~bit;
else *out |= bit;
SREG = oldSREG;
}
Давайте розберемо це окремо, шматок за шматком, по крупицях. Після початкових декларацій даних ми бачимо групу викликів функцій, які служать для перекладу позначення контактів Arduino у відповідні порти ATMega 328P, біти та таймери. (Таймер бізнес, який ми розглянемо найближчим часом.) Цей розділ закінчується перевіркою помилок. Якщо вказаний штифт не існує, функція рятує і нічого не робить.
timer = digitalPinToTimer( pin ); bit = digitalPinToBitMask( pin ); port = digitalPinToPort( pin ); if (port == NOT_A_PIN) return;
Серія контролерів AVR, як і більшість контролерів, містять внутрішні таймери/лічильники. Вони дозволяють контролеру точно час подій або виробляти імпульсні сигнали (зокрема, широтно-імпульсна модуляція). Система Arduino попередньо налаштовує шість доступних виходів з таймерами для використання з функцією AnalogWrite (). Оскільки не всі штифти мають цю здатність, нам потрібно перевести контакт Arduino на пов'язаний таймер з функцією DigitalPintoTimer (). Пізніше ми розглянемо таймери, але наразі важливо лише розуміти, що будь-який пов'язаний таймер повинен бути вимкнений, перш ніж ми зможемо використовувати нашу основну функцію цифрового запису.
if (timer != NOT_ON_TIMER) turnOffPWM( timer );
Код для відключення функціональності ШІМ трохи більше, ніж оператор switch/case. Виклик cbi () використовується для очищення певного біта в порту, у цьому випадку пов'язаний реєстр керування таймер-лічильник (TCCRx). Більш детальну інформацію можна знайти на сайті http://playground.arduino.cc/Main/AVR.
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;
}
}
Після цього вказаний порт Arduino переводять в вихідний регістр, тобто PortX.
out = portOutputRegister( port );
Як було видно з pinMode (), реєстр стану зберігається, глобальний біт переривання очищається, щоб відключити всі переривання за допомогою виклику cli (), потрібний порт (PortX) anDed з доповненням бітової маски, щоб очистити його (тобто встановити його низько) або orD з бітовою маскою для встановити його (тобто встановити високо). Потім реєстр статусів відновлюється до початкового стану:
oldSREG = SREG; cli(); if (val == LOW) *out &= ~bit; else *out |= bit; SREG = oldSREG;
Це дуже багато. Тепер, якщо ви хочете написати купу бітів до групи вихідних портових з'єднань, ви можете просто шукати відповідний порт для цих висновків Arduino (тобто PortX) і встановити або очистити їх безпосередньо. Наприклад, якщо ви хочете очистити біти 0, 1 і 4 порту B (тобто 00010011 або 0x13), ви можете зробити наступне (припускаючи, що таймер не активний):
PORTB &= ~0x13; // clear bits
або встановити їх:
PORTB |= 0x13; // set bits
Це залишило б інші біти повністю недоторканими. На відміну від цього, припустимо, що ви хочете встановити нижні чотири біти (тобто від 0 до 3) у двійковий шаблон 0101. Це еквівалентно 0x05. Ви можете зробити наступне:
PORTB = (PORTB & 0xf0)| 0x05;
Перший шматок очищає нижні чотири біти, а кінцева частина встановлює бінарний шаблон. Це було б краще, щоб очистити біти 1 і 3, а потім встановити біти 0 і 2, оскільки це призведе до двох різних наборів моделей вихідної напруги на зовнішніх штифтах. Звичайно, перший набір буде існувати лише дуже короткий час, але це може створити проблеми в деяких додатках.
- http://arduino.cc/en/Main/ArduinoBoardDue
- Оригінал можна знайти в файлі wiring_digital.c
