7.2. Последовательная и параллельная передача данных
Существуют два способа передачи нескольких битов данных. Напомним, что Arduino, как и все микроконтроллеры, представляет собой цифровое устройство, т. е. "понимает" только "0" и "1". Если вы хотите управлять восьмью светодиодами, необходимо передать 8 бит информации. Ранее мы это делали в параллельном режиме с помощью функций digitalWrite() и analogWrite(). В качестве примера параллельной передачи данных, предположим, что нам необходимо включить 8 светодиодов, подключенных к 8 цифровым выходам. При этом все биты будут переданы на цифровые контакты примерно в одно время. В главе 6 была описана последовательная передача данных, при которой за фиксированный интервал времени передается 1 бит данных. Сдвиговые регистры позволяют легко конвертировать последовательные и параллельные методы передачи данных. Эта глава посвящена регистрам последовательно-параллельного сдвига (SIPO), которые называют просто регистрами сдвига. С их помощью можно принимать данные последовательно, а выводить параллельно на выходы регистра. Кроме того, можно каскадировать сдвиговые регистры и управлять множеством цифровых выходов, используя всего три контакта Arduino.
7.3. Сдвиговый регистр 7 4НС595
В качестве сдвигового регистра мы будем применять микросхему 74НС595, цоколевка которой изображена на рис. 7.2.

Рис. 7.2. Цоколевка микросхемы 74НС595
7.3.1. Назначение контактов сдвигового регистра
Назначение контактов сдвигового регистра:
• QA - QH - восемь параллельных выходов сдвигового регистра;
• GND - соединяется с земляной шиной платы Arduino;
- 156 -
• SER - это вход данных (DA ТА на рис. 7.1 ). По этому входу передаются 8 последовательных битов данных для установки значений на параллельных выходах;
• SRCLK- это тактовый вход (CLOCK на рис. 7.1). При подаче импульса высокого напряжения HIGH на этот вход происходит считывание одного бита данных с входа DA ТА в сдвиговый регистр. Для получения всех 8 битов данных необходимо подать 8 импульсов на этот контакт;
• RCLK - это вход (LA ТСН на рис. 7.1) называется также защелкой и служит для одновременного вывода последовательных данных на параллельные выходы.
Выводы SRCLR и ОЕ не используются в примерах из книги, но они могут пригодиться вам в других проектах, поэтому посмотрим, каково их назначение. ОЕ разрешение вывода данных на параллельные выходы. Черта сверху означает, что активный уровень для этого входа - низкий. Когда на этом входе низкий уровень, параллельные выходы будут включены, когда высокий - выключены. В наших примерах контакт ОЕ подключен к земле, поэтому параллельные выходы постояо находятся во включенном состоянии. Вы можете соединить его с контактом ввода-вывода Arduino, чтобы одновременно включать или выключать все светодиоды. SRCLR - это вход сброса. Подача на него напряжения низкого уровня очищает содержимое регистра сдвига. В наших примерах он подключен к шине 5 В, чтобы предотвратить очистку сдвигового регистра.
7.3.2. Принцип действия сдвиговых регистров
Регистр сдвига является синхронным устройством, он принимает данные по нарастающему фронту тактового сигнала. Каждый раз, когда сигнал на входе CLOCK меняется с низкого на высокий, все значения, хранящиеся в восьми выходных ячейках, смещаются на одну позицию. Данные из последней ячейки либо сбрасываются, либо передаются на выход QH' (при каскадном подключении микросхемы 74НС595). Одновременно последовательные данные на входе DATA сдвигаются на одну позицию. За восемь тактов предыдущие значения в ячейках регистра уходят, а новые загружаются. Подача высокого уровня на вход LATCH выводит значения, хранящиеся в ячейках, на выходы регистра. Этот процесс проиллюстрирован на рис. 7.3.
Предположим, вы хотите включить некоторые из светодиодов, подключенных к параллельным выходам сдвигового регистра, например к выходам QA, QC, QE, QG. В двоичном представлении на параллельных выходах должно быть значение 10101010. Теперь посмотрим, как действует регистр. Установим низкий уровень на входе LATCH, чтобы значения на параллельных выходах не изменялись во время загрузки новых данных в ячейки регистра. Затем, подавая импульсы на вход CLOCK, значения на входе DATA загружаем и сдвигаем по ячейкам. После загрузки в регистр всей последовательности данных, устанавливаем на входе LATCH высокий уровень для вывода значений из ячеек на параллельные выходы.
- 157 -

Рис. 7.3. Перемещение данных по сдвиговому регистру
- 158 -
7.3.3. Передача данных из Arduino
в сдвиговый регистр
Теперь можно написать программу для передачи данных из Arduino в сдвиговые регистры. Воспользуемся встроенной в Arduino IDE функцией shiftOut() для поразрядной выдачи данных на контакт платы Arduino. Эта функция принимает четыре аргумента:
• номер контакта DATA;
• номер контакта CLOCK;
• порядок выдачи битов;
• значение, выдаваемое на выход.
Например, если вы хотите зажечь светодиоды как в предыдущем примере, можно вызвать функцию shiftout() следующим образом:
shiftOut(DATA, CLOCK, MSBFIRST, 810101010);
Константы DATA и с1оск - номера контактов Arduino для передачи данных. Аргумент MSBFIRST показывает, что самый старший бит (крайний слева бит в двоичном числе) будет отправлен первым. Можно передавать данные с параметром LSBFIRST, который начнет передачу с младшего бита. Последний параметр - это передаваемые данные. Знак в перед числом указывает Arduino IDE, что данные представлены в двоичном виде.
Теперь соберем схему устройства. Подключим регистр сдвига к плате Arduino следующим образом: вывод DATA к контакту 8 платы, LATCH к контакту 9, CLOCK к контакту 10.
Не забывайте, что светодиоды нужно подключать через токоограничительные резисторы (220 Ом). При монтаже сверяйтесь с рис. 7.4.
Теперь, зная как работают сдвиговые регистры и используя встроенную в Arduino IDE функцию shiftOut(), мы можем написать программу управления светодиодами (листинг 7.1).
Листинг 7.1. Программа управления светодиодами с помощью сдвигового регистра - alternate.ino
const int SER=8; // Контакт для подключения вывода DATA
const int LATCH =9;// Контакт для подключения вывода LATCH
const int CLK =10; // Контакт для подключения вывода CLOCK
void setup()
{
// Установить контакты на вывод (OUTPUT}
pinMode(SER, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(CLK, OUTPUT);
- 159 -
digitalWrite(LATCH, LOW);// LATCH - низкий
shiftOut(SER, CLK, MSBFIRST, 810101010); // Старший бит - первый
digitalWrite(LATCH, HIGH);// LATCH - высокий
}
void loop() {; }

Рис. 7.4. Подключение 8 светодиодов к сдвиговому регистру
Поскольку регистр сдвига фиксирует полученные данные, отправляем их только один раз в функции setup(). Полученные значения хранятся до следующего изменения. Эта программа выполняет те же шаги, что показаны на рис. 7.3. На выводе
- 160 -
LATCH устанавливается низкий уровень, восемь битов данных передаются функцией shiftOut() в ячейки, а затем на LATCH подается высокий уровень, чтобы вывести значения из ячеек на параллельные выходы регистра.
Как видим, нам удалось получить восемь цифровых выходов из трех портов ввода-вывода. Уже неплохо. Но что делать, если нужно еще больше? Это возможно! Последовательно подключая несколько сдвиговых регистров, теоретически можно добавить сотни цифровых выходов, задействуя только три контакта Arduino. Но в таком случае потребуется внешнее питание. Посмотрите на рис. 7.2, там есть неиспользованный контакт QH'. Когда значения смещаются по ячейкам, они на самом деле не отбрасываются, а поступают на вывод QH'. Подключив выход QH' к входу DA ТА другого сдвигового регистра, а также соединив выводы LATCH и CLOCK
обоих регистров, можно создать 16-разрядный регистр сдвига, который управляет 16 выводами. Добавляя все больше и больше регистров сдвига, каждый из которых подсоединен к предыдущему, вы получите сколь угодно много выводов из платы Arduino.
Можете попробовать подключить еще один регистр сдвига и дважды вызвать функцию shiftout() (за один раз функция shiftOut() может обрабатывать только 8 разрядов данных).
7.3.4. Преобразование между двоичным и десятичным форматами
В листинге 7.1 данные для включения светодиодов передавались в виде двоичной строки. Это позволяет наглядно отобразить включенные и выключенные светодиоды. Тем не менее, данные можно записать в десятичном виде, преобразовав их из двоичного (base2) в десятичный (base 1 0) формат. Каждый разряд двоичного числа (начиная с младшего, самого правого) представляет следующую степень числа 2.
Преобразовать двоичное представление числа в десятичное очень просто. Рассмотрим этапы преобразования двоичного кода в десятичный (рис. 7.5).

Рис. 7.5. Преобразование двоичного числа в десятичное
Двоичное значение каждого бита представляет собой увеличивающуюся степень числа 2. В нашем случае биты 7, 5, 3, 1 установлены в единицу. Таким образом, чтобы найти десятичный эквивалент, вы складываете 2 7, 2 5, 2 3 и i. Полученное десятичное значение равно 170. Можно доказать, что это эквивалентно, подставив десятичное значение в код из листинга 7.1.
Замените строку с shiftout() на следющую:
shiftOut(DATA, CLOCK, MSBFIRST, 170);
и убедитесь, что результат будет таким же, как и для двоичного представления.
-161 -
7.4. Создание световых эффектов с помощью СДВИГОВОГО регистра
В предыдущем примере мы создали с помощью регистра сдвига и светодиодов неподвижное изображение. Гораздо интереснее отображать динамичную информацию. В следующих примерах используем сдвиговые регистры для создания анимационных эффектов "бегущего всадника" и "гистограммы".
7.4.1. Эффект "бегущий всадник"
"Бегущий всадник" - анимационный эффект, когда горящий светодиод сначала движется в одну сторону, а затем в обратную. Соберем схему из предыдущего примера. С помощью функции shiftout() можно очень быстро обновлять данные в ячейках сдвигового регистра, чтобы создавать динамичные световые анимации.
В нащем примере необходимо зажигать по одному светодиоду сначала слева направо, затем справа налево. На временной диаграмме (рис. 7.6) показано, как светодиоды будут гореть на каждом шаге, и приведены десятичные значения для включения конкретной комбинации светодиодов.
В программе передаем функции shiftout() десятичные значения комбинаций светодиодов. В цикле выбираем значение из массива и отправляем в сдвиговый регистр. Код программы приведен в листинге 7.2.
0000000* | 1 | t=1
000000*0 | 2 | t=2
00000*00 | 4 | t=3
0000*000 | 8 | t=4
000*0000 | 16 | t=5
0*000000 | 64 | t=7
*0000000 | 128 | t=8
0*000000 | 64 | t=9
00*00000 | 32 | t=10
000*0000 | 16 | t=11
0000*000 | 8 | t=12
00000*00 | 4 | t=13
000000*0 | 2 | t=14
Рис. 7.6. Пошаговое представление эффекта "бегущий всадник"
- 162 -
Листинг 7.2. Световой эффект "бегущий всадник" - lightrider.ino
// Создание световой анимации "бегущий всадник"
const int SER=8;// Контакт для подключения вывода DATA
const int LATCH =9;// Контакт для подключения вывода LATCH
const int CLK =10;// Контакт для подключения вывода CLOCK
// Последовательность включения светодиодов
int seq[14] = {1,2,4,8,16,32,64,128,64,32,16,8,4,2};
void setup()
{
// Установить контакты на вывод (OUTPUT)
pinMode(SER, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(CLK, OUTPUT);
}
void loop()
{
for (int i = 0; i < 14; i++)
{
digitalWrite(LATCH, LOW);// LATCH - низкий
shiftOut(SER, CLK, MSBFIRST, seq[i]); // Старший бит - первый
digitalWrite(LATCH, HIGH);// LATCH - высокий
delay(100);// Скорость анимации
}
}
Регулируя величину задержки, можно менять скорость анимации. Попробуйте изменить значения в массиве последовательностей, чтобы получить различные комбинации включения светодиодов.
ПРИМЕЧАНИЕ
Для просмотра демонстрационного видеоклипа программы lightrider зайдите по адресу http://www.exploringarduino.com/content/ch7. Видеоклип также доступен на сайте издательства Wiley.
7.4.2. Отображение данных в виде гистограммы добавив ИК-датчик расстояния в предыдущую схему, можно создать светящуюся гистограмму, которая показывает, насколько близко вы находитесь. Для большей наглядности возьмите несколько светодиодов разного цвета. Принципиальная схема устройства с разноцветными светодиодами и ИК-датчиком расстояния приведена на рис. 7.7.
- 163 -

Рис. 7.7. Схема устройства, реализующего эффект "гистограммы расстояния"
Зная принцип действия аналогового датчика и регистра сдвига, вы в состоянии самостоятельно выбрать пороги расстояния и соответствующие им комбинации включенных и выключенных светодиодов (рис. 7.8).
Из главы 3 ясно, что диапазон используемых значений для ИК-датчика расстояния не должен превышать 10 бит (у меня максимальное значение оказалось равно 500, у вас оно возможно отличается). Лучше всего самостоятельно проверить дальность действия датчика и уточнить соответствующие значения. Все десятичные комбинации гистограммы хранятся в массиве из девяти элементов. Ограничиваем максимальное расстояние и приводим значения к диапазону от 0 до 8. Листинг 7.3 иллюстрирует программную реализацию эффекта гистограммы.
Листинг 7.3 Гистограмма отображения расстояния - bargraph.ino
// Гистограмма расстояния
const int SER=8;// Контакт для подключения вывода DATA
const int LATCH =9; // Контакт для подключения вывода LATCH
- 164 -
const int CLK =10;// Контакт для подключения вывода CLOCK
const int DIST =0;// Контакт для подключения датчика расстояния
// Возможные значения светодиодов
int vals[9] = {0,1,3,7,15,31,63,127,255};
// Максимальное значение расстояния
int maxVal = 500;
// Минимальное значение расстояния
int minVal = 0;
void setup()
{
// Установить контакты на вывод (OUTPUT)
pinMode(SER, OUTPUT);
pinMode(LATCH, OUTPUT);
pinMode(CLK, OUTPUT);
}
void loop()
{
int distance = analogRead(DIST);
distance = map(distance, minVal, maxVal, 0, 8);
distance = constrain(distance,0,8);
digitalWrite(LATCH, LOW);// LATCH - низкий - начало отправки
shiftOut(SER, CLK, MSBFIRST, vals[distance]); // Старший бит - первый
digitalWrite(LATCH, HIGH);// LATCH - высокий
delay (10);// Скорость анимации
}

Рис. 7.8. Комбинации включенных и выключенных светодиодов и соответствующие им десятичные значения
- 165 -
Загрузите программу на плату Arduino, запустите на выполнение и перемещайте руку вперед-назад перед датчиком расстояния. Вы должны увидеть, что гистограмма реагирует на движение руки. Если устройство работает неправильно, отрегулируйте значения maxVal и minVal, чтобы лучше соответствовать показаниям датчика расстояния. Для контроля значений, которые вы получаете на различных расстояниях, можно инициализировать последовательное соединение в заголовке setup() и вызвать функцию Serial.println(DIST) сразу после выполнения шага analogRead(DIST).
ПРИМЕЧАНИЕ
Для просмотра демонстрационного видеоклипа программы, формирующей гистограмму расстояния, зайдите по адресу http://www.exploringarduino.com/content/ch7. Этот видеоклип доступен также на сайте издательства Wiley.
Резюме
В этой главе вы узнали следующее:
• Как работают сдвиговые регистры.
• Чем отличается последовательная и параллельная передача данных.
• В чем различие между десятичной и двоичной формой представления данных.
• Как создать световую анимацию с помощью сдвигового регистра.
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОК