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

Jak ustawić piny w rejestrze 74HC595 bez zmiany stanu pozostałych pinów?

Jakub17 06 Lis 2016 09:23 1494 24
  • #1 16043024
    Jakub17
    Poziom 6  
    Witam.

    Połączyłem sobie dwa rejestry 74HC595 w kaskadzie i uzyskałem rejestr 16 bitowy.
    Chciałbym uzyskać na tym rejestrze efekt operatora |= tzn. ustawiać każdy pin z osobna bez zmieniania wartości logicznej pozostałych pinów. Napisałem funkcję aktywujPIN(PINx) gdzie argumentem jest wartość decymalna odpowiadająca za zapalenie kolejno każdej diody w rejestrze tak jak poniżej:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Taka konstrukcja niestety wymusza stan wysoki na konkretny pinie a pozostałe zeruje. Mogę oczywiście wpisywać pośrednie wartości decymalne tak jak żeby np. paiły się 2 diody naraz np. 3 co daje mi zapalenie bitu zerowego i pierwszego ale nie o to chodzi... Ktoś na tym forum podsunął mi już pomysł że można to zrealizować za pomocą struktury z polem bitowym lub tablicy i stworzenie czegoś w rodzaju wirtualnego rejestru dzięki czemu do rejestru będzie przesyłana cała tablica a ja bedę mógł stosować operację sumy bitowej. Niestety do końca nie wiem jak to zrobić...

    Kod: text
    Zaloguj się, aby zobaczyć kod


    To nie działa, nie ważne jaki rejestr1.bit wpiszę do funkcji aktywujPIN() zawsze zapala się dioda odpowiadająca z binarną 1,bo tez nic dziwnego bo podaje do funkcji wartosć 1... Nie wiem jak to zrobić żeby np. stosować przesunięcia bitowe na tablicy i zapalać różne diody niezależnie. Ktoś pomoże?

    Funkcja aktywujPIN()
    Kod: text
    Zaloguj się, aby zobaczyć kod
  • #2 16043106
    excray
    Poziom 41  
    Potrzebujesz odwołać się do tych samych danych na różne sposoby. Raz jako do poszczególnych bitów, a innym razem jako do całych bajtów. Ty to wiesz, ale kompilator tego nie wie. Dlatego aby go o tym poinformować trzeba zapoznać się z kolejnym nowym zagadnieniem - unią.
  • #3 16043136
    Jakub17
    Poziom 6  
    Unia to przecież to samo co struktura tylko że na różne typy danych i o rozmiarze największej z tych danych zawartych w unii. Zupełnie nie wiem jak miałoby mi to pomóc. Jakieś wskazówki?

    Myślę że pole bitowe jest najwłaściwszy rozwiązaniem ale nie mam pomysłu jak dobrze przetworzyć to dla kompilatora. Chodzi o to żeby mógł dynamicznie modyfikować zawartość tablicy... Np. tab[0] odpowiada za 8 bitowy rejestr (bity 0-7) a tab[1] odpowiada za 8bitowy rejestr (8-16). Np.

    Kod: text
    Zaloguj się, aby zobaczyć kod


    I to mi nie działa poprawnie.
  • Pomocny post
    #4 16043288
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #5 16044116
    BlueDraco
    Specjalista - Mikrokontrolery
    Masz całkiem źle podefiniowane wszystko. Spróbuj coś takiego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    A potem np.:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #6 16044704
    Jakub17
    Poziom 6  
    BlueDraco napisał:
    Masz całkiem źle podefiniowane wszystko. Spróbuj coś takiego:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    A potem np.:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    Działa! Szkoda że na to nie wpadłem...
    Ale też nie do końca rozumiem Twoje rozwiązanie... Uczę się jezyka C i jak dotąd nie używałem za dużo struktur, a unii w cale. Moje pytanie dotyczy zmiennej rejestr. Ta zmienna istnieje po to by rozszerzyć rozmiar unii i żeby zapisywać do niej elementy struktury? Nie można byloby zamiast tej zmiennej zrobić poza unią tablicę z szesnastu elementów diody.bit.bx typu uint16_t i do niej zapisywać wartości bitów diody.bit.bx? Pytam bo w tej chwili nie mam możliwości tego sprawdzić...
  • Pomocny post
    #7 16044732
    BlueDraco
    Specjalista - Mikrokontrolery
    Nie można. Pole unii rejestr zawiera wszystkie 16 bitów widziane jako jedna zmienna 16-bitowa. Pole bit udostępnia je jako 16 indywidualnych zmiennych 1-bitowych b0, b1 itd.
  • #8 16051553
    Jakub17
    Poziom 6  
    Mam jednak znowu problem:( Borykam się z jednym błędem i jednym warrningiem. Wygląda to tak:

    plik main.c
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    plik rejestr.c

    Kod: text
    Zaloguj się, aby zobaczyć kod


    plik naglówkowy

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Błąd przy zmiennej diody i warrning przy udostępnieniu unii do innych plików. Co tu jest źle?

    Przekopiowanie całej definicji unii do pliku nagłówkowego niby sprawia ze wszystkie ostrzeżenia i błędy znikają, ale zastanawiam się czemu nie działa to za pośrednictwem extern.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • Pomocny post
    #9 16051654
    grko
    Poziom 33  
    @Jakub17 Tak po prostu działa kompilator. To znaczy kompiluje pliki sekwencyjnie i gdy kompiluje plik main nie wie jaki layout ma unia diody ponieważ deklaracja znajduje się w pliku rejestr.c. Aby to działało poprawnie powinieneś przenieść samą deklarację unii do nagłówka. Instancję struktury definiujesz w pliku rejestr.c. W nagłówku dodatkowo robisz extern symbolu związanego z instancją struktury. Podsumowując:

    Nagłówek deklaracja + extern:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    rejestr.c
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Jak to chcesz w ten sposób zrobić to diody nie mogą być nienazwaną unią.

    BTW: Zamiast typu _Bool użyj bool z nagłówka stdbool.h.
  • #11 16056532
    Jakub17
    Poziom 6  
    Mam jeszcze jedno pytanko: Jak udostępnić taką bibliotekę rejestr.h w całym Eclipsie, żeby taka biblioteka stał się równie powszechna co np. takie biblioteki:
    <avr/io.h>,<avr/interrupt.h> czy <util/delay.h>?
    Niestety dodatnie biblioteki poprzez include do zupełnie innego pliku main.c w innym projekcie nie działa, zarówno przez cudzysłów jak i nawiasty <>
  • #12 16056555
    Konto nie istnieje
    Konto nie istnieje  
  • #13 16057079
    grko
    Poziom 33  
    @Jakub17 Jeżeli chcesz stworzyć statyczną bibliotekę z pliku *.c to:
    1. Musisz skompilować plik *.c do pliku *.o
    2. Za pomocą programu ar z pliku *.o (lub wielu plików *.o) tworzysz bibliotekę statyczną.
    3. Umieszczasz taką bibliotekę w znanym katalogu .../lib.
    4. Umieszczasz nagłówek w znanym katalogu .../include
    5. W projekcie w którym chcesz załączać bibliotekę we flagach kompilatora powinieneś mieć podaną scieżkę do katalogu z plikiem *.h: -I.../include
    6. Flagi linkera powinny mieć katalog z Twoją biblioteką (*.a):
    -L.../lib
    7. Podczas konsoloidacji powinieneś podać Twoją bibliotekę: -lNazwaTwojejBiblioteki

    Warto to sobie przećwiczyć ręcznie aby wiedzieć dlaczego poźnej coś nie działa w "ładnym i prostym" IDE.
  • #14 16057874
    Jakub17
    Poziom 6  
    Piotrus_999 napisał:
    1. plik nagłówkowy (*.h) nie jest żadną biblioteką
    2. Aby plik (*.c) zawierający funkcje, które Cie interesują musisz go dodać do projektu, aby został skompilowany i zlinkowany (w Twoim przypadku rejestr.c).

    A robi się to tak import -> file system -> wskazujesz katalog -> wybierasz co Cię interesuje
    Nie musisz kopiować pliku mozesz wskazać aby utworzył tylko link do tego pliku w workspace.


    Jeśli zrobię tak jak mówisz otrzymuje jeden błąd:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Niby nie mam żadnych podkreśleń w kodzie ale przez ten błąd wgranie programu na mikrokontroler jest niemożliwe. Dostałem się do tych lokalizacji które wskazuje komunikat, ale nie wiem co mam tam przekopiować... Plik nagłówkowy rejestr.h? Tutaj jest mowa o -lrejestr.h

    Dodano po 6 [minuty]:

    grko napisał:
    @Jakub17 Jeżeli chcesz stworzyć statyczną bibliotekę z pliku *.c to:
    1. Musisz skompilować plik *.c do pliku *.o
    2. Za pomocą programu ar z pliku *.o (lub wielu plików *.o) tworzysz bibliotekę statyczną.
    3. Umieszczasz taką bibliotekę w znanym katalogu .../lib.
    4. Umieszczasz nagłówek w znanym katalogu .../include
    5. W projekcie w którym chcesz załączać bibliotekę we flagach kompilatora powinieneś mieć podaną scieżkę do katalogu z plikiem *.h: -I.../include
    6. Flagi linkera powinny mieć katalog z Twoją biblioteką (*.a):
    -L.../lib
    7. Podczas konsoloidacji powinieneś podać Twoją bibliotekę: -lNazwaTwojejBiblioteki

    Warto to sobie przećwiczyć ręcznie aby wiedzieć dlaczego poźnej coś nie działa w "ładnym i prostym" IDE.


    Programu ar? Mógłbyś bardziej szczegółowo opisać poszczególne kroki albo zapodać jakieś źródło w którym dobrze to tłumaczą, krok po kroku? Znalazłem taką fajną instrukcję:
    (link pobiera instrukcje pdf)
    http://achilles.tu.kielce.pl/Members/achrobot...010-2011/pdf/jezyk-c-2/jc2_laboratorium_2.pdf

    Jednakże już przy opisie kompilacji do pliku .o opisują tam wpisywanie jakiś komend np. gcc -Wall -c library.c
    Ale nie wiadomo gdzie to wpisać, za pomocą jakiego programu.
  • #16 16058049
    Konto nie istnieje
    Konto nie istnieje  
  • #17 16058787
    BlueDraco
    Specjalista - Mikrokontrolery
    grko napisał:
    BTW: Zamiast typu _Bool użyj bool z nagłówka stdbool.h.


    A to niby dlaczego?

    _Bool jest typem standardowym języka; bool jest protezą, której używano, gdy nie było _Bool w standardzie języka. _Bool zapewnia automatyczną konwersję na wartość 0/1; bool tego nie daje.

    Powyższa rada jest moim zdaniem błędna i szkodliwa,

    Podejrzewam (nie sprawdzałem), że przy próbie podstawienia na 1-bitowe pole typu bool niekoniecznie efekt będzie zbieżny z oczekiwanym, np.

    diody.bit.b0 = PINA & 4;

    dla _Bool zadziała, dla bool wymagana podwójna negacja.
  • #18 16059295
    Konto nie istnieje
    Konto nie istnieje  
  • #19 16059413
    grko
    Poziom 33  
    @BlueDraco Typ _Bool, który jest de facto protezą, został wprowadzony do języka bo w wielu bibliotekach typ bool już był zdefiniowany. Więc użycie _Bool zamiast bool jest zalecane tylko w środowiskach gdzie bool jest już zdefiniowane. Nagłówek stdbool został wprowadzony razem z typem _Bool w C99.

    Reszta Twojego posta tylko próbuje (zresztą nieudolnie) tłumaczyć użycie typu _Bool nad bool. A standard wyraźnie mówi:

    Cytat:

    Section 7.16 Boolean type and values < stdbool.h >
    1. The header <stdbool.h> defines four macros.
    2. The macro bool expands to _Bool.
    3. The remaining three macros are suitable for use in #if preprocessing directives. They are:
    true : which expands to the integer constant 1,
    false: which expands to the integer constant 0, and
    __bool_true_false_are_defined which expands to the integer constant 1.
    4. Notwithstanding the provisions of 7.1.3, a program may undefine and perhaps then redefine the macros bool, true, and false.




    @Piotrus_999
    To może jak nie za bardzo rozumiesz to się nie wypowiadaj. Bo Twój post również nie za bardzo świadczy o tym, że wiesz jak to działa.

    Moderowany przez dondu:

    Proszę szanować kolegów, byśmy nie musieli reagować.

  • #20 16059568
    BlueDraco
    Specjalista - Mikrokontrolery
    A co jeśli bool jest zdefiniowany jako unsigned char dla zachowania zgodności z C sprzed C99 - dość typowy przypadek?

    No to jaka w końcu jest PRZEWAGA bool nad _Bool? Konieczność włączania nagłówka stdbool w celu używania bool zamiast dostępnego bez nagłówka _Bool jakoś nie wygląda mi na zaletę. Osobiście wolę pisać 0/1 zamiast false/true bo szybciej to napisać i lepiej widać stałą, która nie chowa się wśród identyfikatorów pisanych małymi literami.

    Odnoszę wrażenie, że cały Twój post jest zwykłym pozamerytorycznym atakiem. Błąd kol. p999 też można wskazać w mniej niesympatyczny sposób.
  • #21 16059614
    grko
    Poziom 33  
    BlueDraco napisał:
    A co jeśli bool jest zdefiniowany jako unsigned char dla zachowania zgodności z C sprzed C99 - dość typowy przypadek?


    Czasy z przed C99 to rzeczywiście bardzo typowy przypadek.

    BlueDraco napisał:

    No to jaka w końcu jest PRZEWAGA bool nad _Bool? Konieczność włączania nagłówka stdbool w celu używania bool zamiast dostępnego bez nagłówka _Bool jakoś nie wygląda mi na zaletę. Osobiście wolę pisać 0/1 zamiast false/true bo szybciej to napisać i lepiej widać stałą, która nie chowa się wśród identyfikatorów pisanych małymi literami.


    Typ bool to dokładnie to samo co _Bool. 99% programistów używa właśnie stdbool. Ten nagłówek i definicje w nim są również częścią standardu. Dokładnie tego samego, który definiuje typ _Bool. Twoje osobiste preferencje nie świadczą czy czegoś należy używać czy nie.

    Jeden argument, który powinien do Ciebie przemówić: bool się szybciej pisze. A wiadomo powszechnie, że mniej znaków w kodzie przekłada się na szybkość wykonania programu.

    BlueDraco napisał:

    Odnoszę wrażenie, że cały Twój post jest zwykłym pozamerytorycznym atakiem. Błąd kol. p999 też można wskazać w mniej niesympatyczny sposób.


    Może odniesiesz się do swojego poprzedniego posta, który wręcz ociekał merytorycznimi argumentami typu:

    Cytat:

    _Bool jest typem standardowym języka; bool jest protezą, której używano, gdy nie było _Bool w standardzie języka. _Bool zapewnia automatyczną konwersję na wartość 0/1; bool tego nie daje.


    oraz
    Cytat:

    Podejrzewam (nie sprawdzałem), że przy próbie podstawienia na 1-bitowe pole typu bool niekoniecznie efekt będzie zbieżny z oczekiwanym, np.

    diody.bit.b0 = PINA & 4;

    dla _Bool zadziała, dla bool wymagana podwójna negacja.


    Nadal tak twierdzisz?
  • #22 16059834
    BlueDraco
    Specjalista - Mikrokontrolery
    Zdziwłbyś się, małosympatyczny kol. grko, ile kompilatorów różnych od gcc nie implementuje C99 lub przynajmniej w ilu środowiskach C99 nie jest domyślnym standardem języka. Fakt, jeśli bool to to samo, co _Bool, dalej pozostają już wyłącznie preferencje typograficzne. Ja przed C99 nie używałem bool z powodów jak powyżej, a od C99 używam _Bool, bo w razie czego od razu komplilator pyskuje, że go nie ma, zamiast implementować go jako char ze wszystkimi niemiłymi tego konsekwencjami.
  • #23 16060384
    grko
    Poziom 33  
    @BlueDraco Powyżej C99 mając typ _Bool masz również nagłówek stdbool. Nie ma żadnego zagrożenia, że będzie to inaczej zdefiniowane niż nakazuje standard. Nie mam nic przeciwko temu abyś w swoim kodzie używał sobie _Bool. Jednak jak twierdzisz, że ma to jakąś przewagę nad tym co jest w stdbool to jesteś w poważnym błędzie. Uwierz mi, że praca w większym zespole od razu eliminuje tego typu upodobania ;)
  • #24 16060395
    BlueDraco
    Specjalista - Mikrokontrolery
    Przewagę jak widać ma tylko jedną: do _Bool nie trzeba włączać stdbool.h. Poza tym jest tak samo, z dokładnością do przypadku braku zgodności kompilatora z C99.
  • #25 16060436
    grko
    Poziom 33  
    @BlueDraco Widzisz oszczędność przy załączaniu stdbool a nie zauważasz tego, że bool się po prostu wygodniej pisze. Zaiste ciekawe. Nie załączając stdbool nie masz dostępu do definicji true oraz false. Tutaj znowu pewnie argument o oszczędzaniu klawiatury wygrywa. Jakbyś chciał skompilować swój kod pod C++ to już _Bool nie będzie się kompilowało. Po refaktoryzacji _Bool na bool będzie trzeba zamienić wszystkie 1 na true oraz wszystkie 0 na false.

    Cytat:
    _Bool: C99's boolean type. Using _Bool directly is only recommended if you're maintaining legacy code that already defines macros for bool, true, or false. Otherwise, those macros are standardized in the <stdbool.h> header. Include that header and you can use bool just like you would in C++.


    https://www.daniweb.com/programming/software-...t/threads/240998/usage-of-new-keywords-in-c99
REKLAMA