logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Atmega8][C][PCF8583P] - Wewnętrzne przerwania asynchroniczne. Czy potrzebne?

Marcin1828 26 Lip 2016 01:08 1974 18
REKLAMA
  • #1 15830052
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    Opracowałem zegar elektroniczny oparty na mikrokontrolerze Atmega8 i zegarze PCF8583P.

    Działanie programu napisanego w C:
    -w nieskończonej pętli głównej wyświetlam na wyświetlaczu LED godziny i minuty poprzez multipleksowanie
    -za każdym wyświetleniem wyświetlacza pobierany i zapisywany jest czas z PCF8583P
    -posiadam dwa przyciski, którymi ustawiam czas

    Możnaby powiedzieć że zegar jest skończony i działa poprawnie, ale zastanawiam się czy takie nieustanne pobieranie czasu z PCF-a jest dobrym rozwiązaniem? Jakie są jego wady? Jak mogę udoskonalić projekt? A może nie muszę go udoskonalać?

    Jest to dopiero mój drugi poważny projekt i aby nie wynosić z niego złych nawyków proszę o radę.
  • REKLAMA
  • #2 15830067
    excray
    Poziom 41  
    Posty: 5500
    Pomógł: 739
    Ocena: 656
    Marcin1828 napisał:
    zastanawiam się czy takie nieustanne pobieranie czasu z PCF-a jest dobrym rozwiązaniem?

    Nie widzę żadnych negatywów ani wad takiego rozwiązania. PCF ani atmega się z tego powodu nie zużyją. Może pokaż schemat, kod. Ciężko bez tego powiedzieć co możesz poprawić. Zegarek zasilany z..?
    Marcin1828 napisał:
    -w nieskończonej pętli głównej wyświetlam na wyświetlaczu LED godziny i minuty poprzez multipleksowanie

    Lepiej by było upchnąć to do przerwania.
  • #3 15830409
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Marcin1828 napisał:
    -za każdym wyświetleniem wyświetlacza pobierany i zapisywany jest czas z PCF8583P

    Nie zapisuj czasu, jeśli nie ma takiej potrzeby.

    Pokaż program i schemat to Ci podpowiemy co i jak.
  • #4 15831864
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    excray napisał:
    Lepiej by było upchnąć to do przerwania.


    Wrzuciłem wyświetlanie godziny na led do przerwania ale przez to ustawianie godziny przestało działać. Po uruchomieniu układu nie działa poprawnie także test wyświetlacza. Da się jakoś zablokować przerwanie jeżeli jestem w trybie ustawiania godziny?

    Oto kod:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #5 15831932
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Marcin1828 napisał:
    Da się jakoś zablokować przerwanie jeżeli jestem w trybie ustawiania godziny?


    Lepiej zamiast tego zrobić całość POPRAWNIE.

    tj:
    1. Bez instrukcji opóźniających
    2. Z eliminacją drgań styków za pomocą przerwania timera (najlepiej tego samego, co od obsługi LEDów)
    3. Odczyt z PCF też wykonywać w przerwaniu (układ ten generuje impulsy o częstotliwości 1Hz - idealne do podłączenia na przerwanie zewnętrzne procesora)
    4. Zapis godziny tylko jeśli trzeba

    Zacznij od poprawnej obsługi LEDów. Przykład zanjdziesz np. http://and-tech.pl/zestaw-evb-5-1/ (przykłady C)
  • REKLAMA
  • #6 15848747
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    Obsługę LEDów zrobiłem zgodnie z przykładem, ale musiałem zmodyfikować przerwanie bo były tam ustawiane inne rejestry niż w Atmedze8.

    Proszę o wyjaśnienie punktu nr 2.

    Ad3
    Zrobiłem przerwanie zewnętrzne INT0, ale koliduje mi ono z tym od LEDów i w rezultacie godzina nie jest pobierana.

    Oto nowy schemat:
    [Atmega8][C][PCF8583P] - Wewnętrzne przerwania asynchroniczne. Czy potrzebne?
  • #7 15849796
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Pokaż program - musiałeś coś ostro namieszać ;)
  • REKLAMA
  • #9 15851920
    JacekCz
    Poziom 42  
    Posty: 8670
    Pomógł: 760
    Ocena: 1462
    a) delay de facto w pętli przerwania (bo w showTimeOnLEDS() ), to może/musi miec głębokie skutki
    b) volatile jest użyte w sposób który myli, to nie działa tak, jak myślisz.
  • #10 15872048
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    Przerwanie TIMER0_COMP_vect, które było użyte w przykładzie od piotrva zastąpiłem TIMER2_COMP_vect.
    Taktowanie procesora w fusebitach ustawiłem na 4MHz- wystarczające?
    Mruganie dwukropka zrobiłem jako zwyczajną pętlę(pewnie powiecie że trzeba też wrzucić to w przerwanie).
    Nie wiem co z ustawianiem godziny. Może zostać w tym miejscu, w którym jest? Wszystkie delay_ms() zastąpić przerwaniami? W jaki sposób to zrobić?

    Bez przerwania zewnętrznego INT0 wszystko działa poprawnie. Po jego "odkomentowaniu" dwukropek mruga częściej i nie jest pobierana godzina z PCF8583P(ciągle wyświetla 00:00).

    Wrzucam kod, zobaczcie proszę w czym problem.
    Załączniki:
    • ZegarLED.zip (7.38 KB) Musisz być zalogowany, aby pobrać ten załącznik.
  • #11 15872887
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Umieść kod w znacznikach syntax - będzie szybciej i łatwiej ocenić.
  • REKLAMA
  • #12 15872923
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    main.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod



    7SEG.c:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #13 15873009
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    1. nie definiuj F_CPU w kodzie!!!!!!!!!!
    2. nie stosuj zapisów typu: PORTC = 0x0c; - zamiast tego użyj etykiet oraz operacji bitowych - tak jak w zapisie do MCUCR np.
    3. mruganie zdecydowanie na przerwanie timera - masz nawet LED_timer ;)
    4. aktualizacja zawartości wyświetlacza - wywołanie funkcji LED_dec(liczba,0); - powinno odbywać się tylko po odczytaniu czasu z zegara - czyli nie częściej niż raz na sekundę - w przerwaniu INT0 - ustawiaj sobie jakąś flagę.
    5. Kopiując spore kawałki kodu - warto zachować informacje skąd je masz ;)
  • #14 15873929
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    Ad 1. Definiowałem bo bez definicji Atmel Studio pokazuje mi warninga. Właściwie dlaczego tego nie można robić? :D
    Ad 2. Zmienione.
    Ad 3. Dobrze to zrobiłem?
    Ad 4. Zrobiłem jakąś flagę, ale chyba źle... Mam straszny problem z tym przerwaniem zewnętrznym. Zaburza cały program. Po odłączeniu PCF-a od INT0 działa ładnie.

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #15 15874036
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Ad. 1. To definiuje się w opcjach projektu. Dlaczego? Bo tylko wtedy definicja będzie widoczna dla wszystkich plików. W przeciwnym wypadku np. plik od obsługi uartu będzie miał inną F_CPU, plik delay.h jeszcze inną a main - trzecią watość.
    Ad. 3. Trochę dobrze, ale skąd naczytałeś się, aby dawać takiego "nop"? Taki blok należy umieścić w bloku atomowym - poczytaj o tej kwestii.
    Ad. 4. Co ta flaga ma robić? Bo u Ciebie coś dziwnego.
    Ona powinna być: po każdym odczycie z zegarka ustawiana na 1, a w main sprawdzana i kasowana:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Co z Ad. 5.?
  • #16 15874523
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    Ad 1. Zdefiniowałem F_CPU jako symbol w ustawieniach Toolchain->Compiler->Symbols i działa poprawnie. Dziękuję za wyjaśnienie. :)
    Ad 5. Źle Cię zrozumiałem, już dodane oczywiście. Oryginalnie było samo imię i usunąłem :-?
    Reszta poprawiona.

    Nadal wszystko komplikuje przerwanie INT0. Nie wykonują się instrukcje wewnątrz przerwania. W tej sytuacji nie pojawia się nic na wyświetlaczu i dwukropek zapala się nieregularnie. Co jest nie tak z tym przerwaniem?

    Oto kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #17 15875148
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Skąd wiesz, że przerwanie się nie wykonuje?
    Dalej - włącz podciąganie na linii przerwania.
  • #18 15876437
    Marcin1828
    Poziom 11  
    Posty: 131
    Ocena: 6
    piotrva napisał:
    Skąd wiesz, że przerwanie się nie wykonuje?

    Wnioskuję po tym, że wrzucając do przerwania instrukcję RTC_Read_Time() wyświetla się godzina 00:00, a jeżeli wrzucę ustawianie flagi to nic się nie wyświetla.
    piotrva napisał:
    Dalej - włącz podciąganie na linii przerwania.

    Znalazłem jedno miejsce w kodzie gdzie ten rezystor mógł być przypadkowo odłączany i poprawiłem, ale nie przyniosło to poprawy...
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Nie wiem co dalej nie gra. Nadal jest coś nie tak z INT0, ale nie potrafię stwierdzić co...


    Na tę chwilę dwukropek miga bardzo nieregularnie a wyświetlacz jest zgaszony.
    Oto kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #19 15876948
    piotrva
    VIP Zasłużony dla elektroda
    Posty: 6409
    Pomógł: 625
    Ocena: 735
    Linijka z ustawianiem portów może wywoływać przerwanie. Musisz trochę nad tym popracować.

    Ponadto, czy masz analizator stanów logicznych? Jeśli nie to kupuj szybko ;)

Podsumowanie tematu

✨ Użytkownik stworzył zegar elektroniczny oparty na mikrokontrolerze Atmega8 oraz zegarze PCF8583P, z programem w C, który wyświetla czas na diodach LED. Zastanawia się nad efektywnością ciągłego pobierania czasu z PCF8583P oraz nad możliwością poprawy projektu. Odpowiedzi sugerują, aby zamiast nieustannego odczytu czasu, wykorzystać przerwania do pobierania danych z zegara oraz do obsługi LED-ów. Wskazano na problemy z przerwaniem INT0, które koliduje z innymi funkcjami, co prowadzi do błędów w wyświetlaniu czasu. Użytkownik został zachęcony do poprawy kodu, eliminacji opóźnień oraz lepszego zarządzania przerwaniami.
REKLAMA