Elektroda.pl
Elektroda.pl
X
Arrow Multisolution Day
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

atmega32 [C] - Obsługa klawiszy, wyświetlacza, przerwań i do tego ADC.

skoomi 08 Kwi 2013 19:02 3141 29
  • #1 08 Kwi 2013 19:02
    skoomi
    Poziom 11  

    Witam!
    Zacząłem niedawno zabawę z mikrokontrolerami i natknąłem się na problem przy obsłudze klawiszy.

    Napisałem program wyświetlający na 2 7-seg wyświetlaczach liczby od 00 do 99 do 00 do 99 itd. i migający przy 00 i przy 99
    Chciałem dorobić miganie przy naciśnięciu klawisza, wiec dodałem odczytywanie stanu na jakimś pinie po KAŻYM wyświetleniu liczby czyli:
    99 sprawdza 98 sprawdza 97 sprawdza itd.
    Trochę to wg mnie kiepskie rozwiązanie tzn, praktycznie wydłuża czas "przelotu" po programie o 2 razy. Czy nie jest tak?
    Czy jest jakiś sensowniejszy sposób na sprawdzanie stanu pinu_klawisz?
    [/u]

    0 29
  • Arrow Multisolution Day
  • #3 08 Kwi 2013 19:38
    skoomi
    Poziom 11  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Edytowałem

    0
  • #5 08 Kwi 2013 19:52
    skoomi
    Poziom 11  

    Wychodzi na to, że rzeczywiście mam źle, bo żadnego timera tam nie używam;d
    O timerach dopiero zacząłem czytać.
    Zrobiłem to w ten sposób bo tak nam na laborkach pokazali. Ale skoro to jest lichy sposób to mam nadzięję że te laborki trochę skoczą z poziomem(dopiero drugie były) i nie będą nam kichy wciskali:D

    0
  • Arrow Multisolution Day
  • #7 09 Kwi 2013 21:00
    skoomi
    Poziom 11  

    Udało się. Mam wyświetlacz odświerzający się przy pomocy przerwania timera0;

    Mam oczywiście kolejny problem i pytania.
    W nocie atmegi wyczytałem że ma on 3 przerwania zewnętrzne INT0 INT1 INT2.
    Chciałbym teraz dodać obsługę klawiszy start stop i reset(jakiś prosty stoper).
    Czy powinienem napisać to tak, aby naciśnięcie klawisza wywoływało przerwanie?

    Przy większych projektach wydaje się to konieczne bo jeśli by sprawdzać stan klawisza bez przerwania to nie miałoby to sensu przy paru dłuższych pętlach w programie.Chodzi mi o to że aby wciśnięcie zostało wykryte trzeba by czekać aż program doleci do odpowiedniego miejsca w kodzie.

    Na końcu kwestia taka, że te przerwania są tylko 3 co pozwala na max 3 klawisze.
    Wiem że źle myślę ale nie wiem gdzie i proszę o naprowadzenie:P

    0
  • #8 09 Kwi 2013 21:18
    piotrva
    Moderator na urlopie...

    Po kolei.
    Dobry program powinien być tak zbudowany, aby w pętli głównej nie występowały (lub występowały tylko w miejscach na prawdę koniecznych) blokujące instrukcje opóźniające. W takiej sytuacji pętla wykonywać się powinna na tyle szybko, aby opóźnienie w cyklicznym sprawdzaniu stanu klawiszy nie było odczuwalne dla użytkownika.
    Co do przerwań to jest to druga alternatywa, ale wtedy zwykle wykonuje się pewien trick - mianowicie ileś klawiszy podpinamy pod osobne porty (lub nawet wykonujemy z nich matrycę), a następnie podpinamy je wszystkie diodami krzemowymi (np. 1n4148) do jednego wejścia INT. Tym sposobem po wciśnięciu klawisza stan niski pojawi się na wejściu mu odpowiadającym, oraz wywołane zostanie przerwanie, w którym będzie można obsłużyć klawiaturę.
    ---
    PS. Masz u mnie dużego plusa za samodzielny research nt. timerów i multipleksowania - szkoda, że nie wszyscy proszący o pomoc tak postępują, zamiast oczekiwać na wklejenie gotowego kodu ;)

    0
  • #9 09 Kwi 2013 21:23
    skoomi
    Poziom 11  

    Ok, teraz wszystko jasne. Dzięki za wyjaśnienie.
    Jeszcze tylko nie wiem jak poznać kiedy powinienem użyć klawiszy i przerwania, a kiedy poprostu klawiszy. Chyba że jak już będę potrzebował tych przerwań to samo z siebie wyjdze?

    0
  • #13 10 Kwi 2013 13:45
    skoomi
    Poziom 11  

    Dzięki będą o tym niedługo myślał. Narazie jednak moją uwagę zabrał mój "stoper".
    Napisałem takie prosty kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jednak w ciągu 90 sekund ten "stoper" odliczył prawie 94sekundy. Skąd ta niedokładność może wynikać?

    0
  • #14 10 Kwi 2013 17:03
    BlueDraco
    Specjalista - Mikrokontrolery

    A co jest wzorcem częstotliwości? Jeśli wewnętrzny RC - to całkiem zrozumiałe. Do OCR1A powinieneś ładować o 1 mniej.

    0
  • #15 15 Kwi 2013 15:13
    skoomi
    Poziom 11  

    Udało mi się podłączyć kwarc 10Mhz i teraz jest w miarę dokładnie:P
    Dzisiaj mam zamiar zrobic prosty zegarek i zostawić to na noc w celu sprawdzenia dokładności.

    Mam jednak problem z kropką. Przerwanie jest co sekundę i nie wiem jak zrobić, aby kropka zaświecała się i gasła w ciągu sekundy.
    Jedyny mój pomysł to zrobić przerwanie co 0,5 sekundy, w każdym przerwaniu zmiana stanu kropki, a w co drugim dodanie sekundy.

    Dodatkowo zastanawiam sie gdzie "wyłuskiwać cyfry". Robię to tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    I właśnie lepiej to robić w przerwaniach co sekundę czy tych od odświeżania wyświetlacza(około 200Hz)?

    0
  • #16 15 Kwi 2013 15:50
    BlueDraco
    Specjalista - Mikrokontrolery

    Już chyba Ci pisaliśmy, że tego wyświetlacza nie da się dobrze obsłużyć bez przerwań, więC przerwania powinieneś mieć pewnie jakieś 1200 razy na sekundę. Czas rozbity na cyfry trzymaj w tablicy. W każdym przerwaniu wyświetlaj jedną cyfrę. Po dojściu do ostatniej cyfry (co będzie następowało 300 razy na sekundę) zmniejszaj licznik zliczający od 300 do zera. Przy stanie 15 zmień stan kropki, przuy stanie 0 zwiększ licznik sekund i przeładuj licznik na 300.

    0
  • #17 15 Kwi 2013 16:07
    skoomi
    Poziom 11  

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Teraz działa. Kropka zmienia stan co sekundę. Tylko dlaczego pisałeś żeby było
    Kod: c
    Zaloguj się, aby zobaczyć kod
    ? Jeśli dam tam ==15 to nie działa i nie wiem dlaczego...

    Przepraszam że zmieniam posty, ale nie chciałem dublować.

    0
  • Pomocny post
    #18 15 Kwi 2013 16:37
    BlueDraco
    Specjalista - Mikrokontrolery

    Możesz użyć jednego timera.

    Procedura obsługi przerwania nie może przeszkadzać w obsłudze innych przerwań. W Twoim przypadku nie ma innych przerwań, więc jedyny warunek to ten, żeby procedura obsługi wykonała się w czasie mniejszym niż odstęp pomiędzy przerwaniami. To jest w sam raz dobry materiał na projekt z pustą pętlą główną, i tak to należy zrobić.

    0
  • #19 19 Kwi 2013 19:54
    skoomi
    Poziom 11  

    Ręce mi już opadają...
    Zacząłem się bawić ADC, ale nagle coś mi się stało z wyświetlaniem.
    Mam teraz taką obsługę przerwania:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Czy w pętli głównej programu piszę np: liczba = 1234;
    Na wyświetlaczu zaświeca się 1234, ale niestety inne segmenty też świecą, lecz dużo słabiej. Wyglada to tak że na 1 seg widać mocno 1 i słabiutko 4 i tak na każdym prześwituje poprzednia cyfra.
    Czym to może być spowodowane? Częstotliwość pracy to 10MHz a przerwanie około 200Hz.

    Właśnie sprawdziłem ,że gdy podaję poprostu cy1=2; cy2=3;... To wyświetla cyfry dobrze. Problemem jest więc rozkład podawanej liczby na cyfry.
    Wygląda to tak jakby nie nadążał policzyć odpowiedniej cyfry i już przechodził w następne przerwanie czyli następny wyświetlacz. Dobrym tropem idę:D?

    Ah udało się...
    Wystarczyło zmianę wyświetlacza zrobić po wyliczeniu nowej cyfry a nie przed:P

    0
  • Pomocny post
    #20 20 Kwi 2013 11:49
    BlueDraco
    Specjalista - Mikrokontrolery

    Klasyczny błąd obsługi wyświetlacza plus kilka innych błędów, które popełniłeś w tym kodzie dają razem takei właśnie efekty.

    "Klasyczny błąd obsługi wyświetlacza" polega na tym, że przed wystawieniem obrazu cyfry nie wyłączasz poprzedniej. Powinno być tak:
    - wyłącz cyfrę
    - podaj segmenty dla nowej
    - włącz nową cyfrę

    Nie potrzbujesz też żadnych if-then-else - wystarczy trzymać cyfry w tablicy i użyć licznika cyfr od 0 do 3 zamiast nadawać zmiennej licznik wartość maski bitowej cyfry.

    0
  • #21 20 Kwi 2013 14:22
    skoomi
    Poziom 11  

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Napisałem takie coś. Nawet działa poprawnie. Czy o to mniej więcej Ci chodziło?

    Niestety sam nie jestem w stanie pozbyć się więcej ifów.

    0
  • Pomocny post
    #22 20 Kwi 2013 17:42
    BlueDraco
    Specjalista - Mikrokontrolery

    żeby zgasić wyświetlacz, wystarczy wystawić na port cztery jedynki - nie musisz do tego zaprzęgać bieżącej pozycji i robić rozejść warunkowych. Łatwiej byłoby, gdyby licznik chodził od 0 do 3. Poza tym ok.

    0
  • #23 20 Kwi 2013 19:21
    skoomi
    Poziom 11  

    O matko... rzeczywiście nie wiem dlaczego sobie wszystko utrudniam:D
    Wielkie dzięki za wszystkie rady;)

    0
  • #24 21 Kwi 2013 18:05
    skoomi
    Poziom 11  

    Tym razem mam problem z ADC.
    Nie mogę znaleźć przyczyny dlaczego wartość w ADC zmienia się od 15 do 1023 niezależnie od potencjometru.
    Napięcie odniesienia ustawione na 2,56V, przy czym 1023 wskakuje przy 2,64V, a 15 dla 0V.
    Jeśli chodzi o to że 1023 jest przy 2,64 to rozumiem, bo wg noty może być od 2,3V do 2,7V.
    Ale dlaczego przy 0V jest 15?
    Podłączenie mam takie: http://2.bp.blogspot.com/-vhUemQW3GDM/Toyvftw...AAAAAABM4/K6MMU78cbOI/s1600/ADC_wersja_03.gif

    Co zauważyłem:
    Dla 1V wyświetla mi 399 czyli po przeliczeniu napięcie odniesienia=2,566V czyli wychodzi dobrze.
    Ale inne napiecia już się nie zgadzają...

    0
  • #26 21 Kwi 2013 18:17
    skoomi
    Poziom 11  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zasilam procesor ze stabilizatora lm7805 wraz z zalecanymi kondensatorami. Wychodzi 5,03V.

    Problem rozwiązany.
    Zmieniłem
    ADCSRA = 0xE0;
    na
    ADCSRA |= (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADPS1);
    czyli ustawiłem jeszcze prescaler na 4 a nie standardowe 2 i teraz zaczyna od wartości 0, a wszystkie inne się zgadzają ;)

    Nie wiem tylko dlaczego tak się działo kiedy prescaler był 2. Może ktoś to wyjaśnić?

    0
  • #27 21 Kwi 2013 19:06
    BlueDraco
    Specjalista - Mikrokontrolery

    Czytaj wartość ADC i zamieniaj na cyfry wtedy, gdy kończysz wyświetlanie czterech cyfr, czyl raz na 4 przerwania timera. Czytanie na okrągło wartości w pętli głównej jest bez sensu, a birąc nową wartość całego pomiaru dla każdej cyfry ryzykujesz np. to, że przy oscylacji 99<->100 wyświetlisz wynik 199.

    0
  • #28 21 Kwi 2013 19:15
    skoomi
    Poziom 11  

    Ok zmieniłem to. Teraz wartość stała się stabilniejsza ;)
    Niestety wartość adc dalej nie zgadzała się z napięciem zmierzonym. Zmieniłem więc prescaler na 8 i teraz jest jeszcze lepiej. Ale np dla 2,5V wyświetla 995 a nie 1000. Zaraz jeszcze zwiększę dzielnik i zobaczę co będzie;>
    Niestety przy podziale przez 16 i więcej nie jest lepiej.

    0
  • #29 21 Kwi 2013 19:26
    BlueDraco
    Specjalista - Mikrokontrolery

    żartujesz chyba. Dokładność 1% dla ADC w ATmega to tak w sam raz, a Ty marudzisz o 0.5%.

    Do wyświetlania nie ma sensu pobierać nowego odczytu częściej niż 2..3 razy na sekundę.

    0
  • #30 21 Kwi 2013 19:28
    skoomi
    Poziom 11  

    Dzięki. W takim razie biorę się za czujnik temperatury.

    0