Управление светодиодами

Итак, начнем с самого простого. Будем управлять восемью светодиодами, подключенными к Ардуино Уно посредством сдвигового регистра 74HC595. Не будем забывать, что каждому светодиоду необходим токозадающий резистор. Наличие регистра не освобождает нас от этого важного компонента.

Принципиальная схема

ardu-595-led_схема

Внешний вид макета

ardu-595-led_bb

Программа

Программа будет последовательно зажигать каждый из светодиодов. Для хранения номера горящего светодиода используем переменную 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 бит, мы не будем использовать крайние два светодиода.

register595

Изменено: