Skip to main content

7.5 Shift registar

Svaki pin na pločici na kraju bude zauzet. Ovaj projekt pokazuje kako dobiti više izlaza nego što imaš pinova: 74HC595 shift registar pretvara tri pina u osam, a četiri od njih koristimo da sagradimo brojač koji broji od 0 do 15 u binarnom, kako to radi računalo.

U ovoj dokumentaciji naučit ćeš:

  • Kako 74HC595 shift registar pretvara tri pina u osam izlaza
  • Što znače pomicanje (shifting) i zaključavanje (latching), i zašto se sve LED-ice mijenjaju u istom trenutku
  • Kako napisati vlastiti shift_out() pomoću operatora pomaka bita i bitovnog I
  • Kako postaviti čip sa 16 pinova na breadboard a da ga ne okreneš naopako
  • Kako pročitati binarni broj s reda LED-ica

Potreban hardver

  • 1x Soldered NULA MINI pločica
  • 1x Breadboard
  • 1x 74HC595 shift registar
  • 4x LED-ice
  • 4x otpornika od 330 Ω
  • 14x Jumper žice
  • 1x USB-C kabel
ℹ️
Četiri otpornika od 330 Ω su obični ograničivači struje za LED-ice koje si koristio u svakom primjeru do sada: po jedan za LED-icu, prstenovi narančasti-narančasti-smeđi. Upravljačkim pinovima čipa ne trebaju otpornici: to su CMOS ulazi i vuku praktički nikakvu struju, pa se spajaju direktno na 3V3 ili na vodilicu mase.
⚠️
Koristi crvene, žute ili narančaste LED-ice. Izlaz shift registra sjedi na oko 2.9 V pod teretom, što je za te sasvim dovoljno, ali plavoj ili modernoj zelenoj LED-ici treba 3.0 V ili više samo da se upali i ostat će tamna, što izgleda točno kao greška u spajanju.

Spajanje komponenti

Ovaj sklop ima više spojeva od svega drugoga u kitu, pa vrijedi ići polako. Svaka fotografija ispod prikazuje pločicu nakon što je unutra otišla još jedna stvar, dvadeset i jedan korak ukupno: četrnaest jumper žica, četiri otpornika, četiri LED-ice i čip.

1. Umetni pločicu i sagradi vodilicu mase

Utisni NULA MINI u jedan kraj breadboarda tako da zauzme redove 25 do 30, pa prije svega drugoga sagradi dijeljenu masu. To je prvi primjer kojem masa treba na obje strane pločice, a dvije plave vodilice duž rubova nisu spojene međusobno unutar breadboarda.

Također su previše daleko jedna od druge da bi ih se doseglo jednom jumper žicom, pa se spoj pravi u skokovima, koristeći red 1 kao kamen za prelaz:

  • j30 (GND) do donje plave vodilice
  • donja plava vodilica do j1
  • e1 do f1, prelazeći središnji kanal
  • a1 do gornje plave vodilice

Nakon tih četiriju jumper žica, obje vodilice i obje polovice reda 1 su jedna jedina masa.

NULA MINI pločica na breadboardu s četiri plave jumper žice koje formiraju vodilicu mase
Pločica u redovima 25–30, s masom premoštenom oko dalekog kraja

2. Utisni 74HC595

Čip premošćuje središnji kanal i zauzima redove 14 do 21, s polumjesečastim zarezom okrenutim prema redu 14, dalje od pločice. Jedan red pinova sleti u stupac e, drugi u stupac f.

⚠️
Čip također ima malu okruglu jamicu u plastici, oko jedan red unutra od kraja kod reda 21. To je oznaka koju je ostavio kalup, a ne pokazatelj pina 1, i pokazuje na pogrešan kraj. Vodi se polumjesečastim zarezom urezanim u kraj kućišta. Okreni ovo naopako i 3V3 sleti na izlazni pin.

Sa zarezom kod reda 14, pinovi sjede ovako:

Red1415161718192021
a–e strana1 · Q12 · Q23 · Q34 · Q45 · Q56 · Q67 · Q78 · GND
f–j strana16 · VCC15 · Q014 · DS13 · OE12 · ST_CP11 · SH_CP10 · MR9 · Q7'
74HC595 utisnut u breadboard preko središnjeg kanala
Čip u redovima 14–21, premošćuje kanal, zarez prema redu 14

3. Spoji čip na masu

Kratka plava jumper žica vodi pin 8 iz a21 do gornje plave vodilice.

Kratka plava jumper žica spaja pin mase shift registra na gornju vodilicu
Plava: a21 (pin 8, GND) do gornje plave − vodilice

4. Daj čipu napajanje

Bijela žica nosi 3V3 iz j29 u j14, VCC pin čipa. Vodi u petlji ispod pločice umjesto da prelazi ravno preko, jer je to dužina žice koja je bila pri ruci. Ispod nije ništa spojeno.

ℹ️
Čip radi s 3V3, a ne s VCC pina pločice. VCC je 5 V koji dolazi preko USB-a, a 74HC595 napojen na 5 V treba 3.5 V da prepozna visoko stanje, više nego što 3.3 V pinovi pločice mogu proizvesti. Radilo bi na stolu a padalo bi negdje drugdje.
Bijela žica nosi 3V3 na VCC pin shift registra
Bijela: j29 (3V3) u j14, VCC pin čipa

5. Veži Master Reset na visoko

Crvena žica ide i20 u i14, pin 10 (MR) do pina 16 (VCC). MR briše cijeli registar kad god je nisko, pa se mora držati na visokom, a najbliže visoko je pin napajanja koji si upravo spojio.

Crvena jumper žica spaja MR na VCC na shift registru
Crvena: i20 u i14, Master Reset vezan na napajanje

6. Omogući izlaze

Druga kratka plava jumper žica vodi j17 (pin 13, OE) dolje do donje plave vodilice. Output Enable odspaja svih osam izlaza kad god je visoko, pa se mora držati na niskom.

Kratka plava jumper žica spaja Output Enable na donju vodilicu mase
Plava: j17 (pin 13, OE) dolje do donje plave − vodilice

7. Spoji liniju podataka

Tamnozelena žica ide j25 (IO2) u j16, pin 14, DS. To je pin preko kojeg sami bitovi putuju, jedan za drugim.

Tamnozelena žica spaja IO2 na pin podataka shift registra
Tamnozelena: j25 (IO2) u j16, linija podataka

8. Spoji zaključavanje

Tamnoplava žica ide j26 (IO3) u h18, pin 12, ST_CP. To je ona koja tjera svih osam izlaza da se promijene zajedno umjesto da trepere kroz svaki korak.

Tamnoplava žica spaja IO3 na pin zaključavanja shift registra
Tamnoplava: j26 (IO3) u h18, zaključavanje

9. Spoji takt

Tirkizna žica ide j27 (IO4) u g19, pin 11, SH_CP. Kao i žica napajanja ide dugim putem ispod pločice.

Time je spajanje čipa dovršeno:

ŽicaIzUPin čipaZašto
Plava (kratka)a21gornja vodilica8 · GNDMasa čipa
Bijelaj29 (3V3)j1416 · VCCNapajanje čipa
Crvenai20i1410 · MR na VCCMaster Reset držan visoko
Plava (kratka)j17donja vodilica13 · OEOutput Enable držan nisko
Tamnozelenaj25 (IO2)j1614 · DSPodaci
Tamnoplavaj26 (IO3)h1812 · ST_CPZaključavanje
Tirkiznaj27 (IO4)g1911 · SH_CPTakt
Svih sedam žica napajanja i upravljanja spojeno na shift registar
Tirkizna: j27 (IO4) u g19, takt i posljednja od sedam upravljačkih žica
ℹ️
Svaka rupica odsad je zadana točno, pa ih možeš pratiti jednu za jednu. Svaka LED-ica sjedi u krajnjem stupcu, a na a–e strani i j na f–j strani, pa njezina kratka nožica doseže vodilicu bez potrebe za jumper žicom. Zapamti da su pet rupica u redu sve jedan spoj: a16 i c16 su ista električna točka, i tako otpornik u sljedećem koraku doseže pin čipa bez žice.

10. Prvi otpornik od 330 Ω

Sada izlazi. Prvi lanac počinje na Q3, pin 3, na a–e strani u redu 16. Otpornik doseže pin čipa direktno, pa je taj lanac jedini kojem ne treba dovodna žica: jedna nožica u c16, druga u c11.

Otpornik od 330 ohma premošćuje red 16 do reda 11 na a-e strani
Prvi 330 Ω, c16 do c11, direktno s Q3 pina čipa

11. Prva LED-ica, bit 3

Duga nožica (anoda) ide u a11, red u kojem otpornik završava. Stupac a je krajnji, pa je nožica vodilici najbliže što može biti. Kratka nožica (katoda) savija se direktno u gornju plavu vodilicu, čime se u ovom sklopu na svakoj LED-ici izbjegava jumper žica.

Crvena LED-ica s anodom u redu 11 i katodom savijenom u vodilicu mase
Bit 3 gotov: LED-ica koja broji 8

12. Dovodna žica za bit 2

Q2 je pin 2, na a15. Njegova LED-ica ide s druge strane kanala, pa narančasta žica izlaz prenosi preko u h11.

Narančasta dovodna žica nosi Q2 preko središnjeg kanala
Narančasta: a15 (Q2) preko u h11 na f–j strani

13. Drugi otpornik od 330 Ω

Iz i11 u i8, nastavljajući lanac na f–j strani.

Drugi otpornik od 330 ohma dodan na f-j strani
Otpornik bita 2, i11 do i8

14. Druga LED-ica, bit 2

Anoda u j8, katoda ovaj put savijena u donju plavu vodilicu, jer ovaj lanac živi na f–j strani.

Žuta LED-ica dodana na f-j strani
Bit 2 gotov: LED-ica koja broji 4

15. Dovodna žica za bit 1

Druga narančasta žica vodi Q1 iz a14 u d8, ostajući na a–e strani.

Druga narančasta dovodna žica dodana za Q1
Narančasta: a14 (Q1) u d8

16. Treći otpornik od 330 Ω

Iz c8 u c5.

Treći otpornik od 330 ohma dodan na a-e strani
Otpornik bita 1, c8 do c5

17. Treća LED-ica, bit 1

Anoda u a5, katoda u gornju plavu vodilicu.

Druga žuta LED-ica dodana na a-e strani
Bit 1 gotov: LED-ica koja broji 2

18. Dovodna žica za bit 0

Q0 je pin 15, na f–j strani u j15, jedini izlaz na toj strani čipa. Bijela žica vodi ga duž do h5.

Bijela dovodna žica nosi Q0 duž f-j strane
Bijela: j15 (Q0) u h5

19. Četvrti otpornik od 330 Ω

Iz i5 u i2, posljednji.

Četvrti otpornik od 330 ohma dodan na f-j strani
Otpornik bita 0, i5 do i2

20. Četvrta LED-ica, bit 0

Anoda u j2, katoda u donju plavu vodilicu. Sva četiri lanca sada su na mjestu:

BitBrojiPin čipaDovodna žica330 ΩAnoda LED-iceKatoda
383 · Q3 (a16)ne trebac16 do c11a11gornja vodilica
242 · Q2 (a15)a15 do h11i11 do i8j8donja vodilica
121 · Q1 (a14)a14 do d8c8 do c5a5gornja vodilica
0115 · Q0 (j15)j15 do h5i5 do i2j2donja vodilica
ℹ️
LED-ice cikcak prelaze središnji kanal umjesto da sjede u jednoj ravnoj liniji. To nije neurednost: Q0 je na suprotnoj strani čipa od Q1, Q2 i Q3, a četiri LED-ice od 10 mm ne ulaze jedna uz drugu u redove koji ostaju. Čitajući duž pločice dalje od čipa i dalje dobivaš bit 3, bit 2, bit 1, bit 0, a to je redoslijed koji je važan.
Sva četiri lanca LED-ica dovršena na breadboardu
Bit 0 gotov: sva četiri lanca na mjestu

21. Utisni USB-C kabel

Gotov krug shift registra sa spojenim USB-C kabelom
Gotov krug

Kako tri pina postaju osam

Shift registar je red od osam memorijskih ćelija s vratima na jednom kraju. DS su vrata. Svaki put kada pin takta ode gore, ono što sjedi na DS pomiče se u prvu ćeliju a svaka ćelija svoj sadržaj predaje sljedećoj. Osam impulsa takta, osam spremljenih bitova.

Kada bi se izlazi mijenjali dok se to događa, gledao bi kako bitovi jure preko LED-ica na putu do svojih mjesta. Ne mijenjaju se, zbog trećeg pina. ST_CP, zaključavanje, drži privatnu kopiju: izlazi nastavljaju prikazivati prethodnih osam bitova dok ne podigneš zaključavanje, a onda se svih osam promijeni u istom trenutku.

To je cijeli trik, i zato skripta svaki krug radi te iste tri stvari:

  1. Povuci zaključavanje nisko da se izlazi prestanu mijenjati
  2. Pozovi shift_out() da pošalje osam bitova, taktirajući svaki od njih unutra
  3. Povuci zaključavanje visoko da ih prikaže sve odjednom

Još dvama pinovima treba reći kako se ponašati, a to su oni koje ljudi zaboravljaju. MR (Master Reset) briše registar kad god je nisko, pa je vezan na visoko. OE (Output Enable) odspaja izlaze kad god je visoko, pa je vezan na nisko. Nijedan nije neobavezan: CMOS ulaz ostavljen da lebdi hvata kakav god električni šum je u blizini i radi kako mu se prohtije.

Vlastito pisanje shift_out()

Arduino ima gotov shiftOut(). MicroPython ne, pa skripta uključuje vlastiti, i vrijedi ga pročitati, jer je to najjasniji pogled na manipulaciju bitovima u cijelom kitu:

def shift_out(value):
for i in range(7, -1, -1):
bit = (value >> i) & 1
data_pin.value(bit)
clock_pin.value(1)
clock_pin.value(0)

Tri ideje rade sav posao:

  • range(7, -1, -1) broji prema dolje: 7, 6, 5, … 1, 0. Tri broja su početak, kraj i korak, a kraj nikada nije uključen, i zato završava na -1 da bi dosegnuo 0. Brojanje prema dolje je ono što šalje najznačajniji bit prvi, a to je redoslijed koji 74HC595 očekuje.
  • value >> i je pomak udesno: pomiče svaki bit broja i mjesta udesno, pa bit koji nas zanima završi na dnu.
  • & 1 je bitovni I s 1, koji zadržava samo taj donji bit i odbacuje sve iznad njega.

Zajedno, (value >> i) & 1 čita bit broj i te vrijednosti, sam za sebe, kao 0 ili 1. Postavljanje data_pin na njega i zatim pulsiranje takta gore i dolje je jedan dostavljen bit.

ℹ️
Budući da podaci ulaze na Q0 i pomiču se dalje, prvi poslani bit putuje najdalje i završi na Q7, dok posljednji poslani bit ostaje na Q0. To je ono što Q0 čini jedinicama, Q1 dvojkama, Q2 četvorkama i Q3 osmicama.

Zašto samo četiri LED-ice? Čip ima osam izlaza, ali counter & 0x0F drži vrijednost unutar četiri bita, pa su Q4 do Q7 uvijek nula. 0x0F je 15, što je u binarnom 1111; spajanje bilo kojeg broja s 1111 na ovaj način zadržava njegova najniža četiri bita a ostalo odbacuje. Pin 9 (Q7') je rezervni bit koji ispada s dalekog kraja. To je ono što bi spojio na DS drugog čipa da nalančaš dva registra u šesnaest izlaza.

ℹ️
counter = (counter + 1) % 16 je isti trik obilaženja koji budilica koristi za sate i minute. % daje ostatak, pa 16 postaje 0 i brojač počinje ponovno.

Kod

from machine import Pin
import time

# Ovo je varijabla kojoj predajemo broj pina na koji smo spojili pin podataka shift registra,
# na čipu označen s DS. To je pin preko kojeg sami bitovi putuju, jedan za drugim.
#
# Zapamti da svakoj od četiri LED-ice na izlazima shift registra treba vlastiti otpornik od 330 ohma u seriji s njom,
# točno kao da je spojena direktno na pločicu.
DATA_PIN = 2

# Ovo je varijabla kojoj predajemo broj pina na koji smo spojili pin zaključavanja shift registra.
# Na čipu 74HC595 taj pin je označen s ST_CP. Zaključavanje je ono što čipu govori "podaci koje sam ti poslao su potpuni,
# prikaži ih sada", i zato se LED-ice mijenjaju sve odjednom umjesto da trepere kroz svaki korak.
LATCH_PIN = 3

# Ovo je varijabla kojoj predajemo broj pina na koji smo spojili pin takta shift registra,
# na čipu označen s SH_CP. Takt je pin koji prebacujemo gore i dolje, i svaki put kada ode gore čip prima jedan
# bit više.
CLOCK_PIN = 4

# Ovdje stvaramo naša tri Pin objekta. Pin.OUT govori pločici da ovi pinovi treba pisati vrijednost umjesto da je
# čitaju, jer sva tri šalju informaciju čipu.
data_pin = Pin(DATA_PIN, Pin.OUT)
latch_pin = Pin(LATCH_PIN, Pin.OUT)
clock_pin = Pin(CLOCK_PIN, Pin.OUT)

# Počni sa sva tri pina u niskom stanju, da čip počne iz poznatog stanja.
data_pin.value(0)
latch_pin.value(0)
clock_pin.value(0)

# Ova varijabla drži vrijednost našeg brojača. U svakom prolazu kroz petlju raste za jedan, a nakon 15 počinje
# iznova od nule.
counter = 0


def shift_out(value):
# Ovo je funkcija koju smo napisali sami, jer ne postoji gotova funkcija za pomicanje bajta van.
# Šalje jedan bajt preko pina podataka, bit po bit, pulsirajući pin takta nakon svakog bita.
# range(7, -1, -1) broji prema dolje od 7 do 0, pa počinjemo s najznačajnijim bitom, dakle onim krajnje lijevim,
# a to je redoslijed koji 74HC595 očekuje.
# Pomicanje vrijednosti udesno za i mjesta i spajanje s 1 pomoću bitovnog I ("&") je način na koji izdvajamo
# pojedini bit koji želimo poslati.
for i in range(7, -1, -1):
bit = (value >> i) & 1
data_pin.value(bit)
clock_pin.value(1)
clock_pin.value(0)


while True:

# Ovdje naš brojač držimo unutar četiri bita. "&" je bitovni I, a 0x0F je heksadekadski način zapisa
# broja 15, koji je u binarnom 1111. Spajanje broja s 1111 na ovaj način zadržava samo njegova najniža četiri bita.
value = counter & 0x0F

# Povlačenje pina zaključavanja u nisko stanje govori čipu da ćemo poslati nove podatke i da svoje izlaze ne bi
# trebao još mijenjati. Bez toga bi LED-ice vidljivo treperile dok bitovi još dolaze.
latch_pin.value(0)

# Pošalji osam bitova naše vrijednosti čipu, koristeći našu funkciju iznad.
shift_out(value)

# Povlačenje pina zaključavanja natrag u visoko stanje govori čipu da su podaci potpuni. Tek se sada izlazi mijenjaju, i
# svih osam mijenja se zajedno.
latch_pin.value(1)

# Ispiši i vrijednost, da broj možeš usporediti s uzorkom upaljenih LED-ica.
print(value)

# Nabroji jedan gore, i počni iznova od nule kada prijeđemo 15, jer četiri LED-ice ne mogu prikazati nikakav broj veći od
# toga. Operator "%" daje ostatak dijeljenja, a to je kratak način obilaženja brojača.
counter = (counter + 1) % 16

# time.sleep() započinje pauzu u kodu, zadanu u sekundama. Pola sekunde je dovoljno sporo da brojanje pratiš
# očima. Slobodno eksperimentiraj s ovom vrijednošću.
time.sleep(0.5)

Što bi trebao vidjeti

Četiri LED-ice broje od 0 do 15 i počinju iznova. Svaki broj drži se pola sekunde, pa jedan cijeli krug traje osam sekundi.

Čitanje broja s LED-ica je pitanje sabiranja onih koje su upaljene. Duž pločice, dalje od čipa, četiri vrijede 8, 4, 2 i 1. Tako je jedna LED-ica sama na dalekom kraju 1; dvije najbliže čipu zajedno su 8 + 4 = 12; kad su sve četiri upaljene to je 15, najveći broj koji četiri LED-ice mogu prikazati, a sljedeći korak nakon toga je natrag na 0.

Za razliku od Arduino verzije ovog projekta, skripta također ispisuje svaki broj kako ga prikazuje, pa možeš provjeriti LED-ice u odnosu na brojanje:

0
1
2
3
4
5

Gledaj LED-icu 1 neko vrijeme i vidjet ćeš uzorak koji binarno brojanje čini funkcionalnim: mijenja se svaki pojedini korak. 2 se mijenja upola rjeđe, 4 ponovno upola rjeđe, a 8 samo dvaput u cijelom krugu. Svaka LED-ica preokreće se točno upola brzine od one prije nje. Ispisana kolona pokazuje istu stvar u brojevima.

Ako se ništa uopće ne pali, iskopčaj USB kabel i provjeri prvo zarez na čipu. 74HC595 postavljen naopako daleko je najčešći uzrok, i vrijedi to brzo uloviti: okretanje čipa s kraja na kraj zamjenjuje redove 14 i 21 preko kanala, pa žica 3V3 sleti na pin 8 (GND) a jumper žica mase sleti na pin 16 (VCC). Čip tada ima napajanje obrnuto, a ne odsutno, što propusno polarizira diodu unutar njega koja je normalno nepropusno polarizirana. Neće raditi, može se osjetno zagrijati, i može se trajno oštetiti, pa ga ne ostavljaj napojenog dok tražiš u čemu je problem. Ako su LED-ice upaljene ali se nikada ne mijenjaju, žica takta ili zaključavanja je u pogrešnom redu; konzola koja broji gore dok LED-ice mirno stoje dokazuje da je greška u spajanju a ne u kodu. Ako se jedna LED-ica nikada ne upali, njezin vlastiti lanac nije u redu, a druge tri dokazuju da je čip u redu.

ℹ️
Pritisak na Stop ostavlja koji god broj je bio prikazan zamrznut na LED-icama. Zaključavanje ga drži, i ništa ga ne briše do sljedećeg pokretanja ili reseta pločice.

Cijeli primjer

Pogledaj cijeli kod primjera na linku ispod:

7.5_Shift_Register.py

Projekt koji pokazuje kako pomoću 74HC595 shift registra upravljati četirima LED-icama kao 4-bitnim binarnim brojačem koristeći samo tri pina NULA MINI.