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

[Atmega32][C]Przypisanie bajtu danych do dwóch różnych portów

mateo238 27 Paź 2011 21:13 2269 21
  • #1 10072624
    mateo238
    Poziom 10  
    Witam,

    Mam zmienna typu uint8_t i potrzebuje dwa najmłodsze bity ze zmiennej przypisać do portu C (odpowiednio do pinu 6 i 7) pozostałe bity przypisać do portu D (piny od 2 do 7). Jak tego dokonać??

    Liczę na cenne wskazówki.
    Pozdrawiam
  • #2 10072674
    Fredy
    Poziom 27  
    może tak:

    PORTC =( zmienna & ((1<<0) | (1<<1))) << 6;
    PORTD =(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2);
  • #3 10072692
    dondu
    Moderator na urlopie...
    Fredy napisał:
    może tak:
    portc |=( zmienna & ((1<<0) | (1<<1))) << 6;
    portd |=(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2;

    A co gdy na bitach zmiennej będą zera, a na PortC jedynki?

    EDIT:
    Ponieważ zmieniłeś |= na = to następny problem:

    Fredy napisał:
    może tak:
    PORTC =( zmienna & ((1<<0) | (1<<1))) << 6;
    PORTD =(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2);


    młodsze bity portC nadpisujesz zerami, a autor tematu chciał tylko bity 6 i 7.
    podobnie PORTD
  • #4 10072712
    Fredy
    Poziom 27  
    Zanim skorygowałem program już Dondu zareagował .
  • #5 10072713
    mateo238
    Poziom 10  
    Jeżeli bity w zmiennej równe są 0 to na port tez ma isc 0 (chodzi o zapalanie/gaszenie diod podłączonych do portów). Pozostałych bitów nie ruszamy.
  • #6 10072718
    Fredy
    Poziom 27  
    No więc niech autor zapytania określi się, co z resztą bitów?

    Dodano po 1 [minuty]:

    no to :

    PORTC| =( zmienna & ((1<<0) | (1<<1))) << 6;
    PORTD| =(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2);
  • #8 10072762
    mateo238
    Poziom 10  
    Zmienione mają zostać tylko piny portu okreslone na początku. Pozostałe piny portu mają zostać bez zmiany.
  • #9 10072774
    dondu
    Moderator na urlopie...
    mateo238 napisał:
    Zmienione mają zostać tylko piny portu okreslone na początku. Pozostałe piny portu mają zostać bez zmiany.

    No to najpierw trzeba odczytać stan portów za pomocą PORTC i PORTD do zmiennych tempC i tempD, i dopiero na nich zerować bity i dodawać stan tych ze zmiennej, a na końcu wysłać do portów.
  • #10 10072780
    Fredy
    Poziom 27  
    Spróbuj to:

    PORTC&=~((1<<6)|(1<<7);
    PORTD&=~((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7));
    PORTC| =( zmienna & ((1<<0) | (1<<1))) << 6;
    PORTD| =(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2);

    Proszę poprawić swoje posty i kod umieszczać w znacznikach code!
    Robak
  • #11 10072799
    dondu
    Moderator na urlopie...
    Fredy napisał:
    Spróbuj to:
    PORTC&=~((1<<6)|(1<<7);
    PORTD&=~((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7));
    PORTC| =( zmienna & ((1<<0) | (1<<1))) << 6;
    PORTD| =(zmienna & ((1<<2) | (1<<3) | (1<<4) | (1<<5) | (1<<6) | (1<<7)) <<2);

    Takie rozwiązanie, powoduje niepotrzebne generowanie fali prostokątnej na pinach.
    Na przykład PC7 miał wartość 1, w zmiennej także ma wartość 1, ale Ty najpierw go zerujesz. by za chwilę go z powrotem ustawić - i fala gotowa :)
  • #12 10072884
    mateo238
    Poziom 10  
    Więc jak najlepiej rozwiązać tą sytuację??
  • #13 10072894
    dondu
    Moderator na urlopie...
    mateo238 napisał:
    Więc jak najlepiej rozwiązać tą sytuację??


    Podałem:

    dondu napisał:
    No to najpierw trzeba odczytać stan portów za pomocą PORTC i PORTD do zmiennych tempC i tempD, i dopiero na nich zerować bity i dodawać stan tych ze zmiennej, a na końcu wysłać do portów.
  • #16 10073600
    krru
    Poziom 33  
    Tak czy inaczej pozostaje problem odczyt-modyfikacja-zapis. Będzie to realizowane w kilku operacjach, pomiędzy które może np. wejść przerwanie. I jeśli takie przerwanie zmieni coś w porcie to może być problem.
  • #17 10073625
    mirekk36
    Poziom 42  
    krru napisał:
    Tak czy inaczej pozostaje problem odczyt-modyfikacja-zapis. Będzie to realizowane w kilku operacjach, pomiędzy które może np. wejść przerwanie. I jeśli takie przerwanie zmieni coś w porcie to może być problem.


    A skąd pozostaje ten problem - ja tam go nie widzę. Tzn w tym sensie, że po pierwsze nikt tu nie pisał (tzn autor nie pisał) że przerwania będą tu istotne, a po drugie nie ma możliwości realizacji takiego zadania w jednej instrukcji asemblera ;), po trzecie - nawet gdyby miałyby być istotne tu przerwania - czyli taki wymyślony na gorąco przez kolegę problem - to jest coś takiego jak ATOMIC_BLOCK, albo najzwyklejsze w świecie wyłączenie przerwań na czas tej operacji.
  • #18 10073695
    krru
    Poziom 33  
    Autor nie podał, że korzysta z przerwań, ale i nie podał, że nie korzysta. A potem nagle coś co już chodziło (np. multipleksowany wyświetlacz LED) nagle przestanie działać.

    Z tego co wiem, avr potrafi w jednej instrukcji ustawić lub skasować bit, można więc zrealizować serię instrukcji warunkowych do 'przekopiowania' bit po bicie.
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    O ile kompilator wstawi odpowiednie instrukcje na ustawianie/kasowanie bitów taka sekwencja (jak i cały szereg takich if'ow dla kolejnych bitow) jest odporna na modyfikacje PORTD na przerwaniach.
    Wadą jest kolejne (nierównoczesne) ustawianie poszczególnych bitów.
    [/code]
  • #19 10073735
    mirekk36
    Poziom 42  
    Porównaj sobie sposób, który napisałem wcześniej, spójrz do pliku *.lss i sprawdź jak wygląda to w asemblerze, porównaj sobie do dziesiątek operacji, które miałyby się wykonać w tych proponowanych przez ciebie IF'ach. Toż nie dość, że zajęłoby to więcej miejsca, więcej czasu to jeszcze z uwagi na to byłoby jeszcze bardziej narażone na zmiany w przerwaniach które sam wymyśliłeś. Więc to sposób na wyjęcie sobie dywanika spod nóg.

    I jeszcze raz podkreślę, że od takiej operacji którą podałem nie przestanie działać wyświetlacz LED ;) .....

    zresztą spójrz sobie tutaj na to co napisałem w asemblerze:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Wykona się to powiedzmy w czasie ok 20-30 cykli przy taktowaniu 8MHz zajmie powiedzmy ok 3us

    A teraz ty spróbuj sobie rozpisać to swoim sposobem na IF'y i rozbicie wszystkiego na ustawianie pojedynczych bitów i wtedy porównaj.

    Dodano po 10 [minuty]:

    krru napisał:

    O ile kompilator wstawi odpowiednie instrukcje na ustawianie/kasowanie bitów taka sekwencja (jak i cały szereg takich if'ow dla kolejnych bitow) jest odporna na modyfikacje PORTD na przerwaniach.


    Panie kolego odporne na przerwanie to może być ustawienie pojedynczego bitu czy całego rejestru stałą - ogólnie mówiąc coś co jest w stanie wykonać się w ciągu jednego cyklu zegara.

    Ale już twoje stwierdzenie że cała sekwencja jest odporna - to hmmm delikatnie mówiąc ogromne nadużycie ;) bo jak pisałem wyżej - zanim uzyskasz zamierzony przez autora efekt, jedno przerwanie w środku całej sekwencji może zniszczyć całą twoją układankę.
  • #20 10073856
    tmf
    VIP Zasłużony dla elektroda
    Zauważ, że jego sekwencja istotnie może być "odporna" gdyż na raz zmieniany jest atomowo tylko jeden bit, mimo, że zapis sugeruje odczyt portu, to zostanie to przetłumaczone na pojedyncze CBI/SBI, w efekcie rozdzielenie warunków nic nie zmienia - stan pozostałych bitów rejestru w międzyczasie może się dowolnie zmienić, a nie będzie to przeszkadzać.
    Tak więc kolega kruu ma całkowitą rację.
  • #21 10074003
    mirekk36
    Poziom 42  
    tmf napisał:

    Tak więc kolega kruu ma całkowitą rację.


    No tak - trochę się rozpędziłem, rzeczywiście cała taka sekwencja jak pisze kruu będzie odporna na przerwania.

    Tak czy inaczej to już wchodzimy w rozważania wyższości świąt bożego narodzenia nad świętami wielkiej nocy - jeśli przerwania nie mają tu nic do rzeczy.
  • #22 10086599
    mateo238
    Poziom 10  
    Przerwania nie są istotnym elementem. Rozwiązanie zaproponowane przez mirekk36 działa w 100% zadowalająco. Dzięki wszystkim za zaangażowanie.
REKLAMA