Arduino:Примеры/ShftOut22

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Поочередное зажигание 16 светодиодов[1]

Это скетч для платы Arduino и двух сдвиговых регистров 74HC595. Он поочередно зажигает два ряда светодиодов – восемь, подключенных к одному регистру, и восемь, подключенных к другому. Переход от одного светодиода к другому осуществляется двумя способами.

Код

//***************************************************************//
//  Название    : Поочередное зажигание 16 светодиодов           //
//  Автор       : Кэрлин Мо, Том Иго                             //
//  Дата        : 25 октября 2006 года                           //
//  Версия      : 1.0                                            //
//  Примечания  : Код для использования с двумя о сдвиговым      //              
//              : сдвиговыми регистрами 74РС595                  //
//***************************************************************//

// Контакт, подключенный к контакту ST_CP на 74HC595:
int latchPin = 8;
// Контакт, подключенный к контакту SH_CP на 74HC595:
int clockPin = 12;
// Контакт, подключенный к контакту DS на 74HC595:
int dataPin = 11;

// для хранения информации, которая будет передана функции,
// отвечающей за перемещение битов:
byte data = 0;



void setup() {
  // выставляем latchPin в режим OUTPUT, 
  // поскольку он будет использоваться в блоке loop():
  pinMode(latchPin, OUTPUT);

}

void loop() {

  // функция, мигающая всеми светодиодами;
  // параметры – количество миганий и пауза между ними:
  blinkAll_2Bytes(1,500); 

  // поочередно зажигаем каждый светодиод с помощью функции A:
  for (int j = 0; j < 8; j++) {
    // задаем контакту latchPin значение LOW и оставляем так, 
    // пока все данные не будут переданы:
    digitalWrite(latchPin, 0);
    // красные светодиоды:
    lightShiftPinA(7-j);
    // зеленые светодиоды:
    lightShiftPinA(j);
    // возвращаем latchPin значение HIGH, сообщая чипу, 
    // что ему больше не нужно прослушивать входящую информацию:
    digitalWrite(latchPin, 1);
    delay(1000);
  }

  // поочередно зажигаем каждый светодиод с помощью функции B:
  for (int j = 0; j < 8; j++) {
    // задаем контакту latchPin значение LOW и оставляем так, 
    // пока все данные не будут переданы:
    digitalWrite(latchPin, 0);
    // красные светодиоды:
    lightShiftPinB(j);
    // зеленые светодиоды:
    lightShiftPinB(7-j);
    // возвращаем latchPin значение HIGH, сообщая чипу, 
    // что ему больше не нужно прослушивать входящую информацию:
    digitalWrite(latchPin, 1);
    delay(1000);
  } 

}

// чтобы перемещаться по контактам, эта функция 
// использует побитовые расчеты:
void lightShiftPinA(int p) {
  // задаем локальную переменную:
  int pin;

  // эта строчка кода использует побитовый оператор;
  // перемещение бита влево при помощи «<<» – это то же самое,
  // что и умножение десятичного числа на «2»:
  pin = 1<< p;

  // перемещаем биты:
  shiftOut(dataPin, clockPin, pin);   

}

// чтобы перемещаться по контактам, эта функция использует тот факт, 
// что каждый бит в байте в два раза больше, чем предыдущий:
void lightShiftPinB(int p) {
  // задаем локальную переменную:
  int pin;

  // начинаем с pin = 1; таким образом, если задать этой переменной
  // значение «0», это зажжет светодиод номер «0»:
  pin = 1;

  for (int x = 0; x < p; x++) {
    pin = pin * 2; 
  }
  // перемещаем биты:
  shiftOut(dataPin, clockPin, pin);   
}


// «сердце» программы;
// эта функция передает 8 бит данных (первым идет самый старший бит);
// передача осуществляется на возрастающем фронте тактового сигнала:
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) {

  // аналог блока setup(), но внутри функции:
  int i=0;
  int pinState;
  pinMode(myClockPin, OUTPUT);
  pinMode(myDataPin, OUTPUT);

  // стираем все, чтобы подготовить 
  // сдвиговый регистр к передаче битов:
  digitalWrite(myDataPin, 0);
  digitalWrite(myClockPin, 0);

  // выполняется для каждого бита в байте myDataOut;
  // обратите внимание, что в цикле for() ниже 
  // СЧЕТ ИДЕТ В ОБРАТНОМ НАПРАВЛЕНИИ, и это значит, что значение
  // «%00000001» или «1» будет соответствовать контакту Q0:
  for (i=7; i>=0; i--)  {
    digitalWrite(myClockPin, 0);

    // если значение было передано переменной myDataOut и проверка 
    // битовой маской прошла успешно... то есть если i=6 
    // и наше значение это «%11010100», код сравнит его с «%01000000», 
    // а затем запишет в pinState значение «1»:  
    if ( myDataOut & (1<<i) ) {
      pinState= 1;
    }
    else {	
      pinState= 0;
    }

    // задаем этому контакту HIGH или LOW в зависимости от pinState: 
    digitalWrite(myDataPin, pinState);
    // если тактовый контакт получает значение HIGH, 
    // сдвиговый регистр перемещает биты: 
    digitalWrite(myClockPin, 1);
    // после перемещения битов задаем контакту для данных 
    // значение «0», чтобы избежать «просачивания» данных:
    digitalWrite(myDataPin, 0);
  }

  // останавливаем перемещение битов:
  digitalWrite(myClockPin, 0);
}


// эта функция мигает всеми светодиодами, подключенными к 2 регистрам;
// переменная «n» – это то, сколько раз нужно мигнуть, а «d» – сколько 
// должна длиться пауза между миганиями; запускается с момента, 
// когда светодиоды не горят – чтобы визуальный эффект 
// от первого мигания был полным: 
void blinkAll_2Bytes(int n, int d) {
  digitalWrite(latchPin, 0);
  shiftOut(dataPin, clockPin, 0);
  shiftOut(dataPin, clockPin, 0);
  digitalWrite(latchPin, 1);
  delay(200);
  for (int x = 0; x < n; x++) {
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 255);
    shiftOut(dataPin, clockPin, 255);
    digitalWrite(latchPin, 1);
    delay(d);
    digitalWrite(latchPin, 0);
    shiftOut(dataPin, clockPin, 0);
    shiftOut(dataPin, clockPin, 0);
    digitalWrite(latchPin, 1);
    delay(d);
  }
}

См.также

Внешние ссылки