- Что такое сдвиговый регистр
- Преимущества использования сдвигового регистра 74HC595:
- Как работает регистр сдвига?
- 74hc595 datasheet характеристики
- Подключение сдвигового регистра74HC595 к Arduino
- Как подключить семисегментный индикатор к 74HC595
- Тестовый скетч для изучения работы регистра сдвига
- Скетч подключение светодиодов к 74HC595 регистру
- Анимация светодиодов
- Временная диаграмма работы микросхемы 74HC595
- Подключение нескольких регистров сдвига к Arduino
Что такое сдвиговый регистр
В электронике регистром называют устройство, которое может хранить небольшой объем данных для быстрого доступа к ним. Они есть внутри каждого контроллера и микропроцессора, включая и микроконтроллер Atmega328, который входит в состав платы Arduino Uno. Как правило регистры представляют собой сборку из D-триггеров — элементарных ячеек памяти. Записывать данные в регистр можно либо последовательно, либо параллельно. Регистры первого типа называются сдвиговыми, второго типа — параллельными.
Считывать данные из регистра можно одновременно из всех ячеек. Именно это его свойство помогает нам работать с кучей светодиодов.
Регистр называется сдвиговым, потому что при добавлении каждого нового бита в него, мы как бы сдвигаем все остальные в сторону. Вспомним, что один бит позволяет нам хранить ноль или единицу, истину или ложь. Посмотрим на диаграмме, как это происходит.
Пусть в начальном состоянии регистр уже заполнен какими-то восемью битами. Попробуем «задвинуть» в него восемь новых бит: 11011010.
Как видно, после двух итераций, в начале регистра оказалось два новых бита, а два бита в последних ячейках «вывалились» через край и пропали. На восьмом шаге весь регистр оказался заполнен новыми битами.
Регистры можно соединять в цепочку. В таком случае, вытесненный бит не будет пропадать без следа, а отправится в начало следующего регистра. При этом увеличивается число доступных выводов.
Преимущества использования сдвигового регистра 74HC595:
- не требует никакой обвязки кроме конденсатора по питанию;
- работает через широкораспостраненный интерфейс SPI;
- для самого простого включения достаточно двух выходов микроконтроллера;
- возможность практически неограниченного расширения количества выходов без увеличения занятых выходов микроконтроллера;
- частота работы до 100 МГц;
- напряжение питания от 2 В до 6 В;
- дешевый — стоит менее 5 центов;
- выпускается как в планарных корпусах (74HC595D удобен для производства), так и в DIP16 (74HC595N удобен для радиолюбителей и макетирования).
Для понимания работы регистра стоит взглянуть на функциональную схему. Она состоит из:
- 8-битного регистра сдвига,
- 8-битного регистра хранения,
- 8-битного выходного регистра.
Рассмотрим какие выводы есть у сдвигового регистра 74hc595.
Общего вывод и вывод питания объяснений не требуют.
- GND — земля
- VCC — питание 5 вольт
Как работает регистр сдвига?
Прежде чем мы начнем подключать чип, давайте рассмотрим, как этот процесс работает.
Первое, что нужно прояснить, – это понятие «биты» для тех из вас, кто не знаком с двоичным кодом. Когда мы говорим о «битах», мы имеем в виду одно из чисел, составляющих двоичное значение. В отличие от обычных чисел, мы обычно считаем, что первый бит является самым большим. Итак, если мы берем двоичное значение 10100010, первый бит на самом деле равен 0, а восьмой бит равен 1. Следует также отметить, если это не подразумевалось, каждый бит может быть только 0 или 1.
Чип содержит восемь контактов, которые мы можем использовать для вывода, каждый из которых связан с битом в регистре. В случае сдвигового регистра 74HC595 мы рассматриваем их от QA до QH.
Чтобы записать эти выходы через Arduino, мы должны отправить двоичное значение в регистр сдвига, и из этого числа сдвиговый регистр может определить, какие выходы использовать. Например, если мы отправили двоичное значение 10100010, контакты, выделенные зеленым цветом на изображении выше, будут активными, а выделенные красным цветом будут неактивными.
Это означает, что самый правый бит сопоставляется как QH, а левый бит сопоставляется с QA. Выход считается активным, когда бит, сопоставленный с ним, установлен на 1. Важно помнить об этом, так как иначе вам будет очень сложно узнать, какие контакты вы используете.
Теперь, когда у нас есть основное понимание того, как мы используем смещение битов, чтобы указать, какие контакты использовать, мы можем начать подключать его к нашему Arduino.
74hc595 datasheet характеристики
- Напряжение питания — 5 В
- Ток потребления — 40 мА
- Разрядность параллельного входа (выхода) — 8 бит
- Количество сигнальных линий для передачи данных — 3
- Время установки — 20 нс
- Максимальная частота — 100 МГц
- Диапазон температур от -40 до +85C°
Когда мы пошлем байт: 00011000 на 74hc595d, он изменит состояние (HIGH или LOW) своих выходов. Затем мы увидим, что если к каждому контакту подключен светодиод, то 2 «средних» светодиода (географически говоря) по отношению к соседним LED будут находиться в противоположном состоянии. Таким образом, используя только три цифровых выхода на Arduino, вы можете задействовать 8 цифровых выходов на регистре.
Подключение сдвигового регистра74HC595 к Arduino
Давайте соберём схему, которая показана на рисунке.
Схема подключения сдвигового регистра 74HC595 к Arduino
Вот таблица подключений:
Вывод свдигового регистра 74HC595Вывод Arduino
VCC | 5V |
GND | GND |
DS | 11 (MOSI) |
STCP | 10 (CS) |
SHCP | 13 (SCK) |
Q7′ | 12 (MISO) |
OE# | GND |
MR# | 5V |
Вывод OE# подключим к земле, чтобы разрешение на вывод данных было всегда активно. А вывод MR# подключим к питанию, таким образом заблокируем случайный сброс устройства.
На монтажной плате 8-штырьковый разъём типа PLS – это выход, с которого будем снимать параллельные данные сдвигового регистра.
Я также подключу ко всем ножкам микросхемы регистра сдвига логический анализатор. С помощью него мы увидим, что же происходит на физическом уровне, какие сигналы куда идут, и разберёмся, что они означают. У меня получилось так, как показано на фотографии.
Подключение сдвигового регистра 74HC595 к Arduino
Как подключить семисегментный индикатор к 74HC595
В следующем примере мы подключим к регистру 74HC595 семисегментный индикатор на светодиодах. Регистр сдвига для Ардуино не только упрощает сборку схемы, но и делает программу намного проще. После сборки схемы, изображенной на рисунке выше, загрузите программу для микроконтроллера. Скетч выводит на светодиодном индикаторе цифры от нуля до пяти. Для вас не составит огромного труда продолжить программу.
Тестовый скетч для изучения работы регистра сдвига
Напишем вот такой скетч и загрузим в память Arduino. Здесь мы по циклу будем записывать два числа – 210 и 0 – в сдвиговый регистр с небольшими временными интервалами между ними. Да, только и всего.
Скетч записи данных в сдвиговый регистр (разворачивается)#include // подключаем библиотеку SPI void setup() { SPI.begin(); // инициализируем SPI pinMode(PIN_SPI_SS, OUTPUT); } void loop() { digitalWrite(PIN_SPI_SS, LOW); // выбор регистра сдвига SPI.transfer(210); // передаём число “210” в сдвиговый регистр digitalWrite(PIN_SPI_SS, HIGH); // конец передачи delay(10); // задержка 10 мсек digitalWrite(PIN_SPI_SS, LOW); SPI.transfer(0); digitalWrite(PIN_SPI_SS, HIGH); delay(90); }
PIN_SPI_SS – это внутренняя стандартная константа, которая соответствует выводу “10” Ардуино в режиме SPI. Данная константа определена в файле pins_arduino.h, который находится по пути %programfiles%arduino-(версия)hardwarearduinoavrvariants Также там определены константы PIN_SPI_MOSI (пин 11), PIN_SPI_MISO (пин 12), PIN_SPI_SCK (пин 13). В ранних версиях Arduino IDE (например, 1.6.хх) этих констант не было.
В принципе, мы могли бы с таким же успехом использовать любой другой цифровой вывод Arduino; тогда пришлось бы в программе объявить его и не забыть задать режим работы – OUTPUT.
Подавая на этот вывод LOW, мы активируем наш сдвиговый регистр на приём/передачу. После передачи мы снова поднимаем напряжение в HIGH, и обмен заканчивается. Включим схему в работу и посмотрим, что покажет логический анализатор.
Скетч подключение светодиодов к 74HC595 регистру
#define dataPin 10 #define latchPin 11 #define clockPin 12 byte byteToSend = 0; void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); digitalWrite(latchPin, HIGH); } void loop() { for (byte bitPos = 0; bitPos < 8; bitPos++) { byteToSend = 0; bitWrite(byteToSend, bitPos, HIGH); digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, byteToSend); digitalWrite(latchPin, HIGH); delay(100); } for (byte bitPos = 0; bitPos < 8; bitPos++) { byteToSend = 0; bitWrite(byteToSend, bitPos, HIGH); digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, byteToSend); digitalWrite(latchPin, HIGH); delay(100); } }
Анимация светодиодов
Другой скетч.
int dataPin = 9; // к выводу 14 регистра int clockPin = 11; // к выводу 11 регистра (SH_CP) int latchPin = 12; // к выводу 12 регистра (ST_CP) byte path[4] = { B11000011, B00111100, B00100100, B00011000 }; void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void loop() { for (int i = 0; i < 4; i++) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, path[i]); digitalWrite(latchPin, HIGH); delay(250); } for (int i = 0; i < 4; i++) { digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, path[3 – i]); digitalWrite(latchPin, HIGH); delay(250); } }
В path[] мы указываем последовательность включённых и выключенных светодиодов. Между этими последовательностями будет происходит анимация.
Для анимации бегущих огней можно реализовать задачу через функцию bitWrite().
int dataPin = 9; // к выводу 14 регистра int clockPin = 11; // к выводу 11 регистра (SH_CP) int latchPin = 12; // к выводу 12 регистра (ST_CP) void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); } void loop() { byte byteToSend = 0; //Создаем пустой байт B00000000 for (int bitPos = 0; bitPos < 8; bitPos++) { // В переменной хранится позиция изменяемого бита byteToSend = 0; // Обнуляем байт при каждом проходе bitWrite(byteToSend, bitPos, HIGH); // При bitPos=0 получим B00000001, при bitPos=1 – B00000010, при bitPos=2 – B00000100 и т.д. digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, MSBFIRST, byteToSend); // Инвертируем сигнал при помощи MSBFIRST, грузим с первого бита digitalWrite(latchPin, HIGH); delay(50); } }
Код попроще, чтобы лучше понять происходящее.
int dataPin = 9; // к выводу 14 регистра int clockPin = 11; // к выводу 11 регистра (SH_CP) int latchPin = 12; // к выводу 12 регистра (ST_CP) byte leds = 0; int currendLed = 0; void setup() { pinMode(latchPin, OUTPUT); pinMode(clockPin, OUTPUT); pinMode(dataPin, OUTPUT); leds = 0; } void loop() { leds = 0; if (currendLed == 7) { currendLed = 0; } else { currendLed++; } bitSet(leds, currendLed); digitalWrite(latchPin, LOW); shiftOut(dataPin, clockPin, LSBFIRST, leds); digitalWrite(latchPin, HIGH); delay(250); }
В методе setup() мы просто инициализируем режимы выводов и переменную светодиодов.
В методе loop() очищаем биты в переменной leds в начале каждой итерации, так что все биты устанавливаются в 0, так как мы хотим только включать один светодиод за раз. После этого мы увеличиваем или перезапускаем текущую переменную currentLed, чтобы затем опять включать правильный светодиод.
После этих двух операций мы переходим к смещению бит. Начинаем с вызова метода bitSet(), которому передаём байт, что хранит биты, и переменную currentLed.
Этот метод позволяет нам установить отдельные биты байта, указав их положение. Например, если мы хотим вручную установить байт в 10010, мы могли бы использовать следующие вызовы, поскольку биты, которые нам нужно установить в 1, являются вторыми справа (это позиция 1, когда мы начинаем в позиции 0) и пятый справа, который находится в положении 4:
bitSet(leds, 1); bitSet(leds, 4);
Таким образом, каждый раз, когда мы увеличиваем текущую переменную currentLed и передаем ее методу bitSet(), мы каждый раз устанавливаем бит слева от предыдущего до 1 и, таким образом сообщаем сдвиговому регистру активировать вывод слева от предыдущего.
После установки бит мы записываем на контакт защёлки указание сдвиговому регистру, что собираемся отправить ему данные. Как только мы это сделаем, мы вызываем метод shiftOut(). Метод позволяет сдвигать биты за один вызов. Для этого мы передаём данные и синхронизацию в качестве первых двух параметров, затем передаём константу LSBFIRST, которая сообщает методу, что первый бит должен быть наименее значимым, а затем мы проходим через байт, содержащий биты, которые мы действительно хотим перенести в регистр сдвига.
Как только мы закончим смещение битов, мы снова обращаемся на контакт защёлки (используя HIGH в этот раз), чтобы указать, что мы отправили все данные. После того, как операция записи будет завершена, загорится соответствующий светодиодный индикатор, а затем задержится на 250 миллисекунд, прежде чем всё повторится.
Временная диаграмма работы микросхемы 74HC595
Общий вид временной диаграммы – на рисунке. Голубой пунктирной линией показаны 4 линии SPI, красной пунктирной – 8 каналов параллельных данных регистра сдвига. Точка A на шкале времени – это момент передачи в регистр сдвига числа “210”, B – момент записи числа “0”, C – завершение текущей итерации цикла и начало новой.
Временная диаграмма работы микросхемы 74HC595
Как видно, от А до B – 10,03 миллисекунд, а от B до С – 90,12 миллисекунд, почти как мы и задали в скетче. Небольшая добавка в 0,03 и 0,12 мс – время передачи последовательных данных от Arduino, поэтому мы тут имеем не ровно 10 и 90 мс.
Рассмотрим подробнее участок A.
Обратите внимание на временной масштаб. Теперь это микросекунды, а на предыдущем были миллисекунды. То есть это сильно укрупнённый по сравнению с первой диаграммой участок.
Диаграмма передачи числа “11010010” по SPI
В первом канале сверху – длинный импульс с нулевым уровнем, которым Arduino инициализирует передачу по линии SPI – ENABLE – выбор ведомого. В это время начинают генерироваться тактовые импульсы SPI – CLOCK (см. второй сверху канал). Для передачи одного байта генерируется 8 тактовых импульсов.
Третий канал сверху – SPI – MOSI – данные, которые мы передаём от Arduino к сдвиговому регистру. Это наше число “210” в двоичном виде – “1101 0010”.
После завершения передачи линия SPI – ENABLE поднимается в высокое состояние, и мы видим, что сдвиговый регистр выставил на своих 8-ми ножках значение “1101 0010”. Я выделил это голубой пунктирной линией и подписал значения для наглядности.
Теперь обратим внимание на участок B.
Диаграмма передачи числа “00000000” по SPI
Опять всё начинается с выбора ведомого и генерирования 8-ми тактовых импульсов (первый и второй каналы сверху). Данные на линии SPI – MOSI теперь – “0000 0000” (3-ий сверху канал). То есть мы записываем в этот момент в регистр число “0”. Но пока передача не закончена, в регистре по прежнему хранится значение “1101 0010”, которое мы выставили ранее. Оно выводится на параллельные выводы Q0..Q7 (8 нижних каналов на рисунке), а также, при наличии тактовых импульсов в линии SPI – CLOCK, выдаётся в линию SPI – MISO (см. 4-ый канал сверху) c последовательного выхода регистра Q7′, что мы тут и видим.
Подключение нескольких регистров сдвига к Arduino
Если подключить несколько сдвиговых регистров таким образом, чтобы линии CLOCK (SCLK на рисунке ниже), MOSI и MISO у них были общие, а ENABLE (SS на рисунке) каждой микросхемы подключались к разным цифровым выводам Arduino, то можно независимо обращаться к каждому из сдвиговых регистров, активизируя низким уровнем соответствующий из них, и записывать в регистры данные и считывать из них данные. Такое подключение называется независимым.
Независимый и каскадный типы подключений по интерфейсу SPI
Независимое подключение ведомых SPI устройств (например, регистров 74HC595) к ведущему (например, Arduino) изображено на левой части рисунка. Думаю, это уже достаточно просто для нас, так как оно почти ничем не отличается от подключения одного сдвигового регистра. Поэтому давайте рассмотрим другой тип подключения – каскадный.
- https://developer.alexanderklimov.ru/arduino/shiftregister.php
- https://hardelectronics.ru/74hc595.html
- https://ArduinoPlus.ru/74hc595-arduino/
- https://arduino-site.ru/sdvigovyj-registr/
- https://soltau.ru/index.php/arduino/item/458-kak-podklyuchit-sdvigovyj-registr-74hc595-k-arduino
Как вам статья?