之前的實驗是使用7447來控制7段顯示器,一個7447的輸入是4條線,因此會用掉樹莓派的4個GPIO連接埠。但是,如果想要在有限的IO下控制最多的輸出,其實使用Shift Register是最好的選擇。74595則是最常見的8位元輸出Shift Register。它主要使用3條輸入訊號,其中一條用來輸入資料,而另外一條則是時脈Clock,再另外一條則是控制是否要輸出的閂鎖Latch信號。先看一下影片:

上面這個影片是一個以二進位計數的方式,從0一直往上數到255的其中一個片段。

74595這顆8位元的Shift Register位移暫存器,就是一個有8個資料位元的輸出,而我們在影片上就是把這8個位元的輸出(分別是D0-D7)各接上一個LED來顯示其內容。但是,如何改變這些位元的內容呢?由於它是以位移的方式一次一個位元的方式移到暫存器中,所以只要有一個位元的輸入端(此為DS,在第14腳),這支接腳要連接到GPIO的輸出(直接接上即可),當把0或1(True or False)準備好了之後,再去Clock時脈端(此為SHcp,第11腳)先送一個HIGH再送一個LOW,讓在DS準備好的資料可以被移入。有幾個位元想要移入,就重覆做幾次(請參考程式)。等到全部都到位之後,再把Latch(STcp,第12腳)打開,也是先送一個HIGH再送一個LOW,則此時所有的資料D0~D7就會被反應出來,驅動LED工作。完整的接線說明如下:

  • 把74595的D0~D7分別先接到1K的電阻,此電阻的另一端再接至LED的正極,然後LED的負極接地。
  • 第16腳Vcc以及第10腳MR’接到樹莓派的+5V電源(PIN 2)
  • 第8腳GND以及第13腳OE’接到樹莓派的GND(PIN 6)
  • DS接到樹莓派的PIN22
  • STcp接到樹莓派的PIN18
  • SHcp接到樹莓派的PIN16

程式如下:

import RPi.GPIO as gpio
import time

DS = 22
LTH = 18
CLK = 16
DLY = 0.01
gpio.setwarnings(False)
gpio.setmode(gpio.BOARD)
gpio.setup(DS, gpio.OUT)
gpio.setup(LTH, gpio.OUT)
gpio.setup(CLK, gpio.OUT)

def clk():
    gpio.output(CLK, gpio.HIGH)
    time.sleep(DLY)
    gpio.output(CLK, gpio.LOW)

def clear_output():
    for i in range(8):
        gpio.output(DS, gpio.LOW)
        clk()
    data_out()

def data_out():
    gpio.output(LTH, gpio.HIGH)
    time.sleep(DLY)
    gpio.output(LTH, gpio.LOW)

def bit_input(b):
    gpio.output(DS, b & True)
    clk()
       

def digit_output(num):
    clear_output()
    bin = list()
    while num > 0:
        bin.append(num % 2)
        num = num / 2
    bin.reverse()
    for b in bin:
        bit_input(b)
    data_out()

clear_output()
for i in range(255):
    digit_output(i)
    time.sleep(0.1)
gpio.cleanup()

程式中最主要的部份是以clk這個函數模擬時脈信號,也就是把輸入從高電位改到低電位,才會觸發位移暫存器做下一個動作。而bit_input這個函數就是一次送一個位元進去暫存器中,digit_output函數則是可以把指定的任一整數化為2進位的數字串列,再逐一把這些數字移入暫存器中,最後,以data_out()這個函數把此暫存器輸出到LED中。

(202)