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.

[m32][C] zegar LED, brak multipleksu, kompilacja bez błędów.

Antystatyczny 21 Lip 2012 11:48 3269 51
  • #1 21 Lip 2012 11:48
    Antystatyczny
    Poziom 16  

    Witam.

    Napisałem program zegara LED, który kompiluje się bez błędów, a mimo to nie działa. Sprzęt mam sprawny, bo wysterowałem na piechotę każdy z segmentów wszystkich 4 cyfr zaświecając w ten sposób wszystkie elementy wyświetlacza. Do próby przełączyłem cały PortA na diody podłączone przez rezystory do masy i widzę, że uC wystawia nań dane( początkowo liczbę 0). W miarę upływu czasu, a konkretnie co 60 sekund, informacja na porcie ulega modyfikacji. Przełączyłem z powrotem PortA na katody wyświetlacza, a jedną z anod na sztywno wysterowałem (masa na bazę tranzystora PNP, a w kolektorze anoda cyfry wyświetlacza). Program wyświetla 0, a w miarę upływu czasu, począwszy od upływu 1 minuty, na wyświetlaczu pojawiają się duszki. Wnoiskuję z tego, że przełączanie zawartości wystawianej na PortA działa. W związku z tym, bardzo proszę o zerknięcie w poniższy kod i sprawdzenie, czy prawidłowo obsługuję PortB ze szczególnym uwzględnieniem pinów 0:3, którymi steruję anody wyświetlacza. Podobnie napisany program w Bascom działał.
    Zastosowałem następującą metodę:
    1. Zgaś katody.
    2. włącz anodę 1.
    3. wyłącz anodę 4.
    4. porta skojarz ze zmienną godzina1 korzystając ze zmiennej tymczasowej temp.
    5. włącz anodę 2.
    6. wyłącz anodę 1.
    7. porta skojarz ze zmienną godzina2 korzystając ze zmiennej tymczasowej temp.
    8. włącz anodę 3.
    9. wyłącz anodę 2.
    10. porta skojarz ze zmienną minuta1 korzystając ze zmiennej tymczasowej temp.
    11. włącz anodę 4.
    12. wyłącz anodę 3.
    13. porta skojarz ze zmienną minuta2 korzystając ze zmiennej tymczasowej temp.

    Prezentuję kompletny kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    PS. Szukałem w google, porównywałem mój kod z wieloma innymi. Elektrodę również przetrzepałem. Moja obsługa multipleksu wygląda na typowo stosowaną.

    Pozdrawiam.

    0 29
  • Arrow Multisolution Day
  • #2 21 Lip 2012 12:06
    Fredy
    Poziom 27  

    Ustawianie w C dajmy na to Portu C pin 3 odbywa się tak:
    PORTA|=(1<<3);

    ale kasowanie już tak nie można robić:
    PORTA|=(0<<3); <--- to nie zadziała !!!!!

    DO kasowania używa się operacji :
    PORTA&=~(1<<3);

    Ponadto, jeżeli masz takie coś :
    klawisz3 = (PORTB & 0b01000000);
    klawisz3 = (klawisz3 >> 6);

    a potem robisz if(klawisz3) .....
    To po co jest ta operacja przesuwania (klawisz3 = (klawisz3 >> 6);?
    W języku C if działa zarówno dla wartości 1 jaki i każdej innej różnej od 0.

    Możesz zatem zrobić to tak:

    if (PORTB & 0b01000000) .......

    I wtedy masz to wszystko w jednej linijce, bez użycia dodatkowej zmiennej.

    0
  • #3 21 Lip 2012 13:44
    Antystatyczny
    Poziom 16  

    Zmodyfikuję program wedle wskazówek i sprawdzę jego działanie. Póki co dzięki za odpowiedź.
    W zmiennych klawisz1:4 przesuwałem bity, by uzyskać wartość 1 lub 0. Ot, tylko dla pewnej elegancji (w moim subiektywnym odczuciu).

    Dodano po 1 [godziny] 18 [minuty]:

    Po poprawkach nadal nie działa.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #4 21 Lip 2012 15:47
    LordBlick
    VIP Zasłużony dla elektroda

    Zacznijmy od tego, że zdefiniuj sobie nazwy co pod co podpinasz, np.

    Kod: C
    Zaloguj się, aby zobaczyć kod
    no i wtedy wypadałoby tego używać... ;)
    Po drugie niepoprawnie ustawiasz DDRB(tam gdzie masz komentarz "Poprawiony zapis" ;) ). Powinieneś oddzielnie najpierw wyzerować bity od wejść, a potem ustawić bity od wyjść. Uwzględniając uwagę wyżej :
    Kod: C
    Zaloguj się, aby zobaczyć kod

    Po trzecie klawisze to się czyta w PINX...
    Kod: C
    Zaloguj się, aby zobaczyć kod

    0
  • #5 21 Lip 2012 19:00
    Antystatyczny
    Poziom 16  

    Bardzo dziękuję za te informacje. W przyszłości będę to rozbijał na dwie linie(zerowanie i ustawianie bitów rejestru). Tymczasem, po przeczytaniu datasheet, a konkretnie sekcji dotyczącej Timer0 i Timer2, stwierdziłem, że mogę po prostu wpisać jedną liczbę do np. rejestru TCCR0. Np TCCR0 = 0b00001111. To powinno spowodować włączenie pinów 7:4 jako wejścia i 3:0 jako wyjścia. Posiłkując sie tym wnioskiem zmodyfikowałem program. W celu testowym przerzuciłem sterowanie wspólnymi anodami na PORTC3:0. Z moich obserwacji: Po ponownym podłączeniu diod LED do PORTA i dokładnym przyjrzeniu się im, zauważyłem, że treść wysyłana na PORTA zmienia się co około 15 sekund. Istnieje jakaś szansa, że dwa przerwania się ze sobą "gryzą". Wiem, że w Atmega32 przerwania nie mają priorytetów i wykonuje się to, które wystąpi najprędzej.

    Dodano po 47 [sekundy]:

    I jeszcze kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 9 [minuty]:

    Zmiana treści na PORTA co 15 sekund była spowodowana błędnym ustawieniem preskalera. Poprawiłem.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #6 21 Lip 2012 21:23
    Fredy
    Poziom 27  

    Czytaj uważnie co piszemy Ci, bo nadal robisz błedy.
    Ta linijka programu jest nieprawidłowa, poszukaj sam błedu:

    PORTC |= ~(1<<PC0);//włącz pierwszą cyfrę - poprawiony zapis,

    0
  • #7 21 Lip 2012 21:28
    Antystatyczny
    Poziom 16  

    Już sprawdzam.

    0
  • Pomocny post
    #8 21 Lip 2012 21:33
    Fredy
    Poziom 27  

    Ok, powtórzę ci.
    aby skasować bit w rejestrze musisz zrobić tak:
    PORTC &= ~(1<<PC0);

    a nie

    PORTC |= ~(1<<PC0);

    Widzisz różnicę ?

    0
  • Arrow Multisolution Day
  • #9 21 Lip 2012 21:42
    Antystatyczny
    Poziom 16  

    Tak, widzę... I nikt inny (doświadczony) tego nie zauważył? Bardzo, dziękuję!
    Doszedłem do momentu, w którym stwierdziłem, że jedynie sterowanie anodami mi nie działa. Nie zdążyłem jeszcze przeanalizować różnic, ale gołym okiem wiedzę, że są.
    Za chwilę dam znać o wynikach poprawek.
    Raz jeszcze dziękuję.

    0
  • Pomocny post
    #10 21 Lip 2012 21:45
    LordBlick
    VIP Zasłużony dla elektroda

    No i wreszcie mógłbyś używać definicji, kod przez to staje się uniwersalny, przy zmianie konfiguracji podłączeń zmieniasz tylko w jednym miejscu, a nie w 54...

    0
  • #11 21 Lip 2012 21:46
    Antystatyczny
    Poziom 16  

    Działa multipleks! Teraz to sobie na spokojnie przeanalizuję. Klikam POMÓGŁ. Teraz, gdy mam juz wizję, obserwuję nieprawidłową pracę obsługi klawiszy, ale z tym sobie poradzę :-) Bardzo, ale to bardzo dziękuję!

    0
  • #12 21 Lip 2012 21:49
    LordBlick
    VIP Zasłużony dla elektroda

    Antystatyczny napisał:
    I nikt inny (doświadczony) tego nie zauważył?
    Pisałem o tym wcześniej, myślałem, że się zastosujesz:
    LordBlick napisał:
    Po drugie niepoprawnie ustawiasz DDRB(tam gdzie masz komentarz "Poprawiony zapis" :wink: ).

    0
  • #13 21 Lip 2012 21:49
    Antystatyczny
    Poziom 16  

    Lordblick, czytałem rózne posty... również takie, w których #define nie było polecane. Uczę się treści programu, a na definicje dla kompilatora też poświęcę czas. Bardzo dziękuję za wszelkie podpowiedzi i sugestie. Szczególnie serdecznie pozdrawiam moderatora za to, że nie zablokował tego tematu.

    Popracuję nad resztą kodu i gdy będzie działał prawidłowo, zamieszczę w całości.

    0
  • #14 21 Lip 2012 21:53
    LordBlick
    VIP Zasłużony dla elektroda

    Antystatyczny napisał:
    Lordblick, czytałem rózne posty... również takie, w których #define nie było polecane.
    Tak ogólnie, czy tylko dotyczące F_CPU ?

    0
  • #15 21 Lip 2012 22:03
    Antystatyczny
    Poziom 16  

    Tak ogólnie... Nie przytoczę teraz źródła, ale widziałem nawet taką wypowiedź, która traktowała wystąpienia #define jako mało profesjonalne. Jestem póki co lamerem, więc się nie odnoszę do tamtej wypowiedzi. Staram się ogarnąć kod, a na dyrektywy też będzie czas... Po prostu nie potrafię ogarnąc wszystkiego jednoczesnie. (Właśnie patrzę jak na wyświetlaczu pieknie odmierza mi się czas od momentu właczenia uC) :) To mi dodało wiatru w skrzydła!

    Dodano po 4 [minuty]:

    Do poprawy obsługa klawiszy.

    0
  • #16 21 Lip 2012 22:19
    LordBlick
    VIP Zasłużony dla elektroda

    Antystatyczny napisał:
    Nie przytoczę teraz źródła, ale widziałem nawet taką wypowiedź, która traktowała wystąpienia #define jako mało profesjonalne.
    Nie uwierzę, dopóki nie zobaczę. Jeśli masz na myśli tą wypowiedź, to nie ma ona takiego sensu, jak to odebrałeś, dotyczyła konkretnego zastosowania zamiast struktury.

    0
  • #17 21 Lip 2012 22:27
    Antystatyczny
    Poziom 16  

    Po sprawdzeniu tablic prawdy piszę dla potomnych (głównie nowicjuszy, jak ja):
    Podczas wstawiania jedynki do bajtu należy użyć OR. Podczas wstawiania zera należy użyć AND.

    Dodano po 3 [minuty]:

    Lordblick, nie... Nie o tę wypowiedź mi chodziło. Dziś od rana przeglądałem sieć w poszukiwaniu rozwiązania problemu braku multipleksu i w pewnym momencie natknąłem się na komentarz do jakiegoś tam rozwiązania, że #define stosują niedoświadczeni, że nie znają innych dyrektyw itp. Postaram się znaleźć to źródło. Dla mnie to żadna opinia, bo się jeszcze na tym nie znam.

    0
  • #18 22 Lip 2012 08:12
    Antystatyczny
    Poziom 16  

    Panowie, męczę się z obsługą 4 przycisków. Na razie nic mądrego nie wymyśliłem. Przypisuję klawisze1:4 odpowiednim bitom PINB. Klawisze za chiny nie chcą działać. Mogę użyć czegoś takiego?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Oczywiście ta instrukcja sprawdza, czy PIN nie jest zwarty do masy.
    Poniższy kod mi nie działa.
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #19 22 Lip 2012 09:20
    LordBlick
    VIP Zasłużony dla elektroda

    Antystatyczny napisał:
    Klawisze za chiny nie chcą działać.
    1. Określ precyzyjniej, co chcesz osiągnąć i jak się objawia "nie działa".
    2. Powtarzam z uporem maniaka - wywal te cudowanie z tempX i zrób sobie definicje podpięcia klawiszy, będziesz wtedy pewny, ze się gdzieś nie pomyliłeś, bo nazwy z definicji ustalasz ty sam. Ma to tą zaletę, ze przy pisaniu programu nie musisz co chwila zerkać do schematu. Stosuję ta metodę z powodzeniem w asemblerze do wszystkiego, co się da, bo inaczej dawno bym się pogubił. Jak angielszczyzna nie odpowiada, to można i tak:
    Kod: C
    Zaloguj się, aby zobaczyć kod

    P.S. W internecie aż się roi od darmowych przykładów deboucingu w C, jeśli to masz na myśli.Nie da się bez sprawdzenia po pewnym czasie czy klawisz jest nadal wciśnięty, abstrahując od wybranej metody opóźnienia(delay_ms/timer)...

    0
  • #20 22 Lip 2012 09:34
    Antystatyczny
    Poziom 16  

    Naciskanie klawiszy nie powoduje inkrementacji/dekrementacji zmiennych godzina2 i minuta2. Fizycznie są sprawne( naciśnięcie klawisza powoduje zwarcie do masy konkretnego pinu portu b. To miałem na myśli, że nie działa. Cały portb mam ustawiony jako wejście z pull up. Zajmę się tymi dyrektywami, przepisze wszystko tak, by były określone klawisze w odpowiednich #define, ale niech mi to choć na chwilę ruszy.

    0
  • #21 22 Lip 2012 09:48
    LordBlick
    VIP Zasłużony dla elektroda

    Antystatyczny napisał:
    Zajmę się tymi dyrektywami, przepisze wszystko tak, by były określone klawisze w odpowiednich #define, ale niech mi to choć na chwilę ruszy.
    Pomyliłeś kolejność działań - większości czytających temat nie będzie się chciało majtać suwakiem przeglądarki z góry na dół i z powrotem, by co chwila sprawdzać, czy procedura jest zgodna z przypisaniem klawiszy. Jak przerobisz to na #define, będzie łatwiej i tobie i nam znaleźć problem.
    Myślę, że coś te zmienne temp i zatrzask mają coś na sumieniu, proponuję je wywalić (są zupełnie zbędne) i zrobić tak, jak napisałem, najpierw bez debouncingu.

    0
  • #22 22 Lip 2012 09:54
    Antystatyczny
    Poziom 16  

    Właśnie to przepisuję. Wkleję kod, gdy tylko skończę przeróbkę.

    0
  • #23 22 Lip 2012 10:06
    gaskoin
    Poziom 38  

    Antystatyczny napisał:
    Tak ogólnie... Nie przytoczę teraz źródła, ale widziałem nawet taką wypowiedź, która traktowała wystąpienia #define jako mało profesjonalne.


    Pewnie chodziło o to, że lepiej robić funkcje inline (dla makr które coś robią), lub o użycie const zamiast define (na AVR jednak lepiej używać define).

    0
  • #24 22 Lip 2012 10:13
    Antystatyczny
    Poziom 16  

    Poprawiony kod:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Skompilowany z kodem 0 i wgrany do uC. Klawisze nadal nie działają.

    0
  • #25 22 Lip 2012 10:13
    LordBlick
    VIP Zasłużony dla elektroda

    Dla mnie osobiście najważniejsza jest weryfikowalność kodu z założeniami( pochodzącymi ze schematu podłączeń).

    0
  • Pomocny post
    #26 22 Lip 2012 10:19
    Krauser
    Poziom 26  

    Tam masz:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    a raczej powinno być co kilkadziesiąt ms, czyli tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #27 22 Lip 2012 10:28
    Antystatyczny
    Poziom 16  

    Nie posiadam schematu w eagle. (Stworzę, gdy tylko opanuję ten program). Moduł uruchomieniowy mam stworzony własnoręcznie i przetestowany za pomocą BASCOM. Klawisze mam podłączone do pinów PB0, PB1, PB2 i PB3. Raz jeszcze sprawdziłem zgodność z pinoutem oraz miernikiem, czy faktycznie klawisze zwierają piny do masy. Zwierają. Makra mam w porządku napisane?

    Dodano po 3 [minuty]:

    Zmieniłem na:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nadal nie działa.

    0
  • #28 22 Lip 2012 10:36
    Krauser
    Poziom 26  

    No w sumie to też nie dobrze, bo anoda później przez 32ms i tak jest 0, a klawisze w tym czasie będą sprawdzane wielokrotnie. Należało by zmienną anoda zmienić, ale jest zmieniana w przerwaniu.
    Przenieś

    Kod: c
    Zaloguj się, aby zobaczyć kod

    do przerwania timera0 za
    Kod: c
    Zaloguj się, aby zobaczyć kod

    a pętlę for pozostaw pustą.

    0
  • #29 22 Lip 2012 10:55
    Antystatyczny
    Poziom 16  

    Po przeniesieniu wywołania funkcji klawisze(); do obsługi przerwania timer0 klawisze pięknie ruszyły. Teraz pozostało mi upchnąć obliczanie czasu do pętli głównej lub do przerwania od timer0, bo podczas naciskania np. MIN_PLUS, gdy zmienna minuta2 osiągnie wartość 10, wyświetla się na 4 cyfrze śmieć. Spowodowane jest to tym, że obliczanie czasu i wszelkie korekcje zmiennych wykonywane są tylko raz na sekundę. Po upływie sekundy zmienna minuta2 jest zerowana, a zmienna minuta1 inkrementowana. Dlaczego nie działały klawisze? Zbyt szybko je mapowałem przez co bounce powodował jakieś nieokreślone interakcje ze zmienną zatrzask?

    0
  • #30 22 Lip 2012 11:09
    Krauser
    Poziom 26  

    Podczas wciskania i puszczania klawisza występuje wielokrotne łączenie i rozwieranie przycisku, bo to element elektromechaniczny. Typowy czas takiego "bouncingu" to kilkanaście ms. Jeśli sprawdzasz stan wejść przycisków częściej to szybki mikrokontroler pojedyncze wciśniecie klawisza odczyta jako wielokrotne.

    0