logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Jak poprawnie połączyć rejestry 74HC595 w kaskadę? Kod programu AVR SPI

Jakub17 04 Lis 2016 18:46 1767 15
REKLAMA
  • #1 16039907
    Jakub17
    Poziom 6  
    Witam.

    Mam problem z połączeniem rejestrów 74HC595 w kaskadę. Niby robie tak jak opisano w książkach i jak podaje się na internecie ale nadal nie wychodzi. Może najpierw kod programu (kod zawiera sprzętową i programową obsługe SPI, korzystam ze sprzętowej) :


    Kod: text
    Zaloguj się, aby zobaczyć kod



    Poniżej schemat mojego połączenia (mam nadzieję że jest dość czytelny):

    Jak poprawnie połączyć rejestry 74HC595 w kaskadę? Kod programu AVR SPI

    Połączenia G,RCK,SCK,SCLR w dolnym rejestrze są takie same jak w górny tzn. np. RCK dolnego rejestru do RCK górnego rejestru itp. Nie wrysowywałem tych połączeń żeby nie zaciemniać rysunku. Co jest tu istotne to połączenie Qh górnego rejestru z Serial Input (SI) dolnego rejestru. W ten sposób tworzy się kaskadę, tak? Czyli tak mogę uzyskać rejestr 16 bitowy, tak? Bo łącząc SI dolnego rejestru z SI górnego rejestru otrzymałbym dwa rejestry 8 bitowe szeregowe gdzie to instrukcje wysłane do górnego rejestru są identyczne dla dolnego rejestru, tak? Tak to rozumiem...

    Do pinów wyjściowych rejestrów QA-QH podłączone sa diody.

    Wgrywając do rejestrów wartość cnt=65535 powoduje że wszystkie diody się zapalają, jest ok, fajnie. 16 bitów zapalonych. Ale gdy w następnej instrukcji chce żeby zapaliła się 1 dioda z całego rejestru 16 bit to na dolny rejestrze zapala się ta jedna dioda, a górny w ogole nie gaśnie... cały czas na górnym rejestrze pali się 8 diód. Gdy resetuję mikrokontroler 8 diod z górnego rejestru gaśnie a pali się ta jedna z dolnego rejestru czyli tak jak być powinno dla cnt=1. Ale gdy w następnej turze wgram np wartosć cnt=4 to zapalają się odpowiednie diody dolnego rejestru no i cały górny rejestr i nie gaśnie aż do kolejnego resetu mikrokontrolera. Tak jakby górny rejestr zatrzaskiwał się na amen bez względu na sygnał zatrzaskiwania z mikrokontrolera.Mało tego... Nie pomaga nawet reset samego rejestru poprzez zwarcie pinu SCLR do masy(diody cały czas się palą). Co robię źle? Program jest raczej ok, myslę że to kwestia złego podłączenia...


    Dokumentacja rejestrów jakich używam:

    http://www.st.com/content/ccc/resource/techni...df/jcr:content/translations/en.CD00000339.pdf
  • REKLAMA
  • REKLAMA
  • #3 16040004
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #4 16040188
    Jakub17
    Poziom 6  
    To może powiem o co mi docelowo chodzi...

    Program jest przykładowy. Wziąłem go jedynie do testów aby sprawdzić czy połączenia rejestrów są poprawne.
    A chodzi mi o stworzenie takiej uniwersalnej biblioteki, gdzie pinom rejestrów przypisze nazwy i będę je mógł ustawiać na stan wysoki poprzez polecenie np. (1<<QA), gdzie QA to zdefiniowany konkretny pin. Nie bardzo rozumiem... Wysyłam zmienną bajt o pojemności 16 bitów i nie otrzymuje żądanego rezultatu... więc co, mam wysłać najpierw jedną parę 8 bitów a później kolejne 8 bitów? Nie moge naraz wysłać 16 bitów?

    Dodano po 11 [minuty]:

    Marek_Skalski napisał:
    0. Ten program tylko raz wysyła dane do rejestrów, ponieważ zakomentowałeś while(1). Reset powoduje wygenerowanie dodatkowe impulsu dla zatrzasku.


    Fakt, teraz działa. Z tym że gdy wysyłam cnt=1 to na obu rejestrach pali się jedna dioda, czyli na obu rejestrach jest to samo... Jak mam zrobić żeby te dwa rejestry były traktowane jak jeden 16 bitowy. Muszę wysyłać 2 bajty w którym jeden będzie 0b0000000 a drugi 0b00000001?
  • Pomocny post
    #5 16040221
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #6 16040835
    Jakub17
    Poziom 6  
    Dzięki serdeczne za pomoc:)

    Dodano po 44 [minuty]:

    Tak się zastanawiam na temat tego sprzętowego SPI...

    Skąd program ma wiedzieć kiedy następuje zakończenie przesyłania bajtu tzn. kiedy następuje przerwanie petli while(cnt) i przepisanie wartości na wyjście? Licznik cnt ciągle przesuwa bit od najmłodszego do najstarszego, dochodzi do najstarszego przekracza go i zaczyna zliczać od początku, w pętli while jest cały czas wartość dodatnia i wykonuje się ona w nieskończoność... Co pominąłem w tym rozumowaniu?
  • #7 16040909
    tronics
    Poziom 38  
    Sprzętowe SPI przesuwa 8 bitów i koniec, dlatego masz dwa wywołania funkcji - najpierw młodsze 8bitów, później starsze. W soft spi wysyłasz tak długo, aż wartość cnt nie będzie równa 0 . Przesuwanie "wciska" od lewej strony 0 więc gdy miałeś np. cnt=0b10000000 to wykona się to 8 razy bo ta jedynka będzie się przesuwać w prawo więc po wykonaniu pętli dla cnt=0b00000001 wartość cnt zmieni się na 0b00000000 i pętla while będzie przerwana. W podobny sposób będzie w przypadku wysyłaniu wartości 16bitowej i uint16_t cnt=0x8000. Tylko czytelnie, jawnie przedstawienie co chcemy osiągnąć jest w formie zaprezentowanej wyżej przez Marka, w pętli FOR.
  • #8 16040921
    Jakub17
    Poziom 6  
    Dzięki za wytłumaczenie. Mam jeszcze jedną zagwozdkę. Teraz mogę wysyłać dane do rejestru ale jak je odbierać do mikrokontrolera?
    Znalazłem informację że połączenie linii MISO z Q'h da mi odczyt poprzedniego stanu rejestru, przed wprowadzeniem nowych dany. Da się to programowo rozwiązać abym mógł zczytywać aktualnie panujący stan na rejestrze?
  • #9 16040942
    tronics
    Poziom 38  
    Ale po co chcesz odczytywać stan z rejestru do którego się dane wsunęło? Przecież wystarczy dodać zmienną przechowującą ostatnio wysłaną zawartość. Twoje podejście jest takie... wysyłam paczkę do Warszawy, wiem co wysyłam... ale za 5 minut nie będę pamiętał więc jadę do Warszawy zobaczyć co w paczce. Po co? Wysyłam paczkę do Warszawy, a na karteczce samoprzylepnej piszę co wysyłam. Jak będę potrzebował wiedzieć co wysłałem to zerkam na karteczkę. Jak wysyłam następną paczkę, to tą karteczkę usuwam i piszę nową. Mogą być sytuacje głównie zw. z zakłóceniami (czyli błąd projektowy) gdzie zawartość rejestru ulegnie przez zakłócenia zmianie. Wtedy jeśli to jest np. wyświetlacz LED zamiast spodziewanego obrazu będzie zmieniona zawartość. Ale to żaden problem jeśli będziemy cyklicznie odświeżać zawartość ekranu (czyli wysyłać cały bufor na wszystkie rejestry w kaskadzie) to nawet takie jednostkowe "glitche" będą tylko drobną uciążliwością. Co nie znaczy, że temat można zupełnie olać.
  • #10 16041017
    Jakub17
    Poziom 6  
    No tak w sumie racja. Wystarczy jednak to połączenie MISO z Q'h. Dążę do tego by osiągnąć coś w rodzaju:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Tak aby pobierać również dane z zewnątrz do mikrokotrolera.
    Napotykam znowu na problem ponieważ w przypadku rejestrów nie działa operacja na wzór takiej:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    tzn. dzięki operatorowi |= aktywowanie kolejnego pinu bez zmiany pinów aktywowanych poprzednio. Nie wiem jak przenieść funkcje tego operatora na moje rejestry. W pierwszej chwili przyszedł mi do głowy głupi pomysł zrobienia tablicy z konfiguracją poszczególnych pinów ale zrobić tablice na 65535 możliwości... hmmm;p No oczywiście nawet i bez tablicy mógłbym zrobić tak aby wpisywać odpowiednie liczby które po przełożeniu na kod binarny pozwolą mi zapalać kolejne "bity" przy zachowaniu tych poprzednich, ale chodzi o to aby nie myśleć jaką dokladnie liczbę wpisać tylko jak w przypadku operatora |= rozwiązywać sprawę za jednym zamachem.Niestety nie da się nakładać na siebie stanów przerzutników które są w rejestrze, więc nie mam pojęcia jak to zrobić.Czy to co chcę osiągnać w ogole jest możliwe na rejestrach?


    A może istnieją jakieś inne układy, na których zrealizuje w pełni funkcjonalny PORT i REJESTR będący imitacją tego z mikrokontrolera?
  • #11 16041067
    Konto nie istnieje
    Poziom 1  
  • #12 16041167
    Jakub17
    Poziom 6  
    Nie wiem czy się zrozumieliśmy dobrze....

    Stanęło u mnie na tym:

    Kod: text
    Zaloguj się, aby zobaczyć kod



    Chodzi mi o to że gdy załącze tą funkcje jako bibliotekę i później w kodzie głownym programu użyję zmiennej x i y np:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    to uzyskam zapalenie np. diody na PIN12 i na PIN16. Poźniej np. wygaszę pin 12
    Kod: text
    Zaloguj się, aby zobaczyć kod

    A pin 16 nadal bedzie się palił.
    Jeżeli np. w mikrokontrolerze wydam polecenie:
    Kod: text
    Zaloguj się, aby zobaczyć kod

    To zapalę pin 0 a wygaszę pozostałe, dlatego stosuje się operator |=.
    Chcialbym uzyskiwać ten sam efekt operatora |= tylko że na rejestrach tzn. zapalając zdefiniowane PINy rejestru jak np. PIN12 i PIN16

    Oczywiście moge użyć odpowiedniej wartości decymalnej która po przełożeniu na kod binarny zapali mi te diody, następnie użyć innej wartości binarnej która wygasi mi jedną diode a drugą zachowa, ale nie o to chodzi by tworzyć przeróżne kombinacje poprzez #define tylko uzyskac efekt operatora |=
  • #13 16041169
    tronics
    Poziom 38  
    Jak rozumiem kolega ma przykładowo (całkiem przykładowo żeby zobrazować problem) 4 cyfrowy wyświetlacz 7seg. Pod każdą cyfrę osobny rejestr przesuwny. I teraz największym problemem dla niego jest zmodyfikować np. 3 cyfrę bez zmiany pozostałych. A odpowiedź jest prosta... nie da się tego w ten sposób zrobić w daisy chain. Musisz mieć np. tablicę gdzie poszczególne elementy tej tablicy odzwierciedlają wartości rejestrów przesuwnych. I potrzebujesz coś zmienić w 3 rejestrze? Nie ma problemu, zmieniasz odpowiadający mu element tablicy, ale wysyłasz CAŁOŚĆ - odświeżasz cały łańcuch rejestrów. Operacje na tych elementach są takie same jak na rejestrach portów. Tyle tylko że programista musi dbać o wysłanie uaktualnionej tablicy na rejestry przesuwne, gdy zmiana w rejestrze portu jest automatycznie dokonywana na porcie.
  • #14 16041177
    Jakub17
    Poziom 6  
    tronics napisał:
    Jak rozumiem kolega ma przykładowo (całkiem przykładowo żeby zobrazować problem) 4 cyfrowy wyświetlacz 7seg. Pod każdą cyfrę osobny rejestr przesuwny. I teraz największym problemem dla niego jest zmodyfikować np. 3 cyfrę bez zmiany pozostałych. A odpowiedź jest prosta... nie da się tego w ten sposób zrobić w daisy chain. Musisz mieć np. tablicę gdzie poszczególne elementy tej tablicy odzwierciedlają wartości rejestrów przesuwnych. I potrzebujesz coś zmienić w 3 rejestrze? Nie ma problemu, zmieniasz odpowiadający mu element tablicy, ale wysyłasz CAŁOŚĆ - odświeżasz cały łańcuch rejestrów. Operacje na tych elementach są takie same jak na rejestrach portów. Tyle tylko że programista musi dbać o wysłanie uaktualnionej tablicy na rejestry przesuwne, gdy zmiana w rejestrze portu jest automatycznie dokonywana na porcie.


    A no własnie tylko stworzenie tablicy która uwzględni wszystkie możliwości jest prawie niemożliwe... Czyli rozumiem ze nie da się tego zrobić na rejestrze 74HC595. A istnieją jakieś układy za pomoca których to osiągnę? Chodzi mi po prostu o sztuczne zwiększenie dostepnych pinow w mikrokontrolerze przy zachowaniu ich pełnej funkcjonalności tzn. możliwości stosowania na nich operatorów bitowych.
  • #15 16041217
    tronics
    Poziom 38  
    Cytat:
    A no własnie tylko stworzenie tablicy która uwzględni wszystkie możliwości jest prawie niemożliwe

    Jest możliwe tylko niepraktyczne. Możliwości jest 256 (0-255) na każdy rejestr przesuwny i jeśli już ktoś bardzo by chciał może sobie taką tablicę machnąć, tylko jaki w tym sens? Jeszcze raz napiszę... w mikrokontrolerze SPRZĘTOWO zapewniona jest synchronizacja stanu pinów danego portu po zmianie zawartości rejestru tego portu. W przypadku JAKICHKOLWIEK rozwiązań w postaci układów dodatkowych (czy to ekspander i2c, spi, czy rejestry przesuwne) MY musimy kontrolować co i kiedy wysyłamy. Co wysyłamy jest proste do ogarnięcia - to jest właśnie ta tablica reprezentująca cały łańcuch rejestrów. Najgorzej jest kiedy wysyłamy. Bo albo robimy to cyklicznie dzięki np. przerwaniu co 1ms, albo operujemy na elementach tablicy funkcją, która sprawdza czy doszło do zmiany i jeśli tak wysyła aktualizację po SPI do rejestrów przesuwnych.
  • #16 16041223
    Konto nie istnieje
    Poziom 1  
REKLAMA