Strony

czwartek, 13 marca 2014

Maskowanie bajtów - z przymrużeniem oka ;)

Witam,

Chciałbym dzisiaj zaprezentować wam krótki film, ale Uwaga! dozwolony od lat 19,5 ! (tylko dla widzów o mocnych nerwach). Proszę także o wyrozumiałość dla mnie. Ale dobrze - nie uprzedzajmy faktów. Ten mini poradnik będzie dotyczył kwestii maskowania bajtów, tzw masek bitowych. Podejmuję się w taki dość hmm niekonwencjonalny sposób wyjaśnienia - jak można spojrzeć na to zagadnienie chłodnym okiem. No właśnie, w zasadzie wszystko w tym poradniku kręci się wokół oka ;) .... Kłopot jednak, wśród wielu początkujących polega na tym, że czasem dość długo nie mogą zrozumieć pojęcia maskowania, co to znaczy to maskowanie? jaka to operacja i co ona ma na celu ? - pomimo iż niejednokrotnie widzą przykłady programowe. Mimo to ciężko im czasem przejść dalej .... dokąd nie zrozumieją raz na dobre w czym rzecz. Dlatego mam nadzieję, że tym poradnikiem, którego proszę traktować również z przymrużeniem oka, uda mi się ostatecznie rzecz wyjaśnić a maskowanie na zawsze stanie się przejrzyste i zrozumiałe ;)


zapraszam na film:


;)

23 komentarze:

  1. Ja to zagadnienie rozumiem, ale nie popieram. "C" jest prawie tak samo wredny jak jedna moja sąsiadka, która wdziewa różne maski aby powiedzieć coś nie wprost.
    Pozdrawiam kolegę Mirka i jak zwykle życzę szczęścia, zdrowia, pomyślności :)
    Zenowi

    OdpowiedzUsuń
    Odpowiedzi
    1. Również pozdrawiam ;) ... i jak zwykle podziwiam upór szanownego kolegi do naszego ulubionego języka C ;) .... ale ja i tak wierzę, że kiedyś ... że przyjdzie taki czas, że kolega się zmieni i zostanie zaczarowany przez C.

      Usuń
  2. Świetny poradnik, przydałby się też taki poświęcony funkcjom. Są co prawda opisane w BB ,ale jednak oglądanie i słuchanie poradników ,to coś więcej niż suchy tekst.

    OdpowiedzUsuń
  3. Fajny poradnik , ale moim zdaniem porównywanie masek jest bardziej zrozumiałe kiedy na operacjach logicznych porównujemy liczby binarne , a nie dziesiętne czy heksadecymalne. Coś mi się wydaje że na F/X kariery nie zrobisz , ale próbuj . Pozdrowienia.

    OdpowiedzUsuń
    Odpowiedzi
    1. Wiem, że na FX kariery nie zrobię ;) nie o to chodzi

      Usuń
  4. Super poradnik . Hirurgicznie wyjaśnione:D Pozdrawiam.

    OdpowiedzUsuń
  5. EXTRA! to mi się podoba podejście do zagadnienia jak DOCTOR!

    OdpowiedzUsuń
  6. W 20 min. w wyrażeniu IF ,brakuje końcowego nawiasu. Ale spoko.

    Rozumiem maskowanie bitów ,ale muszę zapytać ,nawet jeśli to głupio zabrzmi ,dlaczego nie mogę po prostu odczytywać "0" po wciśnieńciu klawisza z rejestru PINx

    ,w taki oto sposób:

    if (PINC7==0) {

    PORTD ^=LED //zmień stan diody

    }

    działa podobnie po skompilowaniu ,więc dlaczego utrudniać sobie maskowaniem ?

    pomijam w przykładzie delaye i drgania styków ( chodzi tylko o formę warunkową).

    OdpowiedzUsuń
    Odpowiedzi
    1. Myślę że sam odpowiedziałbyś sobie na to pytanie mając książkę Bluebooka a nawet zdaje się w tym poradniku o tym wspominałem - ale ok - pewnie ci umknęło więc przypomnę.

      Po pierwsze to maskowanie bitu dla PINC na PC7 nie jest żadnym utrudnianiem ;) ty sobie nie zadałeś trudu sprawdzenia co by było gdyby w całym rejestrze PINC były np same jedynki z jakichś powodów (nie ważne jakich - np inne klawisze) ...

      no to teraz po wciśnięciu klawisza na PC7 jaką wartość będziesz miał w PINC ????

      0b0111111

      rozumiesz ??

      a nie

      0b00000000

      bo gdyby przypadkiem były zera to przypadkiem wychodzi twoje myślenie i się zgadza ;) ale czy tak robisz że na jeden cały port dajesz tylko jeden klawisz a innych pinów nie używasz ?

      Ba! gorzej - nawet gdybyś ich nie używał to na tych pinach byłby stan wysokiej impedancji i za każdym odczytem ZAKŁADAJĄC np że klawisz na PC7 wciśnięty mógłbyś odczytywać takie np wartości z PINC

      0b01011101

      albo

      0b0010100

      albo

      0b01110111

      itp itd

      i co wtedy panie kochany ? ;)

      no MUSIMY zamaskować te inne bity

      0b01101010 - zawartość PINC
      0b10000000 - maska (1<<PC7) i operacja AND
      ----------------------
      0b00000000 - rezultat w IF - teraz jeszcze tylko negacja ! i jest TRUE

      a ty sam sprawdź co się stanie bez maskowania i nie mów że to utrudnianie sobie życia - bo NIEMOŻLIWA jest operacja sprawdzenia bez maskowania po prostu - ok ?

      Usuń
  7. No tak ,ale podciąganie ,załatwia sprawę i mamy "1" dopuki nie nacisnę klawisza.
    Interesuje mnie tylko PINC7 w tym przypadku ,więc nawet jeśli pozostałe stany są dowolne to i tak powinno zadziałać, kiedyś też spotkałem się z takim zapisem:

    if (((PINC & _BV(PC7))==0){

    //instrukcje

    }

    ,stara książka ,chyba jedna z pierwszych na mikrokontrolery AVR w C, ale jakoś nie podeszły mi te zapisy _BV ,odkąd mam BB używam przesunięć bitowych i jest OK.

    Zapytałem z ciekawości ,bo pomimo innego zapisu okazuje się ,że też działa (no chyba ,że ma ukryte wady )

    OdpowiedzUsuń
    Odpowiedzi
    1. No zobacz upierasz się a nie chce ci się przeanalizować prostego przykładu

      załóż że rejestr PINC ma wartość

      0b11111111

      no i teraz że ty wciskasz sobie PC7 do GND

      czyli twój niby warunek

      if( PINC7 == 0 )

      łał - matko dopiero teraz zobaczyłem coś ty tam wyżej napisał

      a co to jest panie kochanieńki

      PINC7 ????? hmmm

      nie ma czegoś takiego - rozumiesz ???

      -----------------------------

      _BV() to BitValue() .... czyli DOKŁADNIE to samo co (1<<PC7)

      a gdy ja widzę, że ktoś unika jak ognia zapisu

      (1<<PC7)

      to z daleka mi pachnie że ma GIGANTYCZNE KŁOPOTY ze zrozumieniem przesunięć bitowych i tak naprawdę co chwilę ma kłopoty z programowaniem w C

      ja ZDECYDOWANIE polecam i piszę to przez całą swoją niebieską książkę - polecam używać zapisów z przesunięciami bitowymi bo kod staje się bardziej przejrzysty niż z tymi kocimi makrami _BV() i już ;)

      Usuń
  8. A no tak teraz to ma sens jeśli nie można bezpośrednio PINC7 ,tylko odczytujemy zawartość całego PINC ,to faktycznie cza maskować. Dziwne ,że kompilator nie protestował?

    OdpowiedzUsuń
    Odpowiedzi
    1. Musiał protestować - chyba że nie używasz Eclipsa tylko np kocie Atmel Studio z wyłączonym ostrzeganiem albo z czegoś jeszcze bardziej egzotycznego. Albo może nie zauważyłeś ;)

      nie ma mocnych ;) PINC7 to twór przypominający rodem robaczka np z Bascoma, więc końpilator C musi dostać co najmniej torsji na widok czegoś takiego ;)

      Usuń
  9. Możliwe ,że to moja wina i coś wyłączyłem ,bo bawiłem się w opcjach edytora. Wrzucę świeżą kopię ,albo dam ustawienia na Defultowe i sprawdzę.

    Tak tylko czy dobrzę rozumię, w mikrokontrolerach 8-bitowych ,najmniejsza zmienna w C to uin8_t ,więc odpada flaga bitowa "0" ,"1"

    Jeśli dokonujemy zapisu to ,przesunięcia bitowe, np. dla trybu Timera1 bit CS02.

    TCCR0B |= (1<<CS02)

    ,ale chcąc np. odczytać wartość tego rejestru ,nie mogę dać (zmienna i):

    i=CS02; (czy wartość 0 lub 1)

    tylko szczytać to z rejestru

    i=TCCR1B; (i 8bitowa uin8_t ) ,potem maskowanie i widzę warość ustawioną CS02.

    Podobnie w rejestrach PINx ,zawsze otrzymujemy 8-bitową daną ,nie można iść na skróty i sprawdzać wiewiórcze pojedyńcze Bity (0-7) ,na wartość 0 i 1.

    Dobrze zrozumiałem?

    OdpowiedzUsuń
    Odpowiedzi
    1. Bardzo dobrze to zrozumiałeś ;) w 8051 mamy pola bitowe realizowane sprzętowo, a w AVR nie. Można sobie wprawdzie zrobić programowo pola bitowe za pomocą struktu

      struct {

      uint8_t flaga1:1;
      uint8_t flaga2:4;

      } TFLAGI;

      opisuję to w swojej książce poniekąd. Jak widać pole bitowe nie musi wtedy mieć rozmiaru jednego bitu a więcej, ale i tak nawet jeśli zrobimy taką strukturę z jedną flagą to w RAM zejdzie nam na to 1 bajt ;) Więc nie zawsze jest to opłacalne

      Usuń
  10. Ale horror przerywnik bąba

    OdpowiedzUsuń
  11. Dziękuję Ci Mirku. Wreszcie zrozumiałem.

    OdpowiedzUsuń
    Odpowiedzi
    1. Nie ma za co ;) ... fajnie że udało się pomóc

      Usuń
  12. Witam
    Na wstepie pozdrawiam autora za jego trud...
    Mam pytanie. Probuje badac stan portu:
    if(!((PIND & 1<<PD4)&&(PIND & 1<<PD3)&&(PIND & 1<<PD2)&&(PIND & 1<<PD1)&&(PIND & 1<<PD0))) PORTB |=(1<<PB7);
    czyli jezeli na ktoryms pinie wystapi stan 0 to zapalam PB7,
    ale ten if to taka dluga zmija i probowalem to zapisac:
    if(!(PIND & 0x1F)) tak zeby czytac od razu calosc ale ten zapis mi nie dziala. Prosze o pomoc jak maskowac caly bajt.
    Pozdrawiam
    Stefan

    OdpowiedzUsuń
    Odpowiedzi
    1. Ale dobrze podchodzisz do tematu, bo nie ma co tylu bitów wpisywać oddzielnie, tylko użyć maski w postaci jednej liczby albo HEX albo BIN. Ty dobrze zamieniłeś badane bity na maskę 0x1F

      Jeśli więc coś ci nie działa jak piszesz to pewnie robisz błąd w całkiem innym miejscu kodu - a tymczasem próbujesz szukać go w masce. A maskę zrobiłeś dobrze ;)
      if( ! ( PIND & 0x1F ) ) .....

      tyle tylko że źle rozumiesz działanie tego IF'a ... bo tu zadziała to tak - że jeśli na KAŻDYM z tych pinów wystąpi ZERO to wtedy warunek zostanie spełniony - rozumiesz ?

      Jeśli chcesz reagować na to czy na którymkolwiek wystąpi zero to trzeba sprawdzać konkretną wartość maski panie kochany ... czyli np

      if( ( PIND & 0x1F ) != 0x1F ) ....

      tu badamy dopiero czy na którymś bicie wystąpiło zero, bo jeśli nie wystąpiło to zawsze wartość PIND zamaskowana 0x1F będzie równa 0x1F - teraz jaśniej ? ;)

      Usuń
  13. Witam
    Oczywiscie Twoje rozwiazanie dziala (za ktore dziekuje) tylko ze go nie kumam... W pierwszym nawiasie sprawdzam maska stan wszystkich 5 pinow portu D, i jezeli na ma tam 1 to maska daje falsz ale ten kolejny zapis to magia. Operator != oznacza ze pierwszy nawias jest rozny od 0x1F ...Czy mam to rozumiec tak: jezeli pierwszy nawias jest rozny do wyrazenia po != to if jest spelniony?
    Takiej kombinacji w poradniku nie ma a jest bardzo interesujaca ( to taki troche OR).
    Serdecznie pozdrawiam
    Stefan

    OdpowiedzUsuń
    Odpowiedzi
    1. Widzisz, jak sam piszesz nie rozumiesz, i wydaje ci się to tajemnicze bo prawdopodobnie nie masz książki:

      http://atnel.pl/mikrokontrolery-avr-jezyk-c.html

      w której to opisałem DOKŁADNIE wszystkie takie podstawowe operacje zarówno logiczne jak i bitowe, ale także operatory jedno- i dwu-członowe - jakie występują w języku C. Pokazuję też w programach w książce jak się nimi posługiwać a także DOKŁADNIE i to z fajnymi grafikami przedstawiam jak to działa tak rozpatrując bit po bicie ....

      zapis panie kochany

      !=

      to dwuczłonowy operator logiczny - a nie tak jak ty próbujesz wysnuć jakieś przedziwne wnioski, że wykrzyknik odnosi się do jakiegoś nawiasu wcześniej czy coś

      ten zapis oznacza nic innego jak

      "różne od"

      w innych językach zapisywane tak

      <>

      To co w pierwszym nawiasie to jest WYRAŻENIE warunkowe w języku C ... nic innego i nic prostszego - ale jeśli no właśnie nie zna się podstaw to później się to rozpatruje jako jakieś nawiasy

      tymczasem wyrażenie po lewej stronie przyjmuje wartość w zależności od podanej maski oraz wciśniętych klawiszy


      i sprawdzamy czy wartość tego wyrażenia jest różna od wartości 0x1F

      to aż tyle i tylko tyle

      Mówię - szczerze polecam zacząć od książki - bo moje praktycznie wszystkie poradniki są tworzone właśnie z myślą - jako uzupełnienie do książek .... i ciężko tylko na ich podstawie się nauczyć programowania ..... A jak sam widzisz nie byłbym w stanie w kilku poradnikach przekazać dość sporej ilości wiedzy jaką przekazałem w książce

      Usuń
  14. I wszystko gra. Znalazlem to na stronie 94...(mam oczywiscie obydwie ksiazki). Teraz to rozumiem w pelnej krasie. Dziekuje i do nastepnego ;)

    OdpowiedzUsuń