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

Port do pola bitowego [c]

harmichalh 25 Lip 2011 22:23 1695 23
  • #1 9758597
    harmichalh
    Poziom 12  
    Witam.
    Programuję mój mikrokontroler atmega16 i mam problem z zapisem wartości z portu A (wejściowego) do pola bitowego. Używa takiego kodu:
    polebiotwe = PORTA

    Podczas kompilacji pojawia się błąd, że PORTA jest innego typu niż polebitowe. Jakiego typu jest PORTA i w jaki sposób mogę go zapisać do pola bitowego?

    Wiem, że można tak:
    polebitowe.z1 = PORTA0;
    polebitowe.z2 = PORTA1;
    polebitowe.z3 = PORTA2;
    ...
    

    Ale szukam jakiegoś krótszego sposobu.

    Dodam, że jestem początkujący i może problem jest banalny, ale nie dla mnie.
  • #3 9758980
    mirekk36
    Poziom 42  
    A słyszałeś kiedyś o połączeniu unii ze strukturą ? w ogóle o unii ?

    np:

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


    i potem w kodzie gdzieś deklaracja zmiennej:

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


    a potem

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


    natomiast dostęp do bitów

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #4 9759039
    harmichalh
    Poziom 12  
    Mam kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Oto błędy po kompilacji:
    Cytat:
    Build started 1.7.2009 at 03:29:33
    avr-gcc -mmcu=atmega16 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT main.o -MF dep/main.o.d -c ../main.c
    ../main.c:5: error: expected specifier-qualifier-list before 'z0'
    ../main.c: In function 'main':
    ../main.c:21: warning: statement with no effect
    ../main.c:21: error: expected ';' before ':' token
    ../main.c:22: error: 'struct <anonymous>' has no member named 'z1'
    make: *** [main.o] Error 1
    Build failed with 3 errors and 1 warnings...


    Ma to działać tak, że po podłączeniu 5v do PA0 zapali się dioda podłączona do PC7, a jeśli nie to zapali się dioda podłączona do PC6.
  • #5 9759050
    mirekk36
    Poziom 42  
    eeeh no bo zapomniałem przed każdą nazwą bitu dodać uint8_t

    czyli ma być

    uint8_t z0:1
    uint8_t z1:1

    itd - spróbuj

    Dodano po 1 [minuty]:

    harmichalh napisał:

    Ma to działać tak, że po podłączeniu 5v do PA0 zapali się dioda podłączona do PC7, a jeśli nie to zapali się dioda podłączona do PC6.


    Eeeee - no to na prawdę nie wiem po co ci te pola bitowe ;) - toż to przesada na maxa - chociaż można i tak na okrętkę.

    Wystarczyłyby ci zwykłe przesunięcia bitowe i kilka operacji logicznych.
  • #6 9759066
    michalko12
    Specjalista - Mikrokontrolery
    mirekk36 napisał:
    natomiast dostęp do bitów

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

    Stosując anonimowe struktury można pozbyć się tego "bit"
  • #7 9759098
    mirekk36
    Poziom 42  
    michalko12 napisał:
    mirekk36 napisał:
    natomiast dostęp do bitów

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

    Stosując anonimowe struktury można pozbyć się tego "bit"


    Tak, wiem - ale napisałem tak dla porządku przykład - żeby kolega lepiej zaskoczył - bo chyba jeszcze nie widział takich połączeń.
  • #8 9761707
    harmichalh
    Poziom 12  
    Mam taki kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Jednak po przyłożeniu napięcia VCC do PA0 nic się nie zmienia (powinna zgasić się jedna dioda, a zapalić druga). Co jest źle?
  • #9 9762079
    Wojtek75
    Poziom 24  
    harmichalh napisał:
    Co jest źle?
    Podstawy są źle.
    Tym:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    ustawiasz wszystkie piny portu A jako wyjście. Więc jak chcesz sprawdzić jaki stan pojawia się na PA0? Poza tym skoro chcesz wykrywać stan wysoki to czy masz zewnętrzny pull_down podciągnięty do tego portu? Może jakiś schemat.
  • #10 9762128
    mirekk36
    Poziom 42  
    Proszę zwrócić uwagę, że kolega poleceniem

    DDRA = 255;

    1. ustawia kierunek portu A na wyjściowy

    2. potem próbuje wczytać jego zawartość poleceniem PB.bajt = PORTA do zmiennej

    3. jeśli kolega do portu A który jest wyjściem i ma ustawiony stan niski na swoich pinach będzie przykładał stan wysoki za pomocą switch'a to niechybnie w końcu nastąpi przykre uszkodzenie tegoż portu (zwarcie) :(

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


    tak to powinno wyglądać a klawisze podłączone tym razem do portu A powinny zwierać piny wejściowe nie do VCC tylko do GND. Ponieważ domyślnie polecenie PORTA=255; włączyło podciąganie wewnętrznymi rezystorami pinów do VCC, zatem bez wciśniętego klawisza panuje normalnie stan wysoki.

    I dlatego w warunku sprawdzamy czy pojawił się w PB.bit.z0 stan niski teraz a nie jak przedtem wysoki

    proszę spróbować.
  • #11 9762182
    harmichalh
    Poziom 12  

    Wiem co tym robię. Cały port wykorzystam jako linię wejść, więc to jest celowe działanie.

    Wszystko mam podpięte na płytce stykowej i kabelkiem łączę PA0 i VCC procesora.

    To jak mam zaprogramować obsługę wejść?

    Dodano po 5 [minuty]:

    #include <avr/io.h>
    typedef union { 
       uint8_t bajt;
       struct {
          uint8_t z0: 1;
          uint8_t z1: 1;
          uint8_t z2: 1;
          uint8_t z3: 1;
          uint8_t z4: 1;
          uint8_t z5: 1;
          uint8_t z6: 1;
          uint8_t z7: 1;
       } bit;
    } polebitowe;
    int main(){
    	DDRA = 0;
    	PORTA = 255;
    	PORTC = 0;
    	polebitowe PB;
    	while(1){
    		PB.bajt = PORTA;
    		if( PB.bit.z0 == 0 )PORTC = 1;
    		else PORTC = 2;
    	}
    return 0;
    }

    Powyższy kod nie działa. PA0 zwieram do GND
  • #12 9762265
    Wojtek75
    Poziom 24  
    A gdzie ustawiasz kierunek portu C jako wyjście?
  • #14 9762305
    harmichalh
    Poziom 12  
    Aktualny kod:
    #include <avr/io.h>
    typedef union { 
       uint8_t bajt;
       struct {
          uint8_t z0: 1;
          uint8_t z1: 1;
          uint8_t z2: 1;
          uint8_t z3: 1;
          uint8_t z4: 1;
          uint8_t z5: 1;
          uint8_t z6: 1;
          uint8_t z7: 1;
       } bit;
    } polebitowe;
    int main(){
    	DDRA = 0;
    	DDRC = 255;
    	PORTA = 255;
    	PORTC = 0;
    	polebitowe PB;
    	while(1){
    		PB.bajt = PORTA;
    		if( PB.bit.z0 == 0 )PORTC = 1;
    		else PORTC = 2;
    	}
    return 0;
    }
    

    Bez zmian. Nadal świeci się jedna dioda, nigdy nie gaśnie, a druga się nie zapala. Na wypadek gdyby port był uszkodzony próbowałem z portem D i to samo.
  • #16 9762337
    harmichalh
    Poziom 12  
    Działa, a jak mogę wykrywać stan wysoki? Tzn. podpięcie VCC?
  • #17 9762395
    mirekk36
    Poziom 42  
    harmichalh napisał:
    Działa, a jak mogę wykrywać stan wysoki? Tzn. podpięcie VCC?


    Chodzi o wykrywanie klawiszy ???

    Jeśli klawiszy to proszę się zastanowić - po co sobie komplikować życie i na upartego wykrywać stan wysoki ? ;)

    Tak jak jest to pięknie wykorzystujemy wewn. rezystor PullUp i po kłopocie.

    A jeśli na upartego ktoś chce wykrywać stan wysoki to też w sumie żaden problem ale bez zewnętrznego rezystora się już nie obędzie.

    Do każdej linii portu A trzeba dodać rezystor podciągający wejście ale do GND. Wtedy normalnie bez wciśniętego klawisza na wejściu zawsze będzie ZERO - prawda? A gdy się wciśnie klawisz to pojawi się upragniony VCC czyli stan wysoki.

    warto? dla klawiszy ? te rezystory ?
  • #18 9762411
    harmichalh
    Poziom 12  
    Cały PORTA wykorzystam do komunikacji z komputerem przez port LPT i dane z komputera są wysyłane przez stan wysoki. W przypadku klawiszy nie upierałbym się o wykrywanie stanu wysokiego, ale tu mi to jest potrzebne. Więc jak zrobić wykrywanie stanu wysokiego?
  • #19 9762643
    mirekk36
    Poziom 42  
    harmichalh napisał:
    Cały PORTA wykorzystam do komunikacji z komputerem przez port LPT i dane z komputera są wysyłane przez stan wysoki. W przypadku klawiszy nie upierałbym się o wykrywanie stanu wysokiego, ale tu mi to jest potrzebne. Więc jak zrobić wykrywanie stanu wysokiego?


    Ależ w takim przypadku nie robi się żadnego specjalnego wykrywania stanu. Z takim pojęciem to mamy np przy klawiszach, stykach itp.

    A gdy cały port wykorzystujemy jako magistralę danych to po prostu:

    zmienna = PINA;

    i wszystko - w zmiennej masz wszystkie potrzebne ci stany - zera i jedynki jakie nadleciały na port w jakimś tam czasie. Co więc tu wykrywać? Chyba, że czegoś nie rozumiem?
  • #20 9763011
    piotrva
    VIP Zasłużony dla elektroda
    Chodzi chyba o to, że pc zwiera tylko do vcc, a nie ściąga do masy i tu wbudowane pullup nie dają rady. Rozwiązanie to zastosować zewnętrzne rezystory ściągające piny do masy.
  • #21 9763083
    mirekk36
    Poziom 42  
    piotrva napisał:
    Chodzi chyba o to, że pc zwiera tylko do vcc, a nie ściąga do masy i tu wbudowane pullup nie dają rady. Rozwiązanie to zastosować zewnętrzne rezystory ściągające piny do masy.


    Niemożliwe chyba - akurat LPT ładnie bez żadnych pullupów może podawać i podaje zresztą ładnie obydwa stany logiczne. Nie raz z tego korzystałem. Żadnego problemu nie miałem - wyjścia D0-D7 szły wprost np na jakiś bufor 74245 albo 74373 itp
  • #22 9764978
    harmichalh
    Poziom 12  
    Oto mój kod:
    #include <avr/io.h>
    typedef union { 
       uint8_t bajt;
       struct {
          uint8_t z0: 1;
          uint8_t z1: 1;
          uint8_t z2: 1;
          uint8_t z3: 1;
          uint8_t z4: 1;
          uint8_t z5: 1;
          uint8_t z6: 1;
          uint8_t z7: 1;
       } bit;
    } polebitowe;
    int main(){
    	DDRA = 0;
    	DDRC = 255;
    	PORTA = 0;
    	PORTC = 0;
    	polebitowe PB;
    	while(1){
    		PB.bajt = PINA;
    		if( PB.bit.z0 == 1 )PORTC = 1;
    		else PORTC = 2;
    	}
    return 0;
    }
    

    Niestety niezależnie od wartości portu LPT świeci dioda podłączona do pinu PC7. Przewodem połączyłem D0 (z LPT) z pinem PA0 mojego mikrokontrolera i drugim przewodem gnd lpt z gnd mikrokontrolera. Gdy gnd nie jest podpięte świecą obie diody, czego nie rozumiem. Jak mogę przesyłać dane z LPT do mikrokontrolera?
  • #23 9765044
    mirekk36
    Poziom 42  
    harmichalh napisał:
    Oto mój kod:
    #include <avr/io.h>
    typedef union { 
       uint8_t bajt;
       struct {
          uint8_t z0: 1;
          uint8_t z1: 1;
          uint8_t z2: 1;
          uint8_t z3: 1;
          uint8_t z4: 1;
          uint8_t z5: 1;
          uint8_t z6: 1;
          uint8_t z7: 1;
       } bit;
    } polebitowe;
    int main(){
    	DDRA = 0;
    	DDRC = 255;
    	PORTA = 0;
    	PORTC = 0;
    	polebitowe PB;
    	while(1){
    		PB.bajt = PINA;
    		if( PB.bit.z0 == 1 )PORTC = 1;
    		else PORTC = 2;
    	}
    return 0;
    }
    

    Niestety niezależnie od wartości portu LPT świeci dioda podłączona do pinu PC7. Przewodem połączyłem D0 (z LPT) z pinem PA0 mojego mikrokontrolera i drugim przewodem gnd lpt z gnd mikrokontrolera. Gdy gnd nie jest podpięte świecą obie diody, czego nie rozumiem. Jak mogę przesyłać dane z LPT do mikrokontrolera?


    A jak wg ciebie ma się nie świecić. Chociaż tak na prawdę to zadając takie pytanie wypadałoby narysować schemat tego swojego połączenia a nie robić opisy z których mało wynika i sporo trzeba się domyślać. Jednak pomimo to spróbuję się domyślić że dioda podłączona do pinu PC7 jest podłączona katodą a anodą przez rezystor do VCC.

    W związku z powyższym sterowana jest stanem niskim czyli zerem.

    Jak więc chcesz żeby na podstawie tego kodu miała się ona włączać albo wyłączać ???

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


    Przecież zapalasz tylko albo gasisz diody podłączone do pinów albo PC0 albo PC1. Co ma z tym wspólnego PC7 ????

    Dlatego w pewnej książce od początku sugeruję wszystkim żeby nauczyli się stosować poprawne techniki programowania i w takich przypadkach posługiwali się przesunięciami bitowymi do kodu programu. To stosuje się nie tylko dla jakiejś tam teoretycznej zasady dobrego programowania ale po to żeby samemu było wygodnie pisać kod.

    A tu jest właśnie taki idealny przykład jak się nie powinno programować no i przy okazji przykład dlaczego - bo sam autor się myli już w określeniu pinu dla diody LED.

    Ja bym to napisał np tak:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Dodano po 1 [minuty]:

    aha - to return 0; na końcu jest niepotrzebne

    Dodano po 2 [minuty]:

    harmichalh napisał:
    Gdy gnd nie jest podpięte świecą obie diody, czego nie rozumiem. Jak mogę przesyłać dane z LPT do mikrokontrolera?


    I to jest pierwszy krok do uszkodzenia swojego portu LPT gdy nie łączysz masy - zresztą nie tylko LPT ale i być może nawet mikrokontrolera. Więc nie radzę tak robić. Ani nawet podłączać tego w trakcie działania. Najlepiej połączyć LPT z układem - tzn sygnały i masę - a potem włączyć dopiero urządzenie z mikrokontrolerem.

    Dlaczego wtedy świecą ci obie diody - nawet nie ma co się zastanawiać. Dobrze, że dym nie leci ;) gdy masy nie są połączone.
  • #24 9765222
    harmichalh
    Poziom 12  
    Właśnie zauważyłem, że wcześniej źle pisałem i zamiast pisać PC0 pisałem PC7(pod PC0 jest PD7 i stąd ta pomyłka). W załączniku daję schemat. Użyłem przesunięć bitowych, ale nadal coś jest źle bo niezależne od wartości z LPT świecą się obie diody.

    Oto mój kod teraz:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
REKLAMA