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.

[Atmega8][C++] - ADC i wyświetlacz 7seg nie współpracują

afterparty 05 Mar 2013 18:12 1821 8
  • #1 05 Mar 2013 18:12
    afterparty
    Poziom 12  

    Cześć, tym razem chciałem napisać program, który wyświetli wynik konwersji ADC na czterech wyświetlaczach 7-seg:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    Postanowiłem wykorzystać funkcję zwracającą cyfry z tego tematu: Link
    Zrobiłem dzielnik napięcia - fotorezystor i rezystor 4k7, i podłączyłem do VCC, GND i pinu PC0 - czyli kanału ADC0. Problem w tym, że powyższy kod nic nie robi. Cały czas na wyświetlaczu mam 0000. Po prostu już nie wiem co jest nie tak, podpowie ktoś?
    [Atmega8][C++] - ADC i wyświetlacz 7seg nie współpracują
    Pełny schemat:
    [Atmega8][C++] - ADC i wyświetlacz 7seg nie współpracują

    0 8
  • Arrow Multisolution Day
  • #2 05 Mar 2013 19:15
    tmf
    Moderator Mikrokontrolery Projektowanie
  • #3 06 Mar 2013 18:38
    afterparty
    Poziom 12  

    tmf napisał:
    A jak myślisz, jak zadziała pętla tego typu:
    Kod: c
    Zaloguj się, aby zobaczyć kod
    ?

    Cały czas będzie odejmować 1 :/

    Dobra teraz mam taki kod:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Teraz cały czas świeci się tylko zero na pierwszym wyświetlaczu, i nic więcej się nie dzieje, tak jakby mikrokontroler się zawiesił. O co chodzi?

    0
  • Arrow Multisolution Day
  • Pomocny post
    #4 06 Mar 2013 19:06
    BlueDraco
    Specjalista - Mikrokontrolery

    Wyłącz przerwanie ADC - bit ADIE nie powinien być ustawiony. W przerwaniu timera, kiedy zmieniasz licznik cyfr na 0, odczytaj ADC do zmiennej pomocniczej, a potem tę zmienną rozbij na cyfry. Nie rób tego w pętli głównej bez potrzeby w kółko. W pętli głównej tylko uśpij procesor.

    ((ADC % 1000) % 100) % 10 to dokładnie to samo co ADC % 10. Nie używaj wielu operatorów % w tej samej instrukcji - to nie ma sensu.

    Twój program prawdopodobnie wisi w przerwaniu ADC, które jest ciągle zgłoszone.

    Czy konwersja ADC chodzi w kółko? Jeśli nie, to po odczytaniu wyniku w przerwaniu timera startuj ADC ponownie.

    0
  • #5 06 Mar 2013 20:09
    afterparty
    Poziom 12  

    Co było źle:
    1. Nie włączyłem bitu ADSC - rozpoczęcie konwersji :)
    2. W extract_digit zamiast cyfry[1],[2],[3],[4] dałem cyfry[0],[1],[2],[3]

    Cytat:
    W przerwaniu timera, kiedy zmieniasz licznik cyfr na 0, odczytaj ADC do zmiennej pomocniczej,
    - a nie mogę poprostu rozbić na cyfry wartości bezpośrednio z ADC? (Jak teraz)

    Konwersja w trybie Free Running (działa ciągle)

    Nowy kod:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #6 06 Mar 2013 20:52
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie możesz odczytywać kilka razy pod rząd ADC, bo w trybie konwersji ciągłej może się zdarzyć, że wartość zmieni się w trakcie Twojej zamiany. Jeśli np. zmieni się z 99 na 100, to wyświetlisz 199.
    % 1000 % 100 to też to samo, co %100. Nie ma też sensu zmieniać wartości wyświetlanej aż tak często - do odczytu przez człowieka max. kilka razy na sekundę. Odliczaj dodatkowym licznikiem i wywołuj konwersję wyniku do wyświetlania nie przy każdym przemiataniu wyświetlacza, ale np. co 30, 50 albo 100 odświeżeń.

    Zmienną licznik zadeklaruj wewnątrz obsługi timera jako static uint_t licznik = 0;

    Przy pustej pętli głównej nie potrzebujesz deklarować niczego jako volatile.

    0
  • #7 07 Mar 2013 15:10
    afterparty
    Poziom 12  

    Cytat:
    Zmienną licznik zadeklaruj wewnątrz obsługi timera jako static uint_t licznik = 0;
    - nie miało być uint8_t? Bo nie chciało mi się skompilować bez tego 8. A co mi daje takie zdeklarowanie wewnątrz przerwania? Zmienną odswiez też tak mogę zdeklarować?

    Tu kod:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • Pomocny post
    #8 07 Mar 2013 18:31
    BlueDraco
    Specjalista - Mikrokontrolery

    Oczywiście uint8_t - zjadłem '8'.

    Jeśli zmienna jest używana tylko wewnątrz procedury, to powinna być zadeklarowana wewnątrz procedury. Jeśli taka zmienna ma "przeżywać" czas, kiedy procedura nie jest aktywna (czyli zachowywać wartość pomiędzy wywołaniami), to musi być zadeklarowana z atrybutem static.
    Ten sam atrybut oznacza coś zupełnie innego w odniesieniu do zmiennych i procedur zadeklarowanych na poziomie zewnętrznym - tam należy go używać jak najczęściej, do wszystkiego, co nie ma być widoczne w innych modułach (plikach programu).

    W programach jednomodułowych używamy static do wszystkich deklaracji zewnętrznych oprócz main() i procedur obsługi przerwań.

    Kod powyżej z grubsza dobry, tylko nie ma sensu czytać ADC, kiedy nic nie robisz z odczytaną wartością.

    0
  • #9 09 Mar 2013 11:02
    afterparty
    Poziom 12  

    Jak zwykle dzięki za pomoc. Na razie wszystko jasne.

    0