Kanał - ATNEL tech-forum
Wszystkie działy
Najnowsze wątki



Teraz jest 10 sty 2025, o 22:06


Strefa czasowa: UTC + 1





Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 6 ] 
Autor Wiadomość
PostNapisane: 30 gru 2013, o 14:32 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 07 gru 2012
Posty: 56
Lokalizacja: Praszka
Pomógł: 1

Chciałem zadać pytanie do konkretnego kawałka kodu z pełnym przekonaniem, że teorię to ja już pojąłem, a mimo wszystko coś nie pasuje.
I tak opisując w miarę dokładnie to z czym się zmagałem, pod sam koniec, na chwilkę przed kliknięciem Wyślij otrzymałem odpowiedź, jak grom z jasnego nieba, kończąc opisywać problem z którym nie mogłem sobie poradzić.

Może gdyby komuś, kiedyś trafił się podobny problem ze zrozumieniem tych zagadnień w konkretnym przykładzie... wrzucam tego posta, jak krok po kroku próbowałem to opisać, żeby ktoś mi pomógł, aż w końcu z BlueBookiem doszedłem do rozwiązania. :lol:

tak to się zaczęło:
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Czytając artykuł Obsługa klawiszy - drgania styków CD...2, napotkałem taki problem, którego nie potrafię sam przejść.

Dotyczy tego programu.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


Zmieniłem w nim 22 linię na coś takiego, tak w ramach testów na:
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

i po tej zmianie nie działa już ten program tak jak powinien, bo nie można zmieniać stanu diody na przeciwny po tej modyfikacji.


Zacząłem analizować poszczególne przypadki po kolei, od początku robiąc to w następujący sposób:

--- rozpoczęcie programu - Pierwsze wejście - do pętli while(1) ---

1) sytuacja
Klawisz KEY1 --- NIE wciśnięty


if(!00000000 && !(1xxxxxxx & 10000000) )
if( 1 && ! (10000000) )
if( 1 && 0 )
if( 0 )

W instrukcji FAŁSZ, więc przechodzę do else if()

else if( 00000000 && (1xxxxxxx & 10000000) )
else if( 00000000 && 10000000 )
else if( 0 )

W instrukcji FAŁSZ, więc zmienna key_lock = 0 nadal równa się zero, dopóki nie wcisnę przycisku, to program będzie tak latał w pętli while(1) BEZ ZMIAN ----> --- kolejne wejścia - do pętli while(1) ---



--- rozpoczęcie programu - Pierwsze wejście - do pętli while(1) ---

2) sytuacja
Klawisz KEY1 --- Wciśnięty



if( !00000000 && !(0xxxxxxx & 10000000) )
if( 1 && !(00000000) )
if( 1 && 1)
if( 1 ) key_lock=1;

W instrukcji PRAWDA, więc key_lock = 1, a to co dalej czyli elese if() już się nie wykona...
... i gdy tak będę trzymał ten klawisz wciśnięty w tej sytuacji i nie będę go puszczał to program wejdzie po raz kolejny do pętli while(1) ----> --- kolejne wejścia - do pętli while(1) ---

if(!00000001 && !(0xxxxxxx & 10000000) )
if( 0 && ! (00000000) )
if( 0 && 1 )
if( 0 )

W instrukcji FAŁSZ, więc przechodzę do else if()

else if( 00000001 && (0xxxxxxx & 10000000) )
else if( 00000001 && 00000000 )
else if( 0 )

W instrukcji FAŁSZ, więc program, znów wskakuje do pętli while(1), a ja nie puszczam klawisza, tak jak bym się o niego oparł i zasnął... klawisz jest cały czas wciśnięty, więc program przechodzi wszystkie warunki tak, jak w powyżej przedstawionej kolejności i nic się nie zmienia, program tak lata i lata "w kółko..."

...aż w końcu podczas snu przewracam się na drugi bok i już puszczam ten klawisz...
--- kolejne wejścia - do pętli while(1) ---

if(!00000001 && !(1xxxxxxx & 10000000) )
if( 0 && ! (10000000) )
if( 0 && 0 )
if( 0 )

W instrukcji FAŁSZ, więc przechodzę do else if()

else if( 00000001 && (1xxxxxxx & 10000000) )
else if( 00000001 && 10000000 )
else if( 1 )

no w końcu, program doszedł do bloku po else if(1) , który wykona zmianę stanu diody na przeciwny...
A zmiana, ta wykona się dzięki temu, że puściłem, ten przycisk.

Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.


...ale chwila, chwila, zanim jednak dokona się ta zmiana to jest przecież jeszcze jedna instrukcja if() po drodze, w której jest:
NegacjaLogiczna Preinkrementacji zmiennej key_lock

:( i tutaj właśnie zaczynają się dla mnie schody...
wyczytałem w BB:
- 94 str., że cyt.: "Jeśli operator ++ stoi przed zmienną, to najpierw jest ona zwiększana o jeden, a następnie ta już zwiększona wartość brana jest jako wynik tego wyrażenia"
- 107 str., że operatory przedrostkowe: ! i preinkrementacja są tej samej, wagi, mają ten sam priorytet, a ich łączność jest prawostronna, co oznacz że działanie wykonuje się od strony prawej.

No to po takim zastrzyku wiedzy, siup, myślę sobie tak...
key_lock był równy 1, to będzie tak:
if(!++key_lock)
if(!++1)
if(!2)
if(0)
key_lock został najpierw zwiększony z wartości = 1, do wartości = 2, następnie został zanegowany negacją logiczną i warunek instrukcji if() jest teraz FAŁSZEM, więc zmiana stanu diody jeszcze się nie wykona...
Działa opisany mechanizm na blogu nazwany przez naszego Mistrza: mikro programowy timer ;)
program po raz kolejny wskakuje do pętli while(1) i zwiększa stan zmiennej key_lock aż do wartości jaką może maksymalnie osiągnąć, czyli 255, bo jest typu uint8_t, a jak osiągnie 255 to następnie po zwiększeniu o 1, będzie key_lock wyzerowany, czyli key_lock=0 przyjmie wartość zero.

--- kolejne wejścia - do pętli while(1) --- podczas gdy zwiększa się z kolejnymi wejściami wartość zmiennej key_lock

if(!00000_ _ _ && !(1xxxxxxx & 10000000) ) w miejscu _ _ _ zwiększają się te watości key_lock przez co zawsze ten pierwszy człon ifa będzie z logicznego punktu widzenia PRAWDĄ, która będzie negowana
if( 0 && ! (10000000) ) ...w tej linii widać to pierwsze zero, to jest ta zanegowana PRAWDA
if( 0 && 0 )
if( 0 )

W instrukcji FAŁSZ, więc przechodzę do else if()

else if( 00000001 && (1xxxxxxx & 10000000) )
else if( 00000001 && 10000000 )
else if( 1 )

-----------------------------------------------------------------------------
i w tym miejscu po tak szczegółowym rozpisaniu :) dochodzę do tego...

key_lock = 1
if(!++key_lock)
if(!++1)
if(!2) --------------------- key_lock=2
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

key_lock = 2
if(!++key_lock)
if(!++2)
if(!3) --------------------- key_lock=3
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

key_lock = 3
if(!++key_lock)
if(!++3)
if(!4) --------------------- key_lock=4
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

key_lock = 4
if(!++key_lock)
if(!++5)
if(!2) --------------------- key_lock=5
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona
.

.

.

key_lock = 255
if(!++key_lock)
if(!++255)
if(!0) --------------------- key_lock=0
if(1)
---------------------------------- PRAWDA mikro programowy timer wykonał swoją robotę ;) zmieni się stan diody na przeciwny, a następna zmiana jeśli się będzie miała dokonać, to będzie trzeba ponownie przejść taką samą drogę, tzn. wcisnąć klawisz, następnie puścić... mikro programowy timer wykona swoją robotę ;) (ZROBI TO BARDZO SZYBCIUTEŃKO, ja tego nie zauważę nawet... ale stan przejściowy w którym akurat mogą wystąpić drgania styków minie... i nie będzie żadnych problemów z niespodziewanymi zmianami stanu diody).


No i się cieszę, bo podany przykład działa tak jak powinien :)
-----------------------------------------------------------------------------------------------------------------------------
Ale jak sobie chciałbym przeanalizować to samo z tą małą zmianą, którą jak już wspomniałem, zadałem sobie tak dla testów.
Składnia: [ Pobierz ] [ Ukryj ]
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.

w 22 linijce...
to sięgając ponownie do książki:
- 94 str. cyt.: "jeśli operator stoi za zmienną, to najpierw brana jest pod uwagę stara wartość tej zmiennej i ona będzie wynikiem tego wyrażenia. Następnie, po operacji, gdy wynik został już pobrany do obliczeń, wartość ta jest zwiększana o jeden"
- 107 str. w tabelce priorytetów operatorów postinkrementacja ma większy priorytet niż ! negacja logiczna.

Po tym co przeczytałem, ja to widzę tak... /może? tu gdzieś leży błąd w moim rozumowaniu/ że skoro postinkrementacja ma większy priorytet niż negacja logiczna to operacja postinkrementacji na zmiennej key_lock jest wykonywana najpierw, a potem już w następnej kolejności jest robiona negacja logiczna - czyli myślę/wydaje mi się że jest to to samo co w przypadku z preinkrementacją, z tą różnicą, że w pierwszym przypadku gdy key_lock = 1, negacja zostanie wykonana na wartości 1, a nie wartości 2:

key_lock = 1
if(!key_lock++)
if(!1++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=1
if(!1) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock=2, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona


key_lock = 2
if(!key_lock++)
if(!2++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=2
if(!2) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock=3, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

key_lock = 3
if(!key_lock++)
if(!3++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=3
if(!3) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock=4, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

key_lock = 4
if(!key_lock++)
if(!4++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=4
if(!4) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock=5, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona
.

.

.

key_lock = 255
if(!key_lock++)
if(!255++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=255
if(!255) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock= 0, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(0) --------------------- FAŁSZ zmiana stanu diody się jeszcze teraz nie dokona

*

key_lock = 0
if(!key_lock++)
if(!0++) --------------------zgodnie z priorytetem postinkrementacji przekazuję dalej key_lock=0
if(!0) --------------------- wynik w tym przypadku został już pobrany do obliczeń, zwiększam key_lock o jeden, więc key_lock= 1, (zwiększenie nie wpłynęło na wartość wyrażenia, na którym wykona się negacja)
if(1)
---------------------------------- PRAWDA <------------------------ ale tu nigdy program nie dojdzie, w związku z czym nie zmieni NIGDY stanu diody na przeciwny, bo krok wcześniej key_lock w wyniku operacji postinkrementacji osiągnie zero, i jedyne co będzie można programowi nakazać żeby się nie nudził... to podczas ponownego wciśnięcia przycisku i puszczenia go, danie programowi zadania, żeby sobie zwiększał wartość zmiennej key_lock operacją postinkrementacji od 1 przez kolejne liczby całkowite do 252, 253, 254, 255, 0 ... co jak widać nie przyniesie żadnych zmian, przez tą różnicę, (której nie dostrzegałem kiedy zacząłem opisywać ten mój problem, żeby otrzymać pomoc na forum :) ) pomiędzy -PRE -POST -Inkrementacjami.

Przełom nadszedł dopiero w miejscu oznaczonym *, a więc prawie na sam koniec, kiedy już myślami byłem na klikaniu Wyślij i czekaniu aż mi ktoś odpowie :)



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 gru 2013, o 14:34 

Pomógł: 0

Hehe :D Szacun :D.



Góra
  
cytowanie selektywne  Cytuj  
PostNapisane: 30 gru 2013, o 14:40 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27343
Lokalizacja: Szczecin
Pomógł: 1041

śliczna analiza przypadku ;) ... troszkę to męczyliśmy z kolegą na maila ... ale jak widać na forum jest to wszystko łatwiej opisać i pokazać ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 gru 2013, o 19:37 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 09 gru 2013
Posty: 93
Lokalizacja: Piotrków Trybunalski
Pomógł: 1

Dodam od siebie odbiegając od opisywanego przypadku. Jeżeli mamy możliwość wybrania pomiędzy właśnie postin(de)krementacją a prein(de)krementacją, gdy nie wpływa to na realizację programu, lepiej zdecydować się na prein(de)krementację. Wynika to z faktu, że program bezpośrednio przypisuje nową wartość do zmiennej, natomiast kiedy zwiększenie następuje później, musi wytworzyć w pamięci dodatkową zmienną, aby móc odpowiednio podziałać. W związku z tym nie tracimy niepotrzebnie ani miejsca, ani czasu :)

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 gru 2013, o 20:00 
Offline
Moderator
Avatar użytkownika

Dołączył(a): 03 paź 2011
Posty: 27343
Lokalizacja: Szczecin
Pomógł: 1041

absolutnie nie musi zadnej zmiennej dodatkowej w pamieci tworzyc ;) to wszystko odbywa sie na rejestrach procka ;)

_________________
zapraszam na blog: http://www.mirekk36.blogspot.com (mój nick Skype: mirekk36 ) [ obejrzyj Kurs EAGLE ] [ mój kanał YT TV www.youtube.com/mirekk36 ]



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
PostNapisane: 30 gru 2013, o 20:04 
Offline
Użytkownik
Avatar użytkownika

Dołączył(a): 09 gru 2013
Posty: 93
Lokalizacja: Piotrków Trybunalski
Pomógł: 1

Aaaa no to pardonsik, w takim razie należy dodać że to się odnosi do tylko komputerów :)

_________________
sig off ;(



Góra
 Zobacz profil  
cytowanie selektywne  Cytuj  
Wyświetl posty nie starsze niż:  Sortuj wg  
Utwórz nowy wątek Odpowiedz w wątku  [ Posty: 6 ] 

Strefa czasowa: UTC + 1


Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zidentyfikowanych użytkowników i 1 gość


Nie możesz rozpoczynać nowych wątków
Nie możesz odpowiadać w wątkach
Nie możesz edytować swoich postów
Nie możesz usuwać swoich postów
Nie możesz dodawać załączników

Szukaj:
Skocz do:  
cron
Sitemap
Technologię dostarcza phpBB® Forum Software © phpBB Group phpBB3.PL
phpBB SEO