Рано или поздно каждый начинающий схемотехник, перейдя от простых обучающих примеров к реальным задачам задается вопросом: где же взять столько выходов микроконтроллера, сколько нужно? После подключения одного светодиода встает вопрос — а как подключить пять? десять? двадцать? Стандартных 14 выходов на Arduino Nano или даже 54 наArduino Mega легко может не хватить для решения прикладных задач. Неужели придется покупать еще один микроконтроллер, думать о синхронизации двух устройств? Конечно нет. Существует элегантное решение проблемы недостатка выводов — выходной сдвиговый регистр (например, микросхема 74HC595).
Основным параметром сдвигового регистра является битность. Она определяет, сколько выходов будет иметь регистр. Например, указанная выше микросхема — 8-ми битная, и позволит не напрягаясь подключить до 8-ми устройств используя 3 пина микроконтроллера. Экономия на лицо — 3 вместо 8. Но, конечно, есть экономные люди, которым и такой выгоды мало. Специально для них сообщаем — сдвиговые регистры могут быть подключены каскадом. Это значит, что добавлением одной микросхемы мы увеличиваем число выводов еще на 8, но не занимаем новые пины Arduino.
К минусам использования сдвигового регистра стоит отнести невозможность использования широтно-импульсной модуляции (ШИМ), потому что выходы регистра могут иметь только логические значения HIGH (1) и LOW (0). Если вы собираетесь светить светодиодами с регулировкой яркости, стоит обратить внимание на драйверы светодиодов.
Итак, как же устроена микросхема 74HC595?
Для ориентации микросхемы на нее нанесена метка в виде куга — по ней стоит искать, с какой стороны начинать отсчет пинов.
№ Пина | Обозначение | Функция |
1-7, 15 | Q1-Q7, Q0 | Цифровые выводы регистра |
8 | GND | Земля |
9 | Q7′ | Выход для подключения регистров каскадом |
10 | MR | Сброс значений регистра (при подаче сигнала LOW) |
11 | SH_CP | Вход тактовых импульсов |
12 | ST_CP | Синхронизация выходов |
13 | OE | Переключение выходов из высокоомного состояния в рабочий режим (при подаче сигнала LOW) и обратно (при подаче сигнала HIGH) |
14 | DS | Вход последовательных данных |
16 | Vcc | Питание +5V |
В исходном состоянии выводы регистра находятся в высокоомном состоянии. Это значит, что другие элементы могут изменять напряжение на них, не влияя на работоспособность и логику микросхемы. Это может быть полезно, если одними и теми же элементами планируется управлять при помощи разных регистров — когда активен один (сигнал LOW на входе OE), следует перевести второй в высокоомное состояние (сигнал HIGH на входе OE). Если регистр всего один, можно смело подключать OE к земле. Также к земле подключается выход GND.
Для нормального функционирования регистра при подключении также следует подключить вход MR к рельсе питания. Туда же подключаем Vcc.
Пины 1-7 соединены с анодами (длинными ножками) светодиодов (зеленые провода), начиная со 2-го светодиода
Пин 8 соединен с землей (синий провод)
Пин 9 ни с чем не соединен
Пин 10 соединен с +5 V (красный провод)
Пин 11 соединен с 4-м пином Arduino (черный провод)
Пин 12 соединен с 3-м пином Arduino (еще один черный провод). Также пин 12 соединен с землей через конденсатор 0.1 мкФ (желтый провод)
Пин 13 соединен с землей (синий провод)
Пин 14 соединен с 2-м пином Arduino (черный провод)
Пин 15 соединен с анодом (длинная ножка) первого светодиода (зеленый провод)
Пин 16 соединен +5 V (красный провод)
Непосредственно управление регистром осуществляется с помощью входов DS, SH_CP и ST_CP. Когда происходит переключение SH_CP с LOW на HIGH, в регистр считывается значение с DS (1 бит). При переключении ST_CP с LOW на HIGH заканчивается прием информации и выводы переходят в назначенное состояние. Впрочем, не обязательно так досконально разбираться в логике работы регистра — для Arduino уже конечно же есть специальные библиотеки — необходимо только подключить эти входы к цифровым выходам Arduino.
Обратите внимание — подача импульсов на вход микросхемы является высокочастотной, и для фильтрации желательно поставить конденсатор малой емкости (0.1 мкФ) на вход ST_CP для минимизации помех на схеме при подаче закрывающего сигнала. В схеме также использованы светодиоды в качестве нагрузки и резисторы 220 Ом для ограничения тока.
В качестве примера будем управлять восемью светодиодами. Проверьте правильность подключения элементов и загрузите в Arduino следующий скетч:
//Пин SH_CP int SH_CP = 4; //Пин ST_CP int ST_CP = 3; //Пин DS int DS = 2; void setup() { // Настраиваем выходы SH_CP, ST_CP, DS pinMode(SH_CP, OUTPUT); pinMode(ST_CP, OUTPUT); pinMode(DS, OUTPUT); } void loop() { for (int i = 0; i < 256; i++) { // Инициализируем начало приема данных digitalWrite(ST_CP, LOW); // Последовательная передача данных на пин DS shiftOut(DS, SH_CP, MSBFIRST, i); // Инициализируем окончание передачи данных. // Регистр подаст напряжение на указанные выходы digitalWrite(ST_CP, HIGH); // Задержка 0.5 секунды delay(500); } }
Рассмотрим пример подробнее. Вас должна заинтересовать функция shiftOut — именно она управляет передачей данных в регистр. У этой функции всего четыре параметра. Первые два — пин, по которому передаются данные (подключенный ко входу DS) и пин тактовых импульсов (подключенный ко входу SH_CP). Третий параметр определяет параметр передачи битов в регистр: MSBFIRST — прямой порядок, начиная со старшего (первого) бита; MSBLAST — обратный порядок, начиная с младшего (последнего бита). И, наконец, четвертый параметр — непосредственно значение, которое должно быть передано в регистр. В данном случае мы передаем значение от 0 до 255 (2 в степени 8 — вы же не забыли что регистр 8-ми битный?). С практической точки зрения, когда нужно активировать определенные выходы, можно использовать битовые представления чисел, например:
// Загорится первый светодиод shiftOut(DS, SH_CP, MSBFIRST, 0b10000000); // Загорятся 2, 4, 6, 8 светодиоды shiftOut(DS, SH_CP, MSBFIRST, 0b01010101); // Загорится первый светодиод - порядок передачи битов обратный shiftOut(DS, SH_CP, MSBLAST, 0b00000001);
Итак, нам удалось разобраться с одним сдвиговым регистром. Но пытливый читатель конечно же воскликнет — а как же два и более регистров? Вы же обещали подключение каскадом и беспрецедентную экономию пинов Arduino! Конечно, конечно — вот новая схема подключения. Обратите внимание, что изменений не так много — просто два регистра соединены между собой по пинам Q7′ — DS. Второй конденсатор подключать не нужно.
Подключение первого регистра не изменилось, за исключением того, что пин 9 соединен с пином 14 второго регистра (оранжевый провод). Подключение второго регистра полностью идентично подключению первого регистра (за исключением отсутствия конденсатора и уже упомянутого пина 14).
Загрузим скетч для последовательного зажигания всех 16 светодиодов:
//Пин SH_CP int SH_CP = 4; //Пин ST_CP int ST_CP = 3; //Пин DS int DS = 2; void setup() { // Настраиваем выходы SH_CP, ST_CP, DS pinMode(SH_CP, OUTPUT); pinMode(ST_CP, OUTPUT); pinMode(DS, OUTPUT); } void loop() { // Цикл обхода 16 светодиодов for (int i = 0; i < 16; i++) { // Запись в регистр registerWrite(i, HIGH); // Задержка 0.5 с. delay(500); // Отключение предыдущего светодиода if (i > 0) { registerWrite(i - 1, LOW); } // Отключение последнего светодиода // ("предыдущий" для первого" else { registerWrite(15, LOW); } } } // Метод для отсылки данных в регистры void registerWrite(int num, int state) { // Для хранения 16 битов используется unsigned int unsigned int bitsToSend = 0; // 0b000000000000000 // Инициализируем начало приема данных digitalWrite(ST_CP, LOW); // Устанавливаем 1 в соответствующий бит bitWrite(bitsToSend, num, state); // 16 бит необходимо разделить на два байта: // И записать каждый байт в соответствующий регистр byte register1 = highByte(bitsToSend); byte register2 = lowByte(bitsToSend); // Последовательная передача данных на пин DS shiftOut(DS, SH_CP, MSBFIRST, register2); shiftOut(DS, SH_CP, MSBFIRST, register1); // Инициализируем окончание передачи данных. // Регистры подадут напряжение на указанные выходы digitalWrite(ST_CP, HIGH); }
Обратите внимание на функции, которые сильно облегчат работу со сдвиговыми регистрами: bitWrite пишет указанный бит в заданную позицию числа, а highByte и lowByte берут соответственно старший (левые 8 бит) и младший (правые 8 бит) байты из переданного числа.
Итак, мы подключили еще 8 светодиодов (16 в итоге), по-прежнему использовав всего 3 вывода Arduino. Мы восхитительны!