Управление светодиодами
Итак, начнем с самого простого. Будем управлять восемью светодиодами, подключенными к Ардуино Уно посредством сдвигового регистра 74HC595. Не будем забывать, что каждому светодиоду необходим токозадающий резистор. Наличие регистра не освобождает нас от этого важного компонента.
Принципиальная схема
Внешний вид макета
Программа
Программа будет последовательно зажигать каждый из светодиодов. Для хранения номера горящего светодиода используем переменную bt типа byte.
const int data_pin = 2;
const int sh_pin = 4;
const int st_pin = 3;
b bt = 0;
// функция, которая выводит байт в регистр побитно
void shift(byte v){
// перебираем все биты байта
// для каждого бита опускаем уровень на SH_CP
// выставляем нужный уровень на DS
// и обратно поднимаем SH_CP
// всё строго с диаграммой
for(int i=0; i<8; i++){
digitalWrite(sh_pin, LOW);
digitalWrite(data_pin, v & (1 << i ));
digitalWrite(sh_pin, HIGH);
}
// отправляем финальный импульс на контакт ST_CP
digitalWrite(st_pin, HIGH);
digitalWrite(st_pin, LOW);
}
void setup() {
pinMode(data_pin, OUTPUT);
pinMode(sh_pin, OUTPUT);
pinMode(st_pin, OUTPUT);
}
void loop() {
// вызываем функцию shift, передавая в неё очередной байт
shift(1<<bt);
bt++;
if( bt==8 )
bt = 0;
delay(200);
}
Для заполнения регистра мы добавили специальную функцию shift. Функция в цикле опускает уровень на SH_CP, затем устанавливает нужный бит на выводе DS, и в конце поднимает SH_CP. Наконец, после завершения цикла, мы делаем импульс на ST_CP для передачи битов на выходы регистра. Всё как во временной диаграмме, которую мы разобрали ранее.
В цикле мы должны перебрать все биты числа v. Сначала взять первый бит, передать его в регистр. Потом второй, потом третий, и т.д. Как это сделать? Разберем вот такую конструкцию:
v & (1 << i)
переменная v — это восемь бит, которые мы хотим записать в регистр. Операция 1<<i сдвигает единицу на i позиций влево. К примеру, 1<<3 соответствует числу 0000 1000 в бинарном виде. 1<<4 даст уже 0001 0000, и так далее. Назовем результат этой операции трафаретом.
Операция & — это бинарная операция «И». С помощью неё мы как бы накладываем трафарет на число v. Допустим, число v = 0111 0110. На третьем шаге цикла трафарет будет равен 0000 0100. Теперь наложим трафарет и получим:
0111 0110 & 0000 0100 = 0000 0100 = истина
Тут следует уточнить, что в языке C++, как и во многих других языках, любое отличное от нуля число интерпретируется как «истина» или логическая единица. digitalWrite интерпретирует эту логическую единицу как высокий уровень сигнала, что нам и требуется!
На следующей итерации трафарет уже будет равен 0000 1000, наложим теперь его на v:
0111 0110 & 0000 1000 = 0000 0000 = ложь
В общем, мы двигаем единичку в трафарете, и каждый раз накладываем полученный трафарет на число.
Теперь посмотрим на основной цикл:
void loop() {
shift(1<<bt);
bt++;
if( bt==8 )
bt = 0;
delay(200);
}
У нас есть итератор bt, который мы меняем вручную, без for. Просто прибавляем каждый раз по единичке, и обнуляем, когда bt увеличится до 8. Самое главное здесь — вызов функции shift. В качестве аргумента функции мы передаем единицу, сдвинутую влево на bt позиций. Этим мы задаем номер зажигаемого светодиода.
Вот как будет выглядеть полученное устройство, в случае использования не отдельных светодиодов, а шкального индикатора из 10 светодиодов. Поскольку сдвиговый регистр 74HC595 позволяет хранить только 8 бит, мы не будем использовать крайние два светодиода.