04_06 77,17
Использование константы с номером контакта вместо переменной 04_07 77,92
Перенос содержимого loop в setup 04_08 86,39

Байты и биты

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

На рис. 4.2 показано, как связаны биты и байты.

Рис. 4.2. Биты и байты

Бит (в английском языке bit, происходит от binary digit — двоичная цифра) может иметь одно из двух значений — 0 или 1. Байт — это коллекция из 8 битов. Так как каждый из битов в байте может иметь значение 1 или 0, всего возможно 256 разных комбинаций битов в байте. Байт можно использовать для представления любых чисел в диапазоне от 0 до 255.

Каждый бит можно использовать также для обозначения состояния «включено» или «выключено». То есть, чтобы включить или выключить подачу напряжения на какой-то контакт, нужно установить или сбросить некоторый бит.

Порты в ATmega328

На рис. 4.3 изображены порты в микроконтроллере ATmega328 и то, как они связаны с контактами на плате Arduino Uno.

Рис. 4.3. Порты в ATmega328

Каждый порт не случайно имеет по 8 бит (байт), хотя в портах B и C используется только по 6 бит. Каждый порт управляется тремя регистрами. Регистр можно считать специальной переменной, позволяющей присваивать ей значения и читать значение из нее. На рис. 4.4 изображены регистры для порта D.

Рис. 4.4. Регистры для порта D

Регистр DDRD (Data Direction Register D — регистр D направления передачи данных) имеет 8 бит, каждый из которых определяет режим работы соответствующего контакта — вход или выход. Если бит установлен в значение 1, контакт работает как выход, в противном случае — как вход. Этим регистром управляет функция pinMode. Регистр PORTD используется для установки выходного напряжения на выходе, то есть digitalWrite устанавливает соответствующий бит, 1 или 0, чтобы установить на указанном контакте уровень напряжения HIGH или LOW.

Последний регистр называется PIND (Port Input D — вход порта D). Читая содержимое этого регистра, можно определить, на какие контакты подано напряжение HIGH, а на какие — LOW.

Каждый из трех портов имеет свои три регистра, для порта B они называются DDRB, PORTB и PINB, а для порта C — DDRC, PORTC и PINC.

Очень быстрый вывод цифровых сигналов

Следующий скетч обращается к портам напрямую, без применения pinMode и digitalWrite:

// sketch_04_09_square_ports

byte state = 0;

void setup()

{

  DDRB = B00000100;

  while (true)

  {

    PORTB = B00000100;

    PORTB = B00000000;

  }

}

void loop()

{

}

Скетч должен переключать контакт D10, который связан с портом B, поэтому вначале контакт настраивается на работу в режиме выхода, для чего третий бит справа в регистре DDRB устанавливается в 1. Обратите внимание на то, что B00000100 — это двоичная константа. В главном цикле мы сначала устанавливаем тот же бит в 1, а затем сбрасываем его в 0. Установка бита производится как простое присваивание значения регистру PORTB, как если бы это была обычная переменная.

Этот скетч способен генерировать сигнал с частотой 3,97 МГц (рис. 4.5) — почти 4 млн импульсов в секунду, что почти в 46 раз быстрее, чем с использованием digitalWrite.

Рис. 4.5. Сигнал с частотой 4 МГц, сгенерированный платой Arduino

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

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

Быстрый ввод цифровых сигналов

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

Прямой доступ к порту может пригодиться, например, когда требуется прочитать состояние сразу нескольких контактов. Следующий скетч читает все контакты, связанные с портом B (с D8 по D13), и выводит результат в монитор последовательного порта в виде двоичного числа (рис. 4.6).

Рис. 4.6. Чтение состояния сразу восьми контактов

// sketch_04_010_direct_read

byte state = 0;

void setup()

{

  DDRB = B00000000; // все контакты на ввод

  Serial.begin(9600);

}

void loop()

{

  Serial.println(PINB, 2);

  delay(1000);

}

Сбросом всех битов в регистре DDRB в 0 соответствующие контакты на плате настраиваются на работу в режиме входов. В цикле вызывается функция Serial.println, которая посылает число в монитор последовательного порта. Чтобы число посылалось в двоичной форме, а не в десятичной, как обычно, передается дополнительный аргумент 2.

Увеличение скорости ввода аналоговых сигналов

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

// sketch 04_11_analog

void setup()

{

  Serial.begin(9600);

  while (! Serial) {};

  Serial.println("Starting Test");

  long startTime = millis();

  // Далее следует код тестирования

  long  i = 0;

  for (i = 0; i < 1000000; i ++)

  {

    analogRead(A0);

  }

  // конец кода, выполняющего тестирование

  long endTime = millis();

  Serial.println("Finished Test");

  Serial.print("Seconds taken: ");

  Serial.println((endTime — startTime) / 1000l);

}

void loop()

{

}

На плате Arduino Uno этот скетч выполняется 112 с. То есть Uno выполняет в секунду около 9000 операций чтения аналоговых сигналов.

Функция analogRead использует АЦП, имеющийся в микроконтроллере на плате Arduino. В Arduino используется тип АЦП, который называют АЦП с последовательной аппроксимацией. Он действует методом постепенного приближения, сравнивая аналоговый сигнал с опорным напряжением. АЦП управляется таймером, поэтому есть возможность ускорить преобразование, увеличив частоту.

Следующий скетч увеличивает частоту АЦП со 128 кГц до 1 МГц, что должно увеличить скорость чтения в восемь раз:

// sketch 04_11_analog_fast

const

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату