Привет Гость!
Рады видеть Вас на МАЛАТКЕ! Внимание!!! Ваши права ограничены.
Чтобы снять ограничения и не просматривать лишний контент Войдите или
Зарегистрируйтесь на сайте.
С уважением Администрация сайта
Сейчас: 30.11.2024, 21:24.
Сдвиговый регистр - это набор последовательно соединённых триггеров (обычно их 8 штук). В отличии от стандартных регистров, сдвиговые поддерживают функцию сдвига вправо и влево. (т. е. переписывание данных с каждого предыдущего триггера на следующий по счёту).
Функционал и назначение у сдвиговых регистров довольно велик. Сегодня мы познакомим одного из них с Arduino (Отличный способ множить выходы у Arduino: занимаем 3, получаем 8). Наверное самая популярная микросхема, представляющая собой такой регистр - это 74HC595.
- Работает на интерфейсе SPI: ноги DS, ST_CP, SH_CP - это шины управления. Соответственно: шина данных(MOSI), защёлка(SS) и тактовая линия(SCK). Подключаем на любые 3 контакта Arduino (библиотека SPI в коде не будет задействована). У меня это 12, 10, 13 выходы Arduino (стандарт). - Ноги Q0, Q1, ..., Q7 - это выходы регистра (разряды). Для того, чтобы следить за состоянием каждого из них, повесим на каждый вывод по светодиоду (с последовательно соединённым резистором. Номинал от 150 до 330 Ом) - VCC и GND - это питание. Подключаем к +5v и GND. - выход Q7` не трогаем (предназначен для последовательного соединения таких регистров) - MR - это сброс. Подключаем к +5v (сброс не активен). - ну и OE притягиваем к земле (подключаем к контакту GND). Получается вот, такая схема: Теперь к коду: - как говорилось ранее, библиотека SPI использоваться не будет. Есть удобная функция shiftOut(). для начала именуем наши пины (тактовая линия - clock, данные - data, защёлка - latch):
Код
#define clock 13 #define data 12 #define latch 10
потом в void setup() обозначаем их как выходы и сразу ставим защёлке высокий уровень, чтобы регистр не принимал сигналов:
теперь давайте попробуем что-нибудь отправить на регистр: - для начала ставим LOW на защёлку (начинаем передачу данных. Теперь регистр принимает сигналы с Arduino). digitalWrite(latch, LOW);
- потом отправляем данные (т. е. отправляем байт в цифровом или двоичном виде. В двоичном проще, т. к. каждый из 8 битов отвечает за свой разряд в регистре. Проще сориентироваться глазами):
Для начала отправим байт 0b10000000; (должен будет загореться первый светодиод): shiftOut(data, clock, LSBFIRST,0b10000000);
- и в конце выставляем HIGH на защёлку (заканчиваем передавать данные). digitalWrite(latch, HIGH);
Теперь вгружаем в ардуину. Результат должен быть таким (зажёгся первый светодиод):
(если у вас зажёгся не первый, а последний светодиод, то в функции shiftOut поменяйте LSBFIRST на MSBFIRST и всё станет на свои места). Итак, получилось! Предлагаю создать функцию для того, чтобы каждый раз не писать эти 3 СТРОЧКИ: Я назову её: sendbyte;
Эта функция отправляет регистру состояние всех разрядов сразу. Это пригодится для управления семисегментом (например). Но, чтобы использовать регистр как расширитель портов, нужно управлять каждым разрядом по-отдельности (аналогично функции digitalWrite()): - Мы можем отправлять регистру только полный байты (8 бит - 0b00000000). Если отправить не 8, а 5 бит (например: 0b00000000), то регистр будет ждать недостающие 3 бита. Значит, что когда мы хотим изменить состояние одного разряда регистра (включить его, или выключить) мы должны, по сути, послать ранее отправленный байт, с изменением на один бит. (P. S.: Сейчас долгое и нудное объяснение (новичкам), кому не интересно, спуститесь чуть ниже :); - Итак, сначала создаём, так называемую (мною), базу данных, в которой будет храниться состояние каждого разряда (включен(HIGH) или выключен(LOW)). тип: boolean: boolean states[8];
Только что у нас появился массив переменных; Каждая переменная в данном массиве обозначает свой разряд (в нулевой (по счёту) будет храниться состояние 1 разряда, второй - 3-го, и т. д.) - Теперь напишем функцию (я назову её: sendpin). Она будет принимать 2 значения: номер разряда, и уровень, который нам надо этому разряду приписать: высокий(HIGH) или низкий(LOW).
Из-за того, что счёт начинается с нуля, нам придётся называть первый пин нулевым. Чтобы это исправить (мы будем писать как есть(первый, значит первый), а Arduino будет сама отбавлять один), Я написал: pin--;
- Затем отмечаем изменения в базе данных: states[pin]=state;
Теперь надо сформировать из 8 битов байт и отправить его на регистр. - для начала создаём переменные: value - тот байт, который будем отправлять. (по умолчанию его нужно сделать нулём): byte value = 0;
add - это переменная, которая будет хранить в себе байт текущего разряда. для первого разряда это байт 1 (0b10000000); byte add = 1;
теперь нам нужно прокрутить в базе данных все 8 переменных и сформировать байт (делать это будем с помощью цикла for():
Код
for(int i=0; i<8; i++){ }
Итак, каждый раз мы проверяем очередной разряд в базе данных. Если он должен иметь высокий уровень, то мы прибавляем к value add и переходим на следующий разряд в цепочке (как бы сдвигаемся на разряд выше (левее). Т. е., в двоичном коде всё просто: было так: 0b01000000; сдвинули единичку влево и получилось так: 0b10000000. А вот в цифровом виде всё по-другому. Сдвиг влево аналогичен умножению на 2 (а вправо, кстати, - делению на 2)). Получается примерно так:
И оставлю от себя, как репостера несколько слов. В этом примере все сделано с минимальной сложностью, т.е. с максимальной понятностью, можно оптимизировать и сделать меньше кода и больше эффективности. Материал взят с сайта "Паяльник" Прикрепленные файлы:
Доброго времени суток. Подскажите уважаемые знатоки, а можно ли, и как, при использовании сдвигового ригистра, байт (0b00000000) отправляемый на него формировать с переменных, значение которых изменяется в результате нажатия кнопки, т.е. 1 или 0.
Доброго времени суток. Подскажите уважаемые знатоки, а можно ли, и как, при использовании сдвигового ригистра, байт (0b00000000) отправляемый на него формировать с переменных, значение которых изменяется в результате нажатия кнопки, т.е. 1 или 0.
void loop() { for (int i = 0; i<10; i++){ digitalWrite(latchPin, LOW); // shiftOut(dataPin, clockPin, MSBFIRST,0b11111101); // без использования массива вывести данные shiftOut(dataPin, clockPin, MSBFIRST, number); //С масивом digitalWrite(latchPin, HIGH); delay(500); } }
Добавлено (10.03.2016, 11:27) --------------------------------------------- Всем спасибо! Уже не актуально код будет такой const byte latchPin = 4; // 11 пин на 74HC595 const byte clockPin = 7; // 12 пин на 74HC595 SRCLR const byte dataPin = 5; // 14 пин на 74HC595 SER int sensorPin=A0;