Układy mikrokontrolerów mają ograniczone liczby pinów cyfrowych. Arduino Mega ma ich aż 54 ale np. małe Arduino NANO i popularne Arduino UNO mają ich po 14. To nie jest zbyt wiele biorąc pod uwagę coraz bardziej złożone zadania jakie współcześnie wykonują mikrokontrolery. Często istnieje więc konieczność oszczędnego korzystania z pinów cyfrowych, a czasami nawet potrzeba rozszerzenia liczby pinów. Służą do tego układy rejestrów przesuwnych.
Rejestry przesuwne (przesuwające) (ang. shift register) są cyfrowymi układami umożliwiającymi szeregowe lub równoległe wpisywanie, odczytywanie i przesuwanie informacji. Ze względu na sposób wprowadzania i wyprowadzania danych wyróżnia się następujące rodzaje rejestrów:
W dalszych rozważaniach będziemy zajmowali się rejestrami SIPO.
Rejestry SIPO są zbudowane z kaskady przerzutników (Fig. 1), w których wyjście (Q) każdego przerzutnika jest połączone z wejściem danych (D) następnego przerzutnika w kaskadzie. Wejście szeregowe (SI) jest najczęściej podłączone do mikrokontrolera i za jego pośrednictwem informacja jaką chcemy zapisać w rejestrze, wraz z kolejnymi taktami sygnału zegarowego, jest przekazywana, bit po bicie, do wejścia danych (D) pierwszego przerzutnika. Załóżmy, że mamy do przesłania do rejestru liczbę w układzie dziesiętnym "11". W systemie dwójkowym 4-bitowe słowo takiej liczby będzie wynosiło 1011
. Pierwsza "1
" tego słowa od lewej to tzw. najbardziej znaczący bit (MSB), zaś ostatnia jedynka od lewej to tzw. najmniej znaczący bit (LSB). W pierwszym narastającym zboczu sygnału zegarowego pierwszy bit przekazywanej porcji informacji (LSB) - "1
" pojawia się na wyjściu pierwszego przerzutnika (QA), W kolejnym zboczu narastającym sygnału zegarowego, drugi bit przekazywanego słowa (także "1
") pojawia się w przezrzutniku 1-szym, zaś bit z wyjścia Q1 jest przesuwany do przerzutnika drugiego i pojawia się na wyjściu QB. W trzecim takcie sygnału zegarowego na wejściu D pierwszego przerzutnika pojawia się 3-ci bit przekazywanego słowa (tym razem jest to "0
"). LSB w tym czasie jest przekazywany do trzeciego przerzutnika, zaś 2-gi bit słowa do drugiego. Po czterech impulsach zegarowych pierwszy bit danych (LSB) zostaje przesłany do czwartego przerzutnika, zaś MSB ("1
") pojawia się na wyjściu QA pierwszego przerzutnika. W rezultacie wejście szeregowe (SI) jest konwertowane na równoległe dane wyjściowe pojawiające się w QD, QC, QB i QA. Należy zauważyć, że gdyby funkcje przerzutników ograniczyć tylko i wyłącznie do przedstawionego schematu to na wyjściach przerzutników ciągle pojawiałyby się różne stany pośrednie generowane podczas przesuwania sygnałów cyfrowych. Nam zależy jednak na czymś innym - na tym aby na wyjściach pojawiały się całe przekazywane słowa (np. rozpatrywany ciąg 1011
). Dlatego, w praktyce, przedstawiony schemat jest rozszerzony o tzw. zatrzask - sygnał sterujący, którego wartość "1
" umożliwia przekazanie sygnałów zapisanych w przerzutnikach na ich wyjścia QA-QD. Szerzej zostanie to opisane poniżej.
Rejestry przesuwające produkowane są w postaci układów scalonych. Jednym z najbardziej popularnych takich układów jest 74HC595 (Fig. 3). Jest to 8-bitowy rejest SIPO. Można go wykorzystać do jednoczesnego sterowaniania 8 wyjściami cyfrowymi QA-QH (piny 1-7, 15). Układ może być zasilany napięciem z przedziału od 2-6V, które podłączamy do pinu 16-go (Vcc). Pin 8 rejestru przesuwnego 74HC595 podłączamy do masy.
Pin | Symbol | Funkcja |
---|---|---|
1-7, 15 | QA-QH | wyjścia cyfrowe; QH - LSB, QA - MSB |
8 | GND | masa |
9 | QH' | wyjście szeregowe, połączenie z ew. kolejnym rejstrem przesuwnym |
10 | SRCLR | główny reset rejestru wyzwalany niskim stanem logicznym (LOW) |
11 | SRCLK | zegar rejestru przesuwnego |
12 | RCLK | zatrzask (ang. latch) |
13 | OE | (ang. output enable) (zwykle podłączamy do GND) |
14 | SER | wejście danych bitowych (np. z Arduino) |
16 | Vcc | zasilanie układu |
Dane są przekazywane do rejestru za pośrednictwem wejścia szeregowego na pinie 14-tym (SER). Gdy podamy na nie stan wysoki ("1
"), w pierwszym rejestrze zapamiętany zostanie (choć póki co nie pojawi się na wyjściu) stan wysoki ("1
"). Gdy podamy na nie stan niski ("0
") to w pierwszym rejestrze zapamiętany zostanie stan niski ("0
"). Do sterowania rejestrem służą cztery piny (10, 11, 12 i 13). Trzy z nich, tj. 11, 12 i 13 podłączamy do cyfrowych wyjść mikrokontrolera, np. Arduino. Wykorzystując ten rejestr jako rozszerzenie mikrokontrolera możemy więc zyskać 8 - 3 = 5 dodatkowych wyjściowych pinów cyfrowych. Pin 11 (SRCLK) służy do przesuwania stanów rejestru w prawo. Wyzwala go zmiana stanu logicznego z niskiego ("0
") na wysoki ("1
") (zbocze narastające). Taka sekwencja jest równoznaczna z poleceniem "przesuń stany rejestru". Na pin ten podawany będzie sygnał zegarowy, który jest konsekwentnym, naprzemiennym ciągiem zer i jedynek o ustalonej częstotliwości. Pin 12 (RCLK) to zatrzask (ang. latch). Odświeża on wyjście układu scalonego. Jak już wspomniano, po przesłaniu danych do rejestru nie pokażą się one automatycznie na wyjściach. Będzie tak dopóki na pin zatrzasku RCLK nie zostanie podany stan wysoki ("1
"). Podanie na to wejście stanu niskiego ("0
") spowoduje zablokowanie wyjść przerzutników QA-QH, co zapobiegnie pojawianianiu się na nich stanów przejściowych (zanim do rejestru nie zostanie wprowadzone całe 8-bitowe słowo). Stan wysoki ("1
") będzie więc typowo podawany na wejście zatrzasku rejestru po wprowadzeniu do niego całego bajta danych. Wejście 13 (OE - en. Output Enable) w układzie 74HC595 to wejście aktywujące wyjścia układu. Gdy sygnał na wejściu OE jest w stanie wysokim ("1
"), to wyjścia układu są wyłączone i nie przekazują danych. Natomiast gdy sygnał na wejściu OE jest w stanie niskim ("0
"), to wyjścia układu są aktywne i przekazują dane. Pin 10 układu (SRCLR) to wejście służące do czyszczenia rejestru przesuwnego. Ma ono charakter asynchroniczny, co oznacza, że jest niezależne od sygnału zegara i może być aktywowane w dowolnym momencie pracy układu. Podczas normalnej pracy rejestru podajemy na nie stan wysoki ("1
"). Jednak gdy chcemy zresetować zawartość rejestru przesuwnego i wszystkich wyjść układu do stanu początkowego ("00000000
") podajemy na to wejście stan niski ("0
").
Zbudujmy układ, którym za pomocą przycisków będziemy mogli sterować zachowaniem rejestru przesuwnego 74HC595 (Fig. 4). Schemat układu przedstawia Fig. 5.
Układ będziemy zasilali napięciem 5V (Fig. 5). Do sterowania rejestrem 74HC595 będzimy używali czterech wejść: danych (SER), zegarowego (SRCLK), zatrzasku (RCLK) i resetu (SRCLR). Potrzebujemy zatem czterech przycisków montażowych (S1-S4). Sterowanie przyciskami będzie polegało na zmianie potencjału sygnałów sterujących rejestrem - odpowiednio do poziomu wysokiego ("1
") - 5V lub do staniu niskiego ("0
") - GND. Zastosujemy więc cztery rezystory podciągające (pull-up) / ściągające (pull-down) (R1-R4). Trzy wejścia rejestru (SER, SRCLK i RCLK) na stałe będą miały podłączone stany niskie ("0
"), a dopiero naciśnięcie przycisków sterujących ich sygnałami będzie powodowało podanie na nie stanu wysokiego ("1
"). Zapewnią to rezystory pull-down R1-R3. Tylko jedno wejście rejestru (SRCLR) wymaga podawania na niego stale sygnału wysokiego ("1
"), a tylko w chwili resetu - sygnału niskiego ("0
"). Ten przycisk wymaga użycia rezystora pull-up - R4. Aby zminimalizować wpływ drgania styków przycisków (ang. debouncing) zastosowano proste filty RC. Składają się one z pary elementów: rezystor (R5-R8) i kondensator (C1-C4). Zadaniem kondensatorów jest niwelowanie efektu drgań styków i wygładzanie przebiegów sygnałów podczas wciskaniu przycisków. Rolą rezystorów R5-R8 jest ograniczanie prądu szpilek napięciowych powstających podczas rozładowywania kondensatorów C1-C4. Do wyjść rejestru QA-QH podłączono osiem czerwonych diod LED z rezystorami R9-R16 o wielkości 150Ω ograniczającymi prąd do 20mA. Fig. 6 przedstawia płytkę prototypową układu. Dla sygnału resetu zrezygnowano w nim z obwodu RC. Można było to zrobić bo to wejście asynchroniczne. Wystarczy, że tylko raz pojawi się na nim sygnał niski ("0
") i rejestr ulegnie wyczyszczeniu.
Układ umożliwia wygodne testowanie rejestru. Do jego zasilania wykorzystano ogniwo Li-Jon 18650 oraz małą przetwornicę step-up podwyższającą napięcie ogniwa 4,2V do 5V. Na wejście danych rejestru (SER), w kolejnych taktach zegara (SRCLK) będziemy podawali kolejne bity danych tworzących 1-bajtowe słowa. Wyobraźmy sobie, że chcemy wprowadzić do rejestru słowo 00110011
. Zaczynamy od bitu LSB ("1
"). Aby go wprowadzić do rejestru należy nacisnąć przycisk DATA oraz równocześnie CLK, Następny bit to także "1
" więc ponownie naciskami DATA+CLK. Trzeci i czwarty bit to stany "0
". Na wejście danych rejestru na stałe podpięta jest masa układu (GND), występuje tam więc niski stan logiczny ("0
"). Wystarczy więc dwukrotnie nacisnąć przycisk zegara CLK. Piąty i szósty bit to stany "1
". Musimy więc ponownie równocześnie nacisnąć kombinację przycisków DATA+CLK. Na koniec mamy dwa bity "0
". Na linii sygnału DATA, dzięki rezystorowi ściągającemu R1 mamy normalnie sygnał "0
", wstarczy więc dwukrotnie nacisnąć sygnał zegarowy i dwa bity "0
" zostaną przesłane do rejestru. Po wprowadzeniu całego bajta danych musimy użyć przycisku zatrzasku (LATCH) aby zapisane dane wyprowadzić na wyjścia układu (QA-QH). Po jego naciśnięciu dane powinny zostać wyświetlone za pomocą diod LED. Jesteśmy gotowi do wprowadzenia do rejestru kolejnego bajta danych. Jeśli coś poszło nie tak możesz zresertować rejestr przyciskiem RESET. Aby wynik wyzerowania rejestru został wyświetlony przez diody LED należy jeszcze nacisnąć przycisk LATCH. Ewentualne błędy mogą być spowodowane debouncingiem, którego do końca nie udało się wyeliminować.
Kolejny projekt będzie układem wykonanym na bazie mikrokontrolera Arduino NANO (Fig. 7). Będzie on w pętli, za pomocą transmisji szeregowej przesyłał do rejestru przesuwnego liczby z zakresu 0-255. Rejestr będzie je następnie wyświetlał za pomocą 8-miu diod LED. Zbudujmy układ pokazany na Fig. 8.
Układ będzie zasilany przez USB. Jego sercem będzie mikrokontroler Arduino Nano. Równolegle do zasilania podłączamy kondensator ceramiczny 100nF wygładzające chwilowe anomalie napięcia. Elementami wyjściowymi będzie pakiet ośmiu czerwonych diod LED. Ich anody poprzez rezystory 150Ω podłączamy do wyjść rejestru przesuwnego 74HC595 QA-QH. Katody diod LED podłączamy do masy. Pin 16 rejestru przesuwnego (Vcc) podłączamy do magistrali zasilającej 5V, zaś pin 8 (GND) do masy. Dane wejściowe będą z pinu D4 mikrokontrolera podawane na wejście SER (14) rejestru przesuwnego. Pin zegarowy rejestru 11 (SRCLK) podłączamy do pinu D2 mikrokontrolera, zaś pin zatrzasku 12 (RCLK) do pinu D3 Arduino. Na pin resetu rejestru SRCLR (10) będziemy podawali stan wysoki ("1
"), który uniemożliwia resetowanie, dlatego podłączamy go na stałe do magistrali zasilającej +5V. Wejście 13 rejestru (OE) podłączamy na stałe do masy.
// The project converts decimal numbers from the range of 0-255 // to binary form and displays them using LED diodes #define DATA 4 #define CLOCK 2 #define LATCH 3 void setup() { pinMode(DATA, OUTPUT); pinMode(CLOCK, OUTPUT); pinMode(LATCH, OUTPUT); } void loop() { int i; for(i=0; i<=255; i++){ digitalWrite(LATCH, LOW); shiftOut(DATA, CLOCK, LSBFIRST, i); digitalWrite(LATCH, HIGH); delay(200); } }