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

PIC18LF46K80 timer1 nie ustawia flagi przerwania

szymonjg 28 Mar 2017 19:00 2391 6
  • #1 28 Mar 2017 19:00
    szymonjg
    Poziom 15  

    Witam. Programuję sobie urządzenie w którym mam zajęty cały PORTB a potrzebuję podłączyć przycisk tak aby jego przyciśnięcie wyzwalało przerwanie. Wymyśliłem, że użyję do tego pinu T1CKI z którego sygnał użyję do przepełnienia timera1 ustawianego każdorazowo na wartość 0xFFFF.
    Timer1 inicjalizuję w poniższy sposób:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Oczywiście pin T1CKI (w tym przypadku RA5) ustawiam jako wejście, a przycisk podłączony mam tak aby jego przyciśnięcie robiło zbocze narastające, czyli pull down 4k7 do masy a druga strona przycisku podłączona jest do 3V3.
    Funkcja obsługi przerwania niskiego wygląda następująco:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Efekt działania programu gdy testowałem go przyciskając przycisk jak porąbany, jest taki, że przerwanie wykonuje się raz, czasem 2 razy i potem nici. Program działa ale przycisk nie reaguje. Debugując program PICKITem3 zauważyłem, że timer jest poprawnie ustawiany wartością 0xFFFF tylko najprawdopodobniej w wyniku drgań styków timer dostaje kilka impulsów które zlicza dalej po przeładowaniu. Problem tylko w tym, że w międzyczasie nie ustawia mi na nowo flagi przerwania i nie wchodzi w przerwanie tylko liczy impulsy od zera.
    Na razie poradziłem sobie podłączając przycisk pod wejście modułu CAPTURE gdzie mam możliwość uzyskania flagi przerwania co każde zbocze i nie muszę nic przeładowywać jak tak jak timer.
    Może jednak ktoś zaznajomiony jest z PICami18 bardziej sprzętowo niż ja i wie dlaczego mi nie ustawia tej flagi w przypadku timera?

    W tym poście kolega krzysiek_krm napisał: "Zapomnieliście chyba, że po przyjęciu przerwania system przerwań jest chwilowo wyłączony, żadne dodatkowe przerwania nie będą przyjęte, flaga musi być skasowana gdziekolwiek przed instrukcją "reti", która powtórnie załącza przerwania." czyli można przez to zrozumieć, że na czas obsługi przerwania, moduł przerwań jest wyłączony i dlatego nie ustawia mi tej flagi mimo przepełnienia timera?

    0 6
  • #2 28 Mar 2017 23:46
    Zielonka
    Poziom 20  

    Witam
    Zamiast tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    spróbuj tak:
    Kod: c
    Zaloguj się, aby zobaczyć kod

    Pozdrawiam
    W.B

    0
  • #3 29 Mar 2017 00:47
    dondu
    Moderator Mikrokontrolery Projektowanie

    szymonjg napisał:
    W tym poście kolega krzysiek_krm napisał: "Zapomnieliście chyba, że po przyjęciu przerwania system przerwań jest chwilowo wyłączony, żadne dodatkowe przerwania nie będą przyjęte, flaga musi być skasowana gdziekolwiek przed instrukcją "reti", która powtórnie załącza przerwania." czyli można przez to zrozumieć, że na czas obsługi przerwania, moduł przerwań jest wyłączony i dlatego nie ustawia mi tej flagi mimo przepełnienia timera?

    A czytałeś moje posty w tamtym temacie?

    Czego nie rozumiesz z:

    Cytat:
    The interrupt flag bits must be
    cleared in software before re-enabling interrupts to
    avoid recursive interrupts.

    i:
    Cytat:
    When a valid edge appears on the RBx/INTx pin, the
    corresponding flag bit, INTxIF, is set. This interrupt can
    be disabled by clearing the corresponding enable bit,
    INTxIE. Before re-enabling the interrupt, the flag bit
    (INTxIF) must be cleared in software in the Interrupt
    Service Routine.

    oraz:
    Cytat:
    The TMR1 register pair (TMR1H:TMR1L) increments
    from 0000h to FFFFh and rolls over to 0000h. The
    Timer1 interrupt, if enabled, is generated on overflow
    which is latched in interrupt flag bit, TMR1IF
    (PIR1<0>). This interrupt can be enabled or disabled
    by setting or clearing the Timer1 Interrupt Enable bit,
    TMR1IE (PIE1<0>).

    wraz z rysunkiem timera: FIGURE 14-1: TIMER1 BLOCK DIAGRAM

    http://ww1.microchip.com/downloads/en/DeviceDoc/39977f.pdf

    0
  • #4 29 Mar 2017 10:14
    szymonjg
    Poziom 15  

    Zielonka napisał:
    spróbuj tak: (...)

    Próbowałem i to samo. A nawet metoda gdzie najpierw przeładowuję timer a potem czyszczę flagę wydaje mi się mniej poprawna bo jeśli zbocze "napędzające" timer wystąpi pomiędzy tymi dwoma operacjami i w tym momencie mi ustawiło flagę od timera to sobie ją wyczyszczę i już drugi raz nie załaduję do timera wartości x0FFFF co robię w tym przerwaniu.

    dondu napisał:
    A czytałeś moje posty w tamtym temacie?

    Czytałem. Ogólny wniosek był taki, że to programista decyduje kiedy gasi flagę przerwania w zależności od tego co chce osiągnąć, dlatego w moim przypadku gaszę flagę na samym początku wykrycia przerwania od timera aby nie zgubić żadnej flagi nawet jeśli miało by to oznaczać wykonanie kilku przerwań po sobie. Bo w końcu użytkownik zabrał by swoje brudne łapska z przycisku i styk przestałby drgać.

    dondu napisał:
    Czego nie rozumiesz z: (...)

    Nie rozumiem tylko zwrotu "rekurencyjne przerwania" (a przynajmniej tak mi przetłumaczyło google). Czy chodzi o to o czym pisał w przytaczanym już wątku kol. Urgon, że funkcja obsługi przerwania również może zostać przerwana przez przerwanie tego samego poziomu i jej aktualny stan będzie odkładany na stos aż do jego przepełnienia? Coś jak w przypadku zwykłych funkcji uruchamianych rekurencyjnie?

    dondu napisał:
    i: (...)

    Flagą INT0IF proszę się nie sugerować. Wiem jak działa przerwanie z pinu zewnętrznego i domyślam się że z timerem nie ma ono za dużo wspólnego, ale w tym kodzie ustawiam ją celowo bo taki mam zamiar. Po prostu zadaniem przycisku podłączonego do wejścia T1CKI jest właśnie ustawienie flagi INT0IF w razie gdyby na pinie RB0/INT0 nic się nie działo przez dłuższy czas.

    dondu napisał:
    oraz: (...)

    Wiem, że TIMER liczy od zera do FFFFh, ale nie chcę naciskać przycisku 65535 razy aby uzyskać kolejne przerwanie tylko zależy mi aby przerwanie od Timera1 było co każde naciśnięcie przycisku podłączonego do pinu T1CKI, dlatego w zarówno przy inicjalizacji timera jak i wewnątrz funkcji obsługi przerwania ustawiam jego wartość od razu na FFFFh tak by każde następne zbocze narastające z pinu T1CKI go przepełniało. Problem tylko jest w tym, że timer owszem się przepełnia, tylko nie powoduje mi to kolejnego przerwania tak by znowu nastąpiło jego załadowanie wartością FFFFh. Bit TMR1IE również ustawiam przy inicjacji przerwania.
    Schemat timera przeglądałem nie raz, ale tam również nie znalazłem podpowiedzi do rozwiązania mojej zagadki.

    0
  • #5 29 Mar 2017 11:16
    BlueDraco
    Specjalista - Mikrokontrolery

    Ile jeszcze razy trzeba będzie napisać, że przycisków NIE obsługuje się przy użyciu przerwań generowanych przez zmianę stanu wejścia? Temat powraca co kilka dni.
    Rozwiązanie, które Autor próbuje wdrożyć, po usunięciu błędów związanych z programowaniem timera i tak nie będzie działać, więc po co te starania o poprawne zaprogramowanie niedziałającego mechanizmu?
    Czemu, Koledzy odpowiadacze, wpuszczacie Autora w maliny?

    Moderowany przez dondu:

    Parafrazując:
    Ile razy mamy tłumaczyć, że to projektant decyduje jak wykorzysta przycisk i mikrokontroler.
    Jeśli ma taką potrzebę, a ma:

    szymonjg napisał:
    By już tutaj nie mieszać w między czasie założyłem nowy temat, w którym wyjaśniam dlaczego się z tym tak gimnastykuję i w którym pytam się co zrobić gdy jednak to przerwanie od przycisku wydaje się być jedynym rozwiązaniem.

    to może wykorzystać przycisk i przerwanie.

    0
  • Pomocny post
    #6 29 Mar 2017 14:42
    krzysiek_krm
    Poziom 34  

    Witam,

    BlueDraco napisał:
    Ile jeszcze razy trzeba będzie napisać, że przycisków NIE obsługuje się przy użyciu przerwań generowanych przez zmianę stanu wejścia? Temat powraca co kilka dni.
    Rozwiązanie, które Autor próbuje wdrożyć, po usunięciu błędów związanych z programowaniem timera i tak nie będzie działać, więc po co te starania o poprawne zaprogramowanie niedziałającego mechanizmu?
    Czemu, Koledzy odpowiadacze, wpuszczacie Autora w maliny?

    Jest coś na rzeczy.
    Zapewne mają miejsce jakieś bliżej nieznane hazardy, możliwe, że nieprzewidziane przez producenta.
    Może powinieneś (na przykład) jednak synchronizować ten timer.
    A może powinieneś (na przykład) w ISR, wyłączyć timer na czas ładowania a następnie włączyć z powrotem.
    Dość intrygująca jest również uwaga w ramce na stronie 212 dokumentacji (o konieczności pojawienia się opadającego zbocza a nie niskiego poziomu).
    Po co w ogóle taka dziwna kombinacja ?
    Możesz skonfigurować ten timer do generowania cyklicznego przerwania, w ISR możesz badać stan przycisku z uwzględnieniem drgań styków i dalej robić co tam trzeba. Przycisk to nie jest jakiś szybki interfejs żeby trzeba było czas reakcji optymalizować do granic wytrzymałości ludzkiej.

    Pozdrawiam

    0
  • #7 29 Mar 2017 18:09
    szymonjg
    Poziom 15  

    krzysiek_krm napisał:
    Może powinieneś (na przykład) jednak synchronizować ten timer.

    Dzięki za sugestię bo nie pomyślałem o tym wcześniej, jednak i to nie pomogło.

    krzysiek_krm napisał:
    A może powinieneś (na przykład) w ISR, wyłączyć timer na czas ładowania a następnie włączyć z powrotem.

    To rozwiązanie pomogło, choć nie bezpośrednio. Bowiem rzeczywiście chwilowe wyłączenie timera i włączenie go gdy wszystko już będzie ustawione powinno
    wyeliminować wszelkie hazardy typu: nieprzewidziane zbocza w momencie wpisywania nowej wartości do rejestru. Mimo wszystko, debugując program i zatrzymując go po przeładowaniu timera jego wartość była taka jak trzeba a gdy dalej puszczałem program na sekundę to nawet bez dotykania felernego przycisku wartość Timera się zerowała. I to mnie zmobilizowało do znalezienia przyczyny.
    Przyczyną okazał się burdel w kodzie, bowiem nie posprzątałem po poprzednim zastosowaniu tego timera w tej aplikacji, jakim było właśnie cykliczne sprawdzanie stanu trzech innych przycisków, występujących w tej aplikacji. Bowiem obsługując te przyciski po wykonaniu kodu przypisanego dla wciśniętego klawisza zerowałem nie tylko zmienną z zapisanym stanem przycisków ale również flagę jak i rejestry liczące timera. Później zachciało mi się czwartego przycisku powodującego przerwanie, dlatego trzy poprzednie przeniosłem z TIMER1 na TIMER2 a czwarty podłączyłem pod wejście T1CKI jak już pisałem wcześniej. I wszystko było by dobrze gdyby nie niechciane już funkcje zerujące TIMER1. Po ich usunięciu wszystko działa tak jak trzeba zgodnie z fragmentami kodu z pierwszego postu.

    krzysiek_krm napisał:
    Dość intrygująca jest również uwaga w ramce na stronie 212 dokumentacji

    Rzeczywiście jest coś z tym na rzeczy bowiem testując już teraz kod, czasem pierwsze wejście do przerwania od timera wymagało dwukrotnego przyciśnięcia czyli wystąpienia również zbocza opadającego. Jednak każde następne wywołanie działa już poprawnie na zbocze narastające, czyli najprawdopodobniej to wymagane zbocze opadające liczy się też z poprzedniego przerwania.

    Reasumując:
    Da się obsługiwać przycisk podłączony do pinu wejścia timera, albo innego pinu powodującego przerwanie po wystąpieniu jakiegoś zbocza,ale nie jest to zalecane bo dużo lepiej jest to zrobić tak:
    krzysiek_krm napisał:
    Możesz skonfigurować ten timer do generowania cyklicznego przerwania, w ISR możesz badać stan przycisku z uwzględnieniem drgań styków i dalej robić co tam trzeba

    co z resztą już nie raz było poruszane np tu.

    By już tutaj nie mieszać w między czasie założyłem nowy temat, w którym wyjaśniam dlaczego się z tym tak gimnastykuję i w którym pytam się co zrobić gdy jednak to przerwanie od przycisku wydaje się być jedynym rozwiązaniem.

    Wszystkim udzielającym się tutaj serdecznie dziękuję, a tym co chcieli mnie wpuścić w maliny (jeśli tacy byli) to niech się przytrafia w kodzie 2 razy tyle błędów co mi. :)

    0