[Arduino範例] 使用74HC595移位暫存器,控制多個LED燈

只要是學過Arduino的人都知道如何控制LED燈,1顆沒問題,3顆5顆沒題,但如果是8顆呢?等等,程式是沒問題,但接完LED,腳位也差不多用完了!這時74HC595就派上用場了,它可以用3個腳位控制8個以上的LED!

74HC595是一顆移位暫存器 (Shift Register),使用這顆晶片,你只需要Arduino的三個接腳,就可以同時控制八個輸出。74HC595是可以串聯多顆來得到更多輸出的腳位,如果串聯2顆就能控制16顆LED燈,以此類推。這次我們先用單顆74HC595進行練習。

另外,移位暫存器不只有74HC595,也有其它選擇的,像是STP16C596,單顆就能提供16個通道,每個通道還能提供高達120mA的電流,遠大於74HC595的25-35mA,不過我們本範例還是先介紹最常見的74HC595哦。

想了解移位暫存器原理的朋友可以參考WiKi上的解說:
https://zh.wikipedia.org/wiki/移位寄存器

74HC595有16個腳位,每個腳位的名稱如下:

74HC595的16個腳位,其中Q0~Q7可以用來接8顆LED,以本次的範例來說,其它腳位的接法如下:

  • VCC => 5V
  • DS => PIN 11 (Data pin)
  • OE => GND
  • STCP => PIN 8 (Latch pin)
  • SHCP => PIN 12 (Clock pin)
  • MR => 5V
  • GND => GND

接法其實不難,就是線超多的,而且每顆LED我們還要加上220歐姆的電阻,相信不少人看了接線圖就眼花了吧,不過一定要把線都接正確哦!

送出資料會用到shiftOut()這個函式,而函式所需要的資料類型為byte,也就是0-255的數字,用來表示8bit的資料,每一個通道一個bit,用0和1來代表LOW和HIGH,也就是LED的亮與不亮。

舉例來說,如果要讓第1、3、5、7,4個燈亮,2、4、6、8,4顆燈不亮,那就是10101010,換算成10進位就是170。

換算的方法應該有上過電概的人就會了,只是很多人都忘了吧^^,沒關係,有不少網站提供換算的功能,Google一下就有了,以下網站是傑森找到的,大家可以參考看看。

https://www.binaryhexconverter.com/binary-to-decimal-converter

我們要做的範例很簡單,就是讓8顆燈,4顆4顆交錯輪流亮,先亮1、3、5、7,再亮2、4、6、8,也就是10101010、01010101,換算十進位就是170和85。

int latchPin = 8;  // Latch pin (STCP腳位)
int clockPin = 12; // Clock pin (SHCP腳位)
int dataPin = 11;  // Data pin (DS腳位)

void setup() 
{
  // Set all the pins of 74HC595 as OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}

void loop() 
{
  digitalWrite(latchPin, LOW);  // 送資料前要先把 latchPin 設成低電位
  shiftOut(dataPin, clockPin, LSBFIRST, 170);  //送出資料,170就是2進位的10101010
  digitalWrite(latchPin, HIGH); // 送完資料後要把 latchPin 設成高電位
  delay(300);
  digitalWrite(latchPin, LOW);
  shiftOut(dataPin, clockPin, LSBFIRST, 85);  //85就是2進位的01010101
  digitalWrite(latchPin, HIGH);
  delay(300);
}

程式裡最主要的是shiftOut()這個函式,它需要4個參數:dataPin、clockPin、資料順序(LSBFIRST由右至左、MSBFIRST由左至右)、資料。其中資料順序我們用的是LSBFIRST,而資料則是填入170或85。

還有一點很重要的,就是在shiftOut()送出資料前,必須先將latchPin設為低電位,送完資料再把latchPin設回高電位。

我們用了兩段程式,分別送出170和85,間隔0.3秒,寫入程式後,就可以看到LED開始閃爍變化囉!

另外再送上另一個範例,就是常見的流水燈,這個例子是由第8顆燈開始亮起,依序亮到第1顆燈,然後全滅,再重覆。

int latchPin = 8;  // Latch pin (STCP腳位)
int clockPin = 12; // Clock pin (SHCP腳位)
int dataPin = 11;  // Data pin (DS腳位)

byte leds = 0;    // 亮燈的LED數量
void setup() 
{
  // Set all the pins of 74HC595 as OUTPUT
  pinMode(latchPin, OUTPUT);
  pinMode(dataPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
}

void loop() 
{
  leds = 0; // 一開始燈全滅,所以設為0
  updateShiftRegister();  //進行送資料的副程式
  delay(500);
  for (int i = 0; i < 8; i++) //依序亮燈
  {
    bitSet(leds, i);    // 經由多少燈要亮的i,換算成10進位,並把結果交給leds
    updateShiftRegister(); //進行送資料的副程式
    delay(100);
  }
}

void updateShiftRegister()
{
   digitalWrite(latchPin, LOW);
   shiftOut(dataPin, clockPin, LSBFIRST, leds);
   digitalWrite(latchPin, HIGH);
}