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:
;)
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.
OdpowiedzUsuńPozdrawiam kolegę Mirka i jak zwykle życzę szczęścia, zdrowia, pomyślności :)
Zenowi
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ńŚ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ń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ńWiem, że na FX kariery nie zrobię ;) nie o to chodzi
UsuńSuper poradnik . Hirurgicznie wyjaśnione:D Pozdrawiam.
OdpowiedzUsuńEXTRA! to mi się podoba podejście do zagadnienia jak DOCTOR!
OdpowiedzUsuńW 20 min. w wyrażeniu IF ,brakuje końcowego nawiasu. Ale spoko.
OdpowiedzUsuń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ą).
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ę.
Usuń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 ?
No tak ,ale podciąganie ,załatwia sprawę i mamy "1" dopuki nie nacisnę klawisza.
OdpowiedzUsuń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 )
No zobacz upierasz się a nie chce ci się przeanalizować prostego przykładu
Usuń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ż ;)
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ń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ś ;)
Usuń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 ;)
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ę.
OdpowiedzUsuń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?
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
Usuń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
Ale horror przerywnik bąba
OdpowiedzUsuńDziękuję Ci Mirku. Wreszcie zrozumiałem.
OdpowiedzUsuńNie ma za co ;) ... fajnie że udało się pomóc
UsuńWitam
OdpowiedzUsuń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
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
Usuń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 ? ;)
Witam
OdpowiedzUsuń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
Widzisz, jak sam piszesz nie rozumiesz, i wydaje ci się to tajemnicze bo prawdopodobnie nie masz książki:
Usuń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
I wszystko gra. Znalazlem to na stronie 94...(mam oczywiscie obydwie ksiazki). Teraz to rozumiem w pelnej krasie. Dziekuje i do nastepnego ;)
OdpowiedzUsuń