Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Kategoria: Kamery IP / Alarmy / Automatyka Bram
Montersi
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATMEGA] [C] Sprawdzenie stanu zmiennej - modulo vs porównanie

krzychusss 16 Lip 2017 17:03 456 13
  • #1 16 Lip 2017 17:03
    krzychusss
    Poziom 11  

    Uczę się obsługi AVR i zatrzymałem się przy licznikach.

    Mam taki oto kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zatrzymałem się w pętli głównej programu, gdzie sprawdzam stan zmiennej licznik - w tym przypadku używam modulo.
    Wszystko niby działa, aczkolwiek zauważyłem, że dioda zapala się i gaśnie "na dwa kroki" - zapala się lekko, a po kolejnym przerwaniu (tak mi się wydaje), świeci pełnym światłem. Tak samo wygląda gaszenie.

    Podmieniając modulo na zwykłe
    Kod: c
    Zaloguj się, aby zobaczyć kod

    i resetując w bloku if-a stan zmiennej
    Kod: c
    Zaloguj się, aby zobaczyć kod

    otrzymuję dokładnie to, czego oczekiwałem: dioda zapala się od razu pełnym światłem i gaśnie co określony czas - także bez efektu "przygaszania".

    Skąd takie zachowanie? Co powoduje, że zapalanie/gaszenie diody w bloku sterowanym operacją modulo odbywa się inaczej, aniżeli w przypadku zwykłego porównania?

  • #2 16 Lip 2017 17:41
    excray
    Poziom 38  

    Jeśli nic nie robisz ze zmienną licznik w pętli głównej to zawartość if(licznik%5 == 0){} wykonuje się wielokrotnie zanim zmieni się licznik.

  • #3 16 Lip 2017 22:11
    electronics_design
    Poziom 11  

    Tat tylko że np. 3 % 5 to zawsze 3, niezależnie ile razy to wykonasz :) jakiej częstotliwości migania się spodziewasz?

  • #4 16 Lip 2017 22:11
    BlueDraco
    Specjalista - Mikrokontrolery

    Wyrzuć wszytkie operacje na porcie i na zmiennej licznik z pętli głównej - to jest przyczyną dwóch błędów, jakie masz w tym programie.

  • #5 16 Lip 2017 22:58
    excray
    Poziom 38  

    electronics_design napisał:
    Tat tylko że np. 3 % 5 to zawsze 3, niezależnie ile razy to wykonasz

    Zgadza się. Ale operacja PORTB ^= (1<<LED1); po każdym wywołaniu zmienia Ci stan wyjścia na przeciwny. Więc ma znaczenie, czy zostanie wykonana raz, czy pięćdziesiąt.
    electronics_design napisał:
    :) jakiej częstotliwości migania się spodziewasz?

    W momencie kiedy warunek jest prawdziwy - bardzo dużej.

  • #6 17 Lip 2017 12:01
    BlueDraco
    Specjalista - Mikrokontrolery

    excray napisał:
    Zgadza się. Ale operacja PORTB ^= (1<<LED1); po każdym wywołaniu zmienia Ci stan wyjścia na przeciwny.


    To niestety nie musi być prawdą - na tym właśnie polega błąd w tym programie.

  • #7 17 Lip 2017 12:15
    excray
    Poziom 38  

    excray napisał:
    operacja PORTB ^= (1<<LED1); po każdym wywołaniu zmienia Ci stan wyjścia na przeciwny.

    BlueDraco napisał:
    To niestety nie musi być prawdą

    Rozwiń tą myśl.

  • Pomocny post
    #8 17 Lip 2017 19:10
    BlueDraco
    Specjalista - Mikrokontrolery

    Pomyśl, co się stanie, gdy przerwanie timera zostanie zgłoszone w trakcie wykonywania modyfikacji portu w pętli głównej, po odczycie PORTB, a przed jego zapisem. Jeśli wyjścia są modyfikowane w przerwaniach - nie należy modyfikować innych wyjść tego samego portu w wątku głównym. To jedna z wielu przesłanek za tym, by "pętla główna" była pusta. Inaczej trzeba na czas modyfikacji blokować przerwania.

  • #9 17 Lip 2017 20:05
    krzychusss
    Poziom 11  

    BlueDraco napisał:
    Pomyśl, co się stanie, gdy przerwanie timera zostanie zgłoszone w trakcie wykonywania modyfikacji portu w pętli głównej, po odczycie PORTB, a przed jego zapisem. Jeśli wyjścia są modyfikowane w przerwaniach - nie należy modyfikować innych wyjść tego samego portu w wątku głównym. To jedna z wielu przesłanek za tym, by "pętla główna" była pusta. Inaczej trzeba na czas modyfikacji blokować przerwania.


    Rozumiem, że problemem w tym przypadku jest czas - w momencie odczytu PORTB jego stan jest inny niż w momencie zapisywania?

  • Pomocny post
    #10 17 Lip 2017 20:34
    excray
    Poziom 38  

    @BlueDraco To o czym piszesz odbędzie się ze szkodą dla operacji na porcie w przerwaniu. Ta z pętli głównej zostanie wykonana bez zmian. Niemniej jak najbardziej masz rację co do tego, że tak się nie powinno robić.

    krzychusss napisał:
    Rozumiem, że problemem w tym przypadku jest czas - w momencie odczytu PORTB jego stan jest inny niż w momencie zapisywania?

    Nie do końca. Ja i kolega @BlueDraco piszemy na innych warstwach abstrakcji. Kolega @BlueDraco pisze o tym, że w taki sposób nie powinno się pisać programów - i ma rację. A ja piszę o tym co w Twoim ogólnie źle napisanym programie powoduje taki efekt jaki opisałeś w 1 poście. Przeanalizuj to co napisałem w #2 i #5.

  • Pomocny post
    #11 17 Lip 2017 20:58
    tronics
    Poziom 35  

    krzychusss - przeanalizuj co ile wykonuje się pętla główna, co ile zgłasza się przerwanie od przepełnienia.

  • #12 17 Lip 2017 22:07
    krzychusss
    Poziom 11  

    Warunek if-a w pętli głównej jest spełniony, więc pętla wykonuje się wielokrotnie (miga LED2, z dużą częstotliwością), aż do następnego przerwania, które podniesie wartość zmiennej licznik i spowoduje, że warunek przestaje być prawdziwy.
    Stąd też prawidłowe działanie programu w przypadku zmiany wartości zmiennej licznik w bloku if - warunek od razu przestaje być prawdziwy. Rzeczywiście :) Dzięki!

    W którym więc miejscu programu powinienem zapalać/gasić LED1? Lepiej ustawić do tego osobny timer czy rozbudować już istniejące przerwanie?

  • #13 18 Lip 2017 08:54
    dondu
    Moderator Mikrokontrolery Projektowanie

    krzychusss napisał:
    W którym więc miejscu programu powinienem zapalać/gasić LED1? Lepiej ustawić do tego osobny timer czy rozbudować już istniejące przerwanie?

    Niestety na to pytanie jest taka sama odpowiedź, jak na pytanie: Który samochód wybrać?
    To Ty decydujesz w zależności od wielu czynników, które Ty o swoim projekcie wiesz, a my nie.
    Istotne jest natomiast to, że jesteś świadomy, że możesz zrobić to na co najmniej dwa sposoby. Przećwicz więc sobie oba :)

  • #14 20 Lip 2017 18:04
    krzychusss
    Poziom 11  

    Sprawdziłem obie metody i faktycznie da się to zrobić na oba sposoby.
    Dzięki wszystkim za pomoc :)

 Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME