Jak działa rejestr przesuwny? Jak można kaskadować rejestry przesuwne tak, aby uruchomić 48 diod LED za pomocą jedynie dwóch linii - zegara i danych? Tutaj postaram się to zademonstrować na przykładzie płytki z elektrośmieci, którą też najpierw przeanalizuję.
Rozpoczynamy zwiad. Na płytce jest 6 układów HC164A oraz jeden 74AHC14D:
Sprawdzamy noty układów, HC164A :
Pierwszy to rejestr przesuwny. Wejście szeregowo, wyjścia równolegle.
Ten rejestr przesuwny ma 8 wyjść a tylko 3 wejścia. Podając odpowiedni sygnał na wejścia, możemy ustawić wedle uznania wyjścia, więc zasadniczo pozwala nam uzyskać więcej pinów IO.
Rejestr przesuwny pamięta to co mu raz ustawimy.
W celu ustawienia jego wyjść podajemy mu sygnał zegara (CLK), zbocze narastające zegara sprawia że pamiętane wartości w rejestrze przesuwają się o miejsce dalej. W tym też momencie następuje pobrania kolejnej wartości (na pierwsze miejsce), stanowi ona rezultat iloczynu logicznego na wejściach A1 i A2.
W uproszczonym zastosowaniu A2 można ustawić na poziom wysoki, wtedy manipulujemy tylko A1 i zegarem (CLK), i w ten sposób wpisujemy dane na kolejne piny wyjściowe rejestru.
Zegar po prostu wykonuje kolejne cykle (ustawiamy na poziom niski, potem na wysoki, itd), a na A1 wystawiamy wedle uznania wartość którą chcemy wpisać na dane miejsce (1 lub 0).
W kodzie będzie to nieco jaśniejsze.
Drugi układ to tylko bramki realizujące funkcję NOT:
W jego środku jest tych bramek kilka, każda na wyjście podaje przeciwny stan logiczny do tego na wejściu:
Teraz trzeba zbadać piny wyprowadzenia.
Odlutowałem złącze:
Najłatwiej jest określić VDD i GND - mamy przecież wyprowadzenia układów. Dodatkowo masa to najczęściej miedziana wylewka na płytce, zasilanie też często może być taką wylewką.
Ustawiamy multimetr w test ciągłości ("pikacz") i badamy, dokąd prowadzi każdy pad, czy przypadkiem nie trafia on do któregoś z pinów układów oznaczonych w nocie katalogowej VDD bądź GND.
W ten sposób zostają zatem tylko 3 sygnały, których podłączenie też zbadałem multimetrem, umieszczając obserwacje na zdjęciu:
Wnioski są następujące, mamy tu trzy sygnały:
- wspólny CLK - prowadzi on do 74AHC14D, który jest w roli bufora, a potem rozwidla się na połączone wspólne zegarowe wejścia układów po prawej i lewej stronie
- wspólny A2 - tak jak zegar, prowadzi do 74AHC14D, który jest w roli bufora, a potem się rozwidla...
- kaskadowy A1 - prowadzi on do A1 pierwszego rejestru przesuwnego
Kolejne piny A1 są podłączane do wyjść QH poprzednich rejestrów przesuwnych, dzięki temu przy kolejno "wsuwamy" bity to ostatni bit, który jest "na wyjściu" nie jest gubiony, tylko przechodzi do kolejnego rejestru.
To co tu mamy, to jest zasadniczo zrobiony "jeden długi rejestr przesuwny" zbudowany z kilku zwykłych rejestrów.
Zostaje jeszcze pytanie po co bramka NOT - pewnie by się obyło i bez niej, podejrzewam, że jest ona tu tylko w roli bufora, by była odpowiednia wydajność prądowa do wysterowania wejść rejestrów. Zresztą, te sygnały przechodzą przez nią dwa razy, więc nie są po tym zanegowane (negacja neguje negację).
Uruchomienie
Zatem szykujemy Arduino, lutujemy kabelki:
Zaglądamy jeszcze do noty katalogowej rejestru, by wiedzieć co wysyłać:
Uprościmy sobie sytuację - te dodatkowe, wspólne wejście ustawimy na stałe na stan wysoki. Operować będziemy tylko zegarem oraz pinem do wpisywania danych.
Wpisujemy nasze piny w kod, tak jak podłączyliśmy:
Kod: C / C++
Ustawiamy je jako wyjścia cyfrowe, ENA na stałe na stan wysoki:
Kod: C / C++
I teraz najważniejsze - wysyłanie danych.
Kod: C / C++
Na razie wysyłam 32-bitową liczbę, w tym przypadku -1, która w reprezentacji bitowej to 0xFFFFFFFF, czyli same zapalone bity, a potem wysyłam same bity zgaszone. Chcę, by coś pomrugało.
Niby coś działa, ale czemu na przemian?
A wiem już, bo przecież te LEDy tam są dwukolorowe... więc tam jest ich w sumie 24*2 = 48 bitów, a ja wysyłam tylko 32 bity. Dodatkowo nie resetuję nic, więc zasadniczo wysyłam najpierw bity [0,31], potem [32, 47] i od nowa [0, 15], i tak się zapętla..
Zbyt pochopnie zrobiłem tę pierwszą próbę, ale już wiem co jest nie tak.
To teraz druga próba. 48 bitów to może być 6 bajtów, więc zrobiłem tablicę. Trochę kusiło też by użyć typu 64-bitowego, ale tablica się przyda do demonstracji. Teraz wysyłam konkretnie 48 bitów, więc liczę, że każda nowa transakcja będzie wpisywać nową osobną kolejkę stanów diod LED.
Kod: C / C++
Jeszcze potrzeba to przetestować - na razie jedna dioda:
Kod: C / C++
Testujemy:
Działa!
Pora na ambitniejszy test. Określiłem eksperymentalnie, że kolory LEDów są na przemian...
Kod: C / C++
Teraz zapalam kolejno czwórki LEDów wedle ich koloru:
To teraz zostało dodać obsługę pojedynczych LEDów... bity powinny być po kolei, trzeba jedynie dopisać ich ustawianie. Pamiętajmy, że to tablica:
Kod: C / C++
Kod demonstracyjny:
Kod: C / C++
Efekt:
I to tyle... teraz można się bawić, wyświetlać jakieś stany urządzenia, itd, bo na "knight rider" tu bym się nie pokusił ze względu na "ghosting", o tym zaraz.
Podsumowanie
Wszystko udało się uruchomić, choć początkowo myślałem, że będą tu 24 LEDy a nie 48, dopiero potem się zorientowałem, że byłby to absurd... mamy 6 rejestrów, każdy po 8 bitów, więc w sumie wychodzi 48 bitów.
Oprócz tego poszło sprawnie.
Rejestry są podłączone kaskadowo ale z punktu widzenia kodu nawet nie musimy o tym pamiętać, one się z automatu zachowują jako jeden duży rejestr.
Chyba jedyny większy problem tutaj jest z tym, że ten konkretny rejestr nie posiada przełącznika "output enable" który by włączał/wyłączał wyjścia, więc jak mu "wsuwamy" bity to przez bardzo krótki okres czasu stany są widoczne na nieodpowiednich diodach. Psuje to efekt animacji i wymaga dodatkowych zabiegów, by to wyglądało dobrze.
Przykładem rejestru przesuwnego z taką funkcją może być 74HC595, w jego przypadku można łatwiej uniknąć potencjalnego "ghostingu" segmentów.
Teraz tylko pojawia się pytanie, do czego wykorzystać ten moduł? Może jakiś wskaźnik, ale co z "ghostingiem"?
PS: To nie było już nasze pierwsze starcie z takim rejestrem, uruchamiałem już w oparciu o niego wyświetlacz 7-segmentowy:
Wyświetlacz 7 segmentowy tunera, uruchomienie z Arduino, rejestr przesuwny
EDIT: Pewnie pojawią się pytania o schemat, więc znalazłem w sieci coś pasującego:
Tyle, że u mnie wszystkie "B" są razem i ja podaję na nie stan wysoki.
Źródło: https://www.amobbs.com/thread-3278926-1-1.html
Fajne? Ranking DIY Pomogłem? Kup mi kawę.