Arduino:Основы/Вывод данных при помощи сдвигового регистра 74HC595
Содержание | Знакомство с Arduino | Продукты | Основы | Справочник языка Arduino | Примеры | Библиотеки | Хакинг | Изменения | Сравнение языков Arduino и Processing |
Черновик |
Вывод данных при помощи сдвигового регистра 74HC595[1]
Иногда случается, что вашему проекту не хватает контактов, которые может предложить плата Arduino, и в этом случае их количество можно увеличить при помощи сдвиговых регистров. В этой статье описывается, как использовать для этого сдвиговый регистр модели 74HC595. В даташите его полное название звучит как «8-битный сдвиговый регистр с последовательным входом, последовательным и параллельным выходом, защелкой на выходе и 3 состояниями». Другими словами, при помощи 74HC595 можно одновременно управлять 8 устройствами вывода данных, используя для этого лишь несколько контактов микроконтроллера. Более того, вы можете подсоединить к цепи не один, а несколько сдвиговых регистров – чтобы увеличить количество управляемых устройств вывода. При желании пользователь может поискать и другие светодиодные драйверы с цифрой «595» или «596» в названии (их много). К примеру, STP16С596 позволяет управлять 16 светодиодами, устраняя необходимость в использовании добавочных резисторов со встроенными источниками тока постоянной силы.
Все это работает при помощи «синхронной последовательной коммуникации» – это тип коммуникации, при котором на один из контактов подаются импульсы HIGH и LOW, что позволяет бит за битом передавать байт данных. Кроме того, в коммуникации участвует и второй контакт (его называют «тактовым контактом»), который «отстукивает» ритм, тем самым отделяя один бит от другого. По-другому построена «асинхронная последовательная коммуникация», использующаяся в функции Serial.begin() – она полагается на то, что получатель и отправитель настраиваются на указанную скорость передачи данных независимо друг от друга. Когда регистр получает байт данных, то значения HIGH и LOW, хранящиеся в каждом бите, «отщепляются» от байта и направляются к своим выходным контактам. Именно это и есть «параллельный выход» в названии 74HC595 – все контакты получают данные одновременно.
Слова «последовательный выход» в названии 74HC595 означают, что этот сдвиговый регистр имеет дополнительный контакт, позволяющий передавать информацию, полученную от микроконтроллера, дальше – к другому регистру. Это значит, что мы можем передать 16 бит (2 байта), друг за другом, и первые 8 бит пройдут сквозь первый регистр, будут переданы второму регистру и оттуда будут доставлены к нужным устройствам вывода. О том, как это сделать, написано во втором примере этой статьи.
Слова «3 состояния» в названии 74HC595 означают, что для выходных контактов можно задать 3 состояния – HIGH, LOW и «высокоимпедансное состояние». Последнее состояние отличается от HIGH и LOW тем, что вы не можете задать его для отдельных контактов. Его можно задать только для всего чипа. Это довольно специализированная функция, которая может пригодиться, к примеру, для массива светодиодов, управляемого совершенно разными микроконтроллерами в зависимости от специальных режимных настроек, встроенных в ваш проект. Ни один из примеров ниже высокоимпедансное состояние не использует, и такой чип требуется, как правило, очень редко.
Ниже – распиновка 74HC595 (с объяснениями) на основе даташита от Philips:
Контакты 1-7, 15 | Q0-Q7 | Выходные контакты |
Контакт 8 | GND | «Земля», Vss |
Контакт 9 | Q7’’ | Контакт для вывода последовательных данных |
Контакт 10 | MR | Контакт, позволяющий «очистить» значения на всех выходных контактах и выставить их на LOW (если подать на него LOW) |
Контакт 11 | SH_CP | Тактовый контакт для сдвигового регистра |
Контакт 12 | ST_CP | Тактовый контакт для регистра данных (контакт-защелка) |
Контакт 13 | OE | Контакт, разрешающий вывод данных (если подать на него LOW) |
Контакт 14 | DS | Контакт для ввода последовательных данных |
Контакт 16 | Vcc | Контакт для питания напряжением с положительным зарядом |
Пример 1: Использование одного сдвигового регистра
Сначала сдвиговый регистр нужно обеспечить питанием и включить. Для этого нужно подключить следующие контакты:
- GND (контакт 8) на регистре к «земле» на Arduino
- Vcc (контакт 16) на регистре к 5V на Arduino
- OE (контакт 13) на регистре к «земле» на Arduino
- MR (контакт 10) на регистре к 5V на Arduino
Это сделает все выходные контакты активными и всегда доступными. Впрочем, есть и один недостаток – до того, как скетч запустится, светодиоды получат значения, которые отправлялись им в самый последний раз, или даже произвольные значения. Решить эту проблему можно, выделив для OE и MR дополнительные контакты на Arduino, однако в этом случае свободных контактов на Arduino, что очевидно, станет на два меньше.
Затем к Arduino нужно подключить 3 «интерфейсных» контакта:
- DS (контакт 14) на регистре к цифровому контакту 11 на Arduino (синий провод)
- SH_CP (контакт 11) на регистре к цифровому контакту 12 на Arduino (желтый провод)
- ST_CP (контакт 12) на регистре к цифровому контакту 8 на Arduino (зеленый провод)
В скетчах эти контакты будут называться dataPin (контакт для данных), clockPin (тактовый контакт) и latchPin (контакт-защелка) соответственно. Обратите внимание, что к контакту-защелке подключен конденсатор на 0,1 фарад – он нужен для того, чтобы смягчить возможные колебания от импульсов.
Теперь подключаем светодиоды. Катод (короткая ножка) каждого светодиода подключается к общей «земле», а анод (длинная ножка) – к соответствующему выходному контакту сдвигового регистра. В результате получается, что регистр не только управляет светодиодами, но и питает их энергией, т.е. он является для них «источником тока». У некоторых регистров такой функции нет, они могут только «потребителями тока». Если вам попался именно такой регистр, то светодиоды к нему нужно подключать по-другому: аноды – к питанию, а катоды (т.е. заземляющие контакты светодиодов) – к выходным контактам сдвигового регистра. Если это чип, не принадлежащий к семейству «595», то лучше свериться с даташитом. И не забывайте про 220-омовые резисторы, чтобы защитить светодиоды от перегрузки.
Так будет выглядеть вся схема:
Код
Ниже – три скетча-примера. Первый – это «Простая передача битов», который просто выводит на светодиоды байт со значением от «0» до «255». Второй скетч одновременно зажигает все светодиоды. Третий циклами проходит по массиву.
Все эти скетчи базируются на информации из даташита – диаграмме синхронизации и таблицы с описанием логики (см. ниже). В частности, таблица с логикой объясняет, что все самое важное происходит при переходе из LOW в HIGH. В частности, когда состояние на контакте clockPin переходит из LOW в HIGH, сдвиговый регистр считывает состояние с контакта данных. Попав в сдвиговый регистр, данные сохраняются во внутреннем регистре памяти. Кроме того, когда состояние переключается из LOW в HIGH на контакте latchPin, эти данные из регистра памяти перемещаются к выходным контактам, подключенным к светодиодам.
Вот диаграмма синхронизации:
Вот таблица, описывающая логику:
ВВОД | ВЫВОД | Функция | |||||
SH_CP | ST_CP | OE | MR | DS | Q7’ | Qn | |
X | X | L | L | X | L | б.и. | Состояние LOW на MR затрагивает только сдвиговый регистр |
X | ˄ | L | L | X | L | L | Пустой сдвиговый регистр загружается в регистр памяти |
X | X | H | L | X | L | Z | Сдвиговый регистр очищается; параллельные выходы переключаются в высокоимпедансное состояние |
˄ | X | L | H | H | Q6 | б.и. | 0-ой триггер сдвигового регистра получает значение HIGH; содержимое всех триггеров сдвигового регистра движется дальше; к примеру, предыдущее значение 6-го триггера (внутренний Q6) перемещается на последовательный выход (Q7’’) |
X | ˄ | L | H | X | б.и. | Qn | Содержимое триггеров сдвигового регистра (внутренние Qn) переходит в регистр памяти и в триггеры последовательного выхода |
˄ | ˄ | L | H | X | Q6 | Qn | Содержимое сдвигового регистра перемещается дальше; предыдущее содержимое сдвигового регистра перемещается в регистр памяти и триггеры параллельного выхода |
Условные обозначения:
- H – уровень напряжения HIGH
- L – уровень напряжения LOW
- ˄ – переход от LOW к HIGH
- ˅ – переход от HIGH к LOW
- Z – высокоимпедансное состояние
- б.и. – без изменений
- X – не важно
Ниже – скетчи, которые можно использовать вместе с этой цепью:
- 1.1 – Простая передача битов
- 1.2 – Один за одним
- 1.3 – Использование массива
Пример 2: Использование нескольких сдвиговых регистров
В этом примере добавляется второй сдвиговый регистр, что позволяет удвоить количество выходных контактов, при этом используя прежнее количество контактов Arduino.
Цепь
Добавляем второй сдвиговый регистр. Его контакты GND, Vcc, OE и MR нужно подключить туда же, куда и у первого регистра.
Теперь соединяем два регистра. Два «интерфейсных» контакта второго сдвигового регистра (для тактового сигнала и «защелкивания») подключаем к тем же контактам Arduino, которые использует первый регистр (т.е. речь о контактах clockPin и latchPin) – это желтый и зеленый провода. Также добавляем дополнительный синий провод, соединяя им контакт 9 (Q7’’) на первом регистре и контакт 14 (DS) на втором регистре.
Добавляем еще 8 светодиодов. Лучше поставить зеленые, чтобы при чтении кода было ясно, какому набору светодиодов соответствует тот или иной байт.
Так будет выглядеть вся схема:
Код
Снова три скетча-примера. Если любопытно, вы можете попробовать их с цепью, построенной для первого примера – просто чтоб увидеть, что получится.
- 2.1 – Два светодиодных счетчика от «0» до «255» (в двоичном формате). Это модифицированная версия скетча «Простая передача битов» из первого примера. Вдобавок к первому она отсылает второй байт. В процессе Arduino отсылает первый байт первому сдвиговому регистру (т.е. тому регистру, к которому Arduino подключена напрямую), а он отсылает его второму сдвиговому регистру, который, в свою очередь, зажигает зеленые светодиоды. Второй байт идет к первому регистру и зажигает красные светодиоды.
- 2.2 – Поочередное зажигание 16 светодиодов. Это модификация скетча «Один за одним» из первого примера. Функция blinkAll() уступила место blinkAll_2Bytes() – чтобы наглядно продемонстрировать, что теперь нам нужно управлять 16 светодиодами. Кроме того, в первой версии этого скетча пульсирование latchPin происходило внутри функций lightShiftPinA() и lightShiftPinB(). Но сейчас эти функции вернули в главный блок loop(), чтобы их можно было запускать два раза подряд: один раз для зеленых светодиодов, и один – для красных.
- 2.3 – Использование двух массивов. Как и скетч-пример 1.3, этот пример тоже был модернизирован новой функцией blinkAll_2bytes(). Другое изменение заключается в том, что вместо одной переменной data и одного массива array мы имеем теперь dataRED, dataGREEN, dataArrayRED и dataArrayGREEN. Это также значит, что строчка...
data = dataArray[j];
...превращается в...
dataRED = dataArrayRED[j];dataGREEN = dataArrayGREEN[j];
А строчка...
shiftOut(dataPin, clockPin, data);
...превращается в...
shiftOut(dataPin, clockPin, dataGREEN); shiftOut(dataPin, clockPin, dataRED);