/*
* Набор для экспериментов MaxKit 01
* Код программы для опыта №14: sketch 14
*
* Сдвиговый регистр
*
* Написано для сайта «Полный комплект» http://maxkit.ru
*
*
* Помощь сообщества Arduino.
* Посетите сайт http://www.arduino.cc
*
*
* РЕГИСТР СДВИГА
*
* Использование микросхемы регистра сдвига для управления 8 выходами
* используя всего 3 порта Arduino
*
* Интегральная Схема (ИС или «IC — integrated circuit»), или «чип»,
* это самодостаточное электронное устройство встроенное в небольшой
* пластиковый корпус. Если внимательно посмотреть на плату Arduino
* можно рассмотреть некоторое количеству ИС установленных на ней.
* Есть тысячи различных видов ИС, доступных для использования, из
* которых можно собрать множество полезных вещей.
*
*
* Микросхема Сдвиговый Регистр 74HC595 из вашего набора является
* ИС, которая имеет восемь цифровых выходов. Чтобы использовать
* эти выходы, мы будем использовать новый интерфейс под названием
* SPI (Serial Peripheral Interface) или последовательный
* периферийный интерфейс. Это как ТX и RX к которому вы привыкли,
* но имеет дополнительные «часы» линию, которая контролирует
* скорость передачи данных. Многие микросхемы используют SPI
* (последовательный интерфейс) для связи между собой, поэтому и у
* Arduino тоже есть такой интерфейс, а также пара команд: shiftIn()
* и shiftOut(), для доступа и передачи данных ИС.
*
* Эта ИС позволяет использовать всего три цифровых порта Arduino
* для управления 8 цифровыми выходами. А если вам нужно еще больше,
* вы можете подключить последовательно несколько регистров сдвига,
* что позволит управлять практически неограниченным количество
* выходов, все из тех же трех портов Arduino! См. таблицу
* (datasheet) обозначения выводов регистра сдвига SN74HC595:
*
* http://www.sparkfun.com/datasheets/IC/SN74HC595.pdf
*
* Подключение оборудования:
*
* Сдвиговый регистр:
*
* Подключите чип, так чтобы его выводы оказались с разных
* сторон центральной линии макетной платы.
*
* ИС «Регистр Сдвига» имеет 16 контактов. Они пронумерованы
* против часовой стрелки, начиная от ключа (не большой выемки
* — углубления на торце чипа). См таблицу выше.
*
* 74HC595 pin LED pin Arduino pin
*
* 1 (QB) LED 2 +
* 2 (QC) LED 3 +
* 3 (QD) LED 4 +
* 4 (QE) LED 5 +
* 5 (QF) LED 6 +
* 6 (QG) LED 7 +
* 7 (QH) LED 8 +
* 8 (GND) GND
*
* 9 (QH*)
* 10 (SRCLR*) 5V
* 11 (SRCLK) Digital 3
* 12 (RCLK) Digital 4
* 13 (OE*) GND
* 14 (SER) Digital 2
* 15 (QA) LED 1 +
* 16 (VCC) 5V
*
* Светодиоды:
*
* После присоединения всех положительных выводов, указанных выше,
* (длинных ножек) светодиодов, соедините их отрицательные выводы
* (короткие ножки), каждого светодиода, с резисторами по 330 Ом,
* и соедините другую сторону каждого резистора с общим проводом.
*
*
*
*
*
* Этот sketch был написан SparkFun Electronics,
* Переведен специально для сайта http://maxkit.ru
* 01 февраля 2015г.
*
*/
// Определения контактов:
// 74HC595 использует SPI (последовательный интерфейс),
// которому требуется всего три пина:
// data — данные
// clock — тактовые импульсы
// latch — защелка
int datapin = 2;
int clockpin = 3;
int latchpin = 4;
// Для наглядности и понимания пины названы соответственно:
// Англ. — рус.: data — данные; clock — тактовые импульсы;
// latch — защелка.
// Мы также объявим глобальную переменную для данных, которые
// будем отправлять в регистр сдвига:
byte data = 0;
void setup()
{
// Установим три SPI пина, которые будут выходными:
pinMode(datapin, OUTPUT);
pinMode(clockpin, OUTPUT);
pinMode(latchpin, OUTPUT);
}
void loop()
{
// Мы собираемся использовать те же самые функции, которые
// использовали в опыте №4 (про несколько светодиодов), мы
// просто заменили DigitalWrite() новой функцией shiftWrite()
// Про эту функцию поговорим чуть ниже.
// Еще появилась новая функция, которая демонстрирует работу
// двоичного счетчика.
// Чтобы опробовать различные функции расположенные ниже, просто
// раскомментируйте одну из них, которую хотите запустить, и
// закомментируйте оставшиеся, которые не будут использоваться.
one after another — один за другим
//oneAfterAnother(); // один за другим
//oneOnAtATime(); // прокрутить строку вниз
//pingPong(); // прокрутить строку вниз и обратно
//randomLED(); // мигание случайным светодиодом
//marquee(); // бегущие огни
//binaryCount(); // двоичный счет от 0 до 255
}
void shiftWrite(int desiredPin, boolean desiredState)
// Эта функция позволяет устанавливать на выходах регистра
// сдвига либо HIGH либо LOW, точно также, как при использовании
// функции digitalWrite().
// И также как digitalWrite(), эта функция принимает два параметра:
// «desiredPin» желаемый pin сдвигового регистра от 0 до 7
// «desiredState» желаемый потенциал на нем HIGH или LOW
// Внутри Arduino, цифры хранятся в виде «битовых» (bits) массивов,
// Каждый бит может содержать лишь одно значение: либо единицу,
// либо ноль (5 Вольт или 0, HIGH или LOW). Из за того что 8 бит
// называется «байтом» (byte) мы будем использовать переменную,
// которой мы дали название «data» в верхней части скетча, длинною
// в байт (byte=8bit), для передачи данных в регистр сдвига.
// Если бит в «data» при входе был единицей, на выходе будет 1.
// Если бит в «data» был «0», на выходе будет 0.
// Для изменения отдельных битов в переменной «data», мы будем
// использовать новую команду Arduino с названием bitWrite(),
// которая может изменять состояние указанного бита на 1 или 0.
{
// Сначала мы изменим глобальную переменную «data», выборочно
// поменяв выбранные биты на 1 или 0:
bitWrite(data,desiredPin,desiredState);
// Теперь мы отправим эти данные в регистра сдвига. Для этого
// используем функцию shiftOut(), она делает всю тяжелую работу
// управляет данными, тактовыми импульсами и т.д.:
shiftOut(datapin, clockpin, MSBFIRST, data);
// После того, как данные попали в регистр сдвига, нам надо чтобы
// они появились на его выходах. Для этого их нужно «защелкнуть»,
// подав логическую единицу (HIGH) на 12 pin регистра сдвига.
// Поэтому даем HIGH через переменную LatchPin, которая будет
// сигнализировать сдвиговому регистру о том что данным пора
// появиться на выходах.
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
}
/*
oneAfterAnother()
Эта функция будет зажигать один светодиод, делать маленькую паузу,
включать следующий светодиод, опять пауза, затем следующий и так, пока
все светодиоды не загорятся. Затем начнет отключить их в обратном
порядке.
*/
void oneAfterAnother()
{
int index;
int delayTime = 1000; // Время (в миллисекундах) для пауз
// уменьшите или увиличте значение
// Включить светодиоды:
// Этот цикл for() увеличивает переменную на единицу от 0 до 7
// Затем используется digitalWrite(), чтобы включить светодиод.
// Затем пауза
for(index = 0; index <= 7; index++)
{
shiftWrite(index, HIGH);
delay(delayTime);
}
// Выключить светодиоды:
// Этот цикл for() уменьшает переменную на единицу от 0 до 7
// Затем используется digitalWrite(), чтобы выключить светодиод.
// Затем пауза
for(index = 7; index >= 0; index—)
{
shiftWrite(index, LOW);
delay(delayTime);
}
}
/*
oneOnAtATime ()
Эта функция будет шаг за шагом, по очереди, по одному,
включать светодиоды — первый, второй, третий и т.д.
*/
void oneOnAtATime()
{
int index;
int delayTime = 1000; // Время (в миллисекундах) для пауз
// попробуйте уменьшить или увиличить
// Этот цикл for() увеличивает переменную на единицу от 0 до 7
// Т.е. «переменная», включили, пауза, выключили, прибавили
// в переменную единицу, включили, пауза, выключили и так до 7,
// затем все с начала
for(index = 0; index <= 7; index++)
{
shiftWrite(index, HIGH); // включить светодиод
delay(delayTime); // маленькая пауза, или большая
shiftWrite(index, LOW); // выключить светодиод
}
}
/*
pingPong()
Эта функция будет шаг за шагом, по очереди, по одному,
включать светодиоды — первый, второй, третий и так до
восьмого, затем действие пойдет в обратном порядке 7, 6,
5, 4, 3, 2, 1 и все повторится, как в игре пинг-понг.
*/
void pingPong()
{
int index;
int delayTime = 100; // Время (в миллисекундах) для пауз
// попробуйте уменьшить или увеличить
// Снова тот же цикл for() увеличивает переменную на единицу
for(index = 0; index <= 7; index++)
{
shiftWrite(index, HIGH); // включить светодиод
delay(delayTime); // маленькая пауза
shiftWrite(index, LOW); // выключить светодиод
}
// Снова цикл for() с уменьшением переменной
for(index = 7; index >= 0; index—)
{
shiftWrite(index, HIGH); // включить светодиод
delay(delayTime); // маленькая пауза
shiftWrite(index, LOW); // выключить светодиод
}
}
/*
randomLED()
Функция включает по одному светодиоду в случайной
последовательности, также случайна длительность свечения
*/
void randomLED()
{
int index;
int delayTime = 1000; // Время (в миллисекундах) для пауз
// попробуйте уменьшить или увеличить
// Далее используется функция random(), которая возвращает
// случайное (точнее сказать псевдослучайное) число. Как
// ее использовать. См https://arduino.ru/Reference/Random
index = random(8); // Выбрать случайное число между 0 и 7
shiftWrite(index, HIGH); // включить светодиод
delay(delayTime); // маленькая пауза
shiftWrite(index, LOW); // выключить светодиод
}
/*
marquee()
Функция имитирует эффек бегущих огней
*/
void marquee()
{
int index;
int delayTime = 2000; // Время (в миллисекундах) для пауз
// попробуйте уменьшить или увеличить
// Шаг — через три светодиода 1-ый и 5-ый, 2-ой и 6-ой…
// То есть Мы будем включать каждый четвертый светодиод
for(index = 0; index <= 3; index++)
{
shiftWrite(index, HIGH); // включить светодиод
shiftWrite(index+4, HIGH); // увеличить на 4 и включить
delay(delayTime); // Пауза, чтобы замедлить последовательность
shiftWrite(index, LOW); // выключить светодиод
shiftWrite(index+4, LOW); // увеличить на 4 и выключить
}
}
/*
binaryCount()
Числа хранятся во внутренней памяти Arduino в виде массивов «бит».
Каждый бит может быть либо логической единицей (HIGH — высокий
потенциал, либо логическим нулем (LOW — низкий потенциал). Так же,
как десятичные числа, которые мы используем каждый день, положение
занимаемой позиции каждого бита влияет на общее число (сумму в байте).
Для примера: В двоичной системе положение бита в первой позиции
(первая позиция в данном случае «0» см. таблицу ниже, вторая «1»,
третья «2» и т.д) будет соответствовать «1» в десятичной системе
исчисления, положение во 2 позиции будет соответствовать двойке
в десятичной, положение в третьей позиции буде соответствовать 4
в десятичной, следующая 8, 16, 32 и т.д )).
Таблица. Соответствие позиции битов десятичной системы к двоичной:
0 1
1 2
2 4
3 8
4 16
5 32
6 64
7 128
Пример 1:
Чтобы создать цифру пять нужно включить бит в первой позиции, т.е
записать в него единицу (HIGH), и бит в третьей позиции, записать
в него тоже единицу (HIGH). Складываем 1+4:
0=HIGH 1
1=LOW 2
2=HIGH 4
3=LOW 8
4=LOW 16
5=LOW 32
6=LOW 64
7=LOW 128
Пример 2:
Чтобы создать цифру 10 нужно включить бит во второй позиции, т.е
записать в него единицу, и бит в четвертой позиции, тоже записать
в него единицу. Складываем 2+8:
0=LOW 1
1=HIGH 2
2=LOW 4
3=HIGH 8
4=LOW 16
5=LOW 32
6=LOW 64
7=LOW 128
Пример 3:
Чтобы создать цифру 20 нужно включить бит в третьей позиции, т.е
установить его в HIGH, и бит в пятой позиции, тоже HIGH.
Складываем 4+16:
0=LOW 1
1=LOW 2
2=HIGH 4
3=LOW 8
4=HIGH 16
5=LOW 32
6=LOW 64
7=LOW 128
Если все биты LOW, это соответствует 0. Если все биты HIGH (включены),
чило равно 255.
Таким образом можно записать любое число от 0 до 255. Именно столько
помещается в 1 byte.
Пример 4: число 200 (8+64+128):
11001000
Пример 5: число 0:
00000000
Пример 6: число 255:
11111111
Эта функция будет увеличивать переменную «data» на 1 шаг за шагом
от 0 до 255. Достигнув 255 начнет все сначала и т.д. Из переменной,
данные передаются в регистр сдвига, после чего появляюются на
его выходах. Индикатором служат светодиоды. Если их выставить в
ряд, они покажут содержание переменной «data», т.е шаблон из
восьми бит, которые и составляют 1 байт.
См http://www.arduino.cc/playground/Code/BitMath для получения
дополнительной информации о двоичных чисел.
*/
void binaryCount()
{
int delayTime = 1000; // Время (в миллисекундах) для пауз
// попробуйте уменьшить или увиличить
// Отправить байт данных в регистр сдвига:
shiftOut(datapin, clockpin, MSBFIRST, data);
// Защелкиваем данные для того чтобы они появились на выходах:
digitalWrite(latchpin, HIGH);
digitalWrite(latchpin, LOW);
// Увиличиваем данные на единицу и повторяем!
// Из за того что тип «byte» это 8-ми битное, беззнаковое,
// целое число, в диапазоне от 0 до 255, мы не може добавить
// более 255-и, в противном случае все «завалится» обратно
// в 0, все начнется сначала.
data++;
// Задержка, для того чтобы вы что-то успели рассмотреть:
delay(delayTime);
}
Добавьте подсветку кода на сайт, это же не сложно. А код читать станет в разы удобнее и проще!
Сегодня вечером добавлю статью и код, его удобнее читать в Arduino IDE
Ужасный формат статьи 🙁
Понимаю, что прошло достаточно много времени с момента публикации, но вдруг! 🙂 Непонятно как работает функция shifWrite. Ей передаются выходной пин регистра и его значение — откуда ардуина знает на какой пин передать байт? shiftOut, там понятно. мы указываем пин data и т.д., а shiftWrite откуда знает на каком пине висит регистр? Что-то сродни мистике для меня.Еще ничего не сказано про пин «clock», нафиг он нужен и что с ним можно делать ведь он OUTPUT? Почему мы ничего вообще с ним не делаем? Или что-то происходит в недрах библы Arduino? Поясните эти моменты, пожалуйста.
А СТОП, понятно как работает. А не понял потому, что статья оформлена не как статья. Вопрос по Clock остается.