Elektroda.pl
Elektroda.pl
X

Wyszukiwarki naszych partnerów

Wyszukaj w ofercie 200 tys. produktów TME
Europejski lider sprzedaży techniki i elektroniki.
Proszę, dodaj wyjątek elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32F407-DISC1, nie działa przerwanie od przycisku, NVIC, IRQHandler, EXTI...

marek1972_2 12 Mar 2017 21:40 1452 21
  • #1 12 Mar 2017 21:40
    marek1972_2
    Poziom 3  

    Witam,

    Temat: Program ma zrobić przerwanie na przycisku PC2 i PA0 tak aby zaświecić LED-ami na płytce.

    Zacząłem przygodę z STM32. Przerabiam poradnik ściągnięty z tego forum "Poradnik STM32 v1.9" . Bardzo interesująca lektura i bardzo wciągająca. Niestety napotkałem problem. Nie znalazłem odpowiedzi na forum więc piszę zapytanie tutaj.

    Chodzi o przerwanie pochodzące od przycisku które to powoduje zapalenie się LED. Walczę już od kilku dni , w miedzy czasie znalazłem wskazówkę że przerwanie na przycisk nie robi się za pomocą NVIC tylko o ile pamiętam za pomocą TIMER-a. Tak czy inaczej było w książce, mam problem i może ktoś mi pomoże, rzuci okiem i powie "hej kolego tu nie dałeś przecinka" - jakiś banalny error.

    Ten kod jest trochę rozrośnięty (był większy) ale to tak w celach testowo-edukacyjnych.

    Mam płytkę jak w temacie, przerwania pochodzą od przycisków PA0 (na płytce) i PC2 (zewnętrzny) zapalam LED-y te na pokładzie.

    Sprawdziłem wszystko, co mogłem ale nadal jakiś błąd sieci w kodzie.

    to mój kod:


    Kod: c
    Zaloguj się, aby zobaczyć kod


    I tak od góry:
    #include "bb.h" jest po to żebym mógł pisać
    BB(GPIOD -> ODR, GPIO_ODR_ODR_15) = 1 zamiast GPIOD - > ODR |= GPIO_ODR_ODR_15

  • Pomocny post
    #2 12 Mar 2017 21:51
    Freddie Chopin
    Specjalista - Mikrokontrolery

    marek1972_2 napisał:
    // Interrupt mask register, that EXTI lines are active: 0 and 1
    EXTI -> IMR = EXTI_IMR_MR0;   //A0
    EXTI -> IMR = EXTI_IMR_MR2;   //C2

    Druga linia kasuje to co zrobiła pierwsza.

    Przy okazji łatwiej by było jakbyś napisał DOKŁADNY opis problemu, bo tak naprawdę to nie wiadomo co Ci nie działa.
    Dodano po 1 [minuty]:
    marek1972_2 napisał:
    __attribute__ ((interrupt)) void EXTI0_IRQHandler(void)

    Atrybut jest całkowicie zbędny.
    Dodano po 1 [minuty]:
    marek1972_2 napisał:
       {    while(x <= 0) {   x = x - 1;    } } }

    Warunek mało sensowny, ponieważ x jest bez znaku.

  • Pomocny post
    #3 12 Mar 2017 22:28
    BlueDraco
    Specjalista - Mikrokontrolery

    Błędów całe mnóstwo.

    1. Nie robi się przerwań od przycisków. Zrób przerwanie timera np. 100 Hz, w nim sprawdzaj stany przycisków.
    2. __attribute__ ((interrupt)) jest zbędne.
    3. Znacznik przerwania kasuje się na początku, nie na końcu obsługi przerwania.
    4. Do zmiany stanu linii portów służą rejestry BSRR- jeden zapis zmienia stany dowolnie wybranych linii na zera i na jedynki, szybciej od bitband i sporo wygodniej.

  • #4 12 Mar 2017 23:25
    marek1972_2
    Poziom 3  

    Freddie Chopin napisał:
    marek1972_2 napisał:
    // Interrupt mask register, that EXTI lines are active: 0 and 1
    EXTI -> IMR = EXTI_IMR_MR0;   //A0
    EXTI -> IMR = EXTI_IMR_MR2;   //C2

    Druga linia kasuje to co zrobiła pierwsza.

    Przy okazji łatwiej by było jakbyś napisał DOKŁADNY opis problemu, bo tak naprawdę to nie wiadomo co Ci nie działa.
    Dodano po 1 [minuty]:
    marek1972_2 napisał:
    __attribute__ ((interrupt)) void EXTI0_IRQHandler(void)

    Atrybut jest całkowicie zbędny.
    Dodano po 1 [minuty]:
    marek1972_2 napisał:
       {    while(x <= 0) {   x = x - 1;    } } }

    Warunek mało sensowny, ponieważ x jest bez znaku.




    Poprawiłem na
    Kod: c
    Zaloguj się, aby zobaczyć kod


    ta pętla while jest tylko dla potrzeb debugera, rzebym mógł podglądać/zmieniać rejestry. Normalnie w kodzie mam zwykłe while(1); ale to powoduje zawieszenie się programu/debugera w w jednym miejscu - nic nie mogę wtedy zrobić.

    W swoim kodzie zmieniłem kolejność w EXITx_IRQHandler(..)
    i teraz EXTI -> PR = EXTI_PR_PR0; jest na początku.

    Tak zrobiłem że zapalam te LED-y różnymi metodami żeby być pewnym że jak któraś metoda jest zła to inna zadziała. Dlatego jedną LED próbuję zapalać BB(..) = 0 a inną ...= 1 Tak na wszelki wypadek.


    Tak, wiem, znalazłem to że przerwanie od przycisku robi się na timerze (Mam nadzieje że to będzie w Poradniku)
    Ale podobno tak też się da więc w celach edukacyjnych/poznawczych .. próbuję.

    Tak przy okazji . Gdybym miał projekt gdzie uC maiłby bardzo dużo do liczenia, i miałby do obsługi sporo przycisków to z punktu widzenia wykorzystania zasobów która metoda jest lepsza: przerwanie tak jak w tym przypadku czy za pomocą timera?

    dziękuje za błyskawiczną odpowiedź

  • #5 13 Mar 2017 08:13
    Freddie Chopin
    Specjalista - Mikrokontrolery

    marek1972_2 napisał:
    Tak przy okazji . Gdybym miał projekt gdzie uC maiłby bardzo dużo do liczenia, i miałby do obsługi sporo przycisków to z punktu widzenia wykorzystania zasobów która metoda jest lepsza: przerwanie tak jak w tym przypadku czy za pomocą timera?

    Oczywiście że timer.

  • #6 14 Mar 2017 20:12
    marek1972_2
    Poziom 3  

    Nadal szukam błędu w kodzie. Co dostałem z debugera:
    Linie ..

    EXTI -> FTSR |= EXTI_FTSR_TR0 | EXTI_FTSR_TR2;
    EXTI -> RTSR |= EXTI_RTSR_TR0 | EXTI_RTSR_TR2;

    ...odpowiadają za uruchomienie numerów pinów. Ja mam PA0 i PC2 i tak jak oczekuje po uruchomieniu dostaje wartości 0b101.
    Podobnie EXTI -> IMR dostaje to samo czyli 0b101

    Dalej jest NVIC_EnableIRQ(EXTI0_IRQn) i z tego dostaję coś czego nie rozumiem.
    Zmieniają mi się rejestry w NVIC -> NVIC -> ISER0 oraz ICER0 na 0b100 0000. Też oczekiwałem odpowiedni pin czyli 0b1.
    Po następnej linijce kodu NVIC_EnableIRQ(EXTI2_IRQn) ISER0 i ICER0 mają już wartości 0b1 0100 0000 . Oczekiwałem 0b101. Ktoś może mi to wyjaśnić?

    Później program wskakuje do pętli. Nic się nie dzieje - żadnych zmian. Aż do naciśnięcia przycisku PA0. Rejestr EXTI ->PR zmienia wartość na 0b1 - i chyba tak powinno być. Uruchamia się EXTI0_IRQHandler(void) - chyba . LED niestety nie świeci.

    Zwalniam przycisk PA0. Oczekiwałem że rejestr EXTI -> PR (był 0b1) przyjmie wartość 0b0 ale tak się nie stało.

    Przycisk PC2 kompletnie nic nie zmienia.

    Podsumowując:
    nie jestem pewien czy to "void EXTI0_IRQHandler(void)" się uruchamia. I czy ten warunek kiedykolwiek zostaje sprawdzony.

    Przy okazji .. jak odwrócić/zanegować ten warunek "if (EXTI -> PR & EXTI_PR_PR0)..." czyli mam "jeśli przycisk jest wciśnięty" jak zamienić na "jeśli przycisk nie jest wciśnięty"

    $$$$$$$$$$$$$$$$$$$$$$$$$$$$
    Następny test:
    Zaraz na początku za nawiasem void EXTI0_IRQHandler(void) wstawiłem zapalenie LED. Tak z marszu, bez warunku. Rozumuję że wskok do tej funkcji powinno LED-y wywołać. Niestety żaden, nie świeci. Czyli co .. void EXTI0_IRQHandler(void) nigdy się nie uruchamia. ?!

    Wszyscy widzieli Elvisa ale do tej pory nikt mu nie zrobił zdjęcia. Piszą o podobnych kodach że są trywialne, powinny chodzić od kopa, ale nie chodzą.
    Myślałem że poświęcę na ten kod max godzinę a siedzę już tydzień.

    Pozdrawiam

  • #7 14 Mar 2017 21:13
    Piotrus_999
    Poziom 40  

    Nie rozumiem: masz debugger a nie wiesz czy wchodzi w przerwanie. Ściągnij sobie poradnik kolegi szczywronka, zobacz przykłady, zastanów się jak debuggowac aby jednak wiedzieć czy wchodzisz w przeranie. No nie można być aż tak nieporadnym. Masz narzędzia i źródło wiedzy (poradnik) - czego chcesz więcej. O to exti tu było tyle pytań że już szkoda odpowiadać.

  • #8 14 Mar 2017 21:27
    Freddie Chopin
    Specjalista - Mikrokontrolery

    marek1972_2 napisał:
    SYSCFG -> EXTICR[0] = SYSCFG_EXTICR1_EXTI0_PA; // PA0 0x0000U
    SYSCFG -> EXTICR[0] = SYSCFG_EXTICR1_EXTI2_PC; // PC2 0x0200U

    Druga linia kasuje to co ustawiłeś w pierwszej, choć akurat w tym konkretnie przypadku nie ma to znaczenia.

    marek1972_2 napisał:
    __attribute__ ((interrupt)) void EXTI0_IRQHandler(void)

    Atrybut jest _NAPRAWDĘ_ zbędny.

  • #9 14 Mar 2017 21:40
    marek1972_2
    Poziom 3  

    Dziękuje Freddie Chopin i dziękuje Piotrus_999 za sugestie. Ja ten kod poprawiłem na swoim komputerze i wydawało mi się że poprawiłem tutaj na stronie.. hm. Teraz poprawiłem.
    Ja ten swój kod ciągle modyfikuje, próbuje różne opcje. Nie nadążałbym za zmianą tego kodu tutaj na stronie , idea jednak pozostaje.

    Tak, mam debuger i nie wiem czy wchodzi w przerwanie. Mogłem śledzić rejestry na debugerze po nazwie, nie wiem ja sprawdzić funkcję, czy też przerwanie. Doczytam.

  • #13 15 Mar 2017 20:17
    marek1972_2
    Poziom 3  

    Ciężko tu mówić o projekcie Freddie , to raczej plik do testów.

    Oto najnowsza wersja (która nadal nie działa):

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Ja to mam właśnie z poradnika szczywronka tylko ze ten swój kod pisałem pod F407. Różnice w kodzie są ale z tego co znalazłem w RM , nie w tych tutaj użytych rejestrach. Szczywronek użył swojej funkcji/biblioteki BB do sterowania np LED-ami , ja jej nie używam żeby już nie mieszać i żeby kod był dla Was bardziej czytelny.

    Zrobiłem jakiś błąd i nie wiem gdzie. Według mnie problem jest w tym
    NVIC_EnableIRQ(EXTI0_IRQn); NVIC_EnableIRQ(EXTI2_IRQn);

    albo / i tym:
    void EXTI0_IRQHandler(void) { ... void EXTI2_IRQHandler(void) {...

    Nie udało mi się tego uruchomić ale nie chce się poddawać - w poradniku Szczawronka widziałem w dalszej części przerwania (inne). Jeśli tego tutaj nie uruchomiłem to tych dalej pewnie też nie uruchomię. A po za tym chce to poznać.

    Jak pracuje w debuggerze to mogę włączyć/wyłączyć pokładowego LEDa wciskając odpowiedni rejestr. Podpowiedzcie mi proszę który rejestr powinienem uruchomić żeby zasymulować przerwanie.

    Wydawało mi się że za wartości w rejestrze EXTI -> PR tak jak ja mam 0b101 dla obydwu przycisków, będzie analogicznie odpowiadać wartość taka sam w którymś z rejestrów ISERx i ICERx ale tak nie jest. Ja dostaje co prawda 0b101 ale przesunięte <<6

  • #14 15 Mar 2017 20:59
    Freddie Chopin
    Specjalista - Mikrokontrolery

    marek1972_2 napisał:
    Ciężko tu mówić o projekcie Freddie , to raczej plik do testów.

    Wrzuć cały projekt, bo błąd może być zupełnie gdzieś indziej.

  • #15 15 Mar 2017 22:04
    marek1972_2
    Poziom 3  

    Płytka STM32F407G-DISC1
    Na pokładzie z tego co używam to 4 LED-y (PD12 - PD15), przycisk PA0 i mój zewnętrzny przycisk podłączony do PC2 i do masy.

  • #16 15 Mar 2017 22:14
    Piotrus_999
    Poziom 40  

    To moja rada - ściągnij sobie to co szczywronek wykorzystuje - i na początek po prostu skopiuj przykład (zmnieniajac piny). Obejrzyj sobie jak on to robi, a pożniej zacznij pisać wariacje do tego przykładu.

  • #17 19 Mar 2017 00:59
    marek1972_2
    Poziom 3  

    Pomyślałem że mam uszkodzoną płytkę. Nie możliwe było że tak prosty kod, powielany na tylu stronach nie chce działać.
    Więc zrobiłem sobie projekt, ten sam i trochę więcej, pod STM32CubeMX
    No i wszystko ruszyło, mam przerwanie. Dioda gaśnie i zapala.
    Więc postanowiłem przetłumaczy ten kod na ten rejestrowy. Wszystko szło OK aż do momentu tłumaczenia tego.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    Przypuszczam że to jest odpowiednik EXTI0_IRQHandler() . Podmieniałem, ćwiczyłem, kombinowałem i nie ruszyło. Tak jak wcześniej mówiłem, ta część kodu mi nie ruszyła, nie zadziałała tak teraz też nie ruszyła.
    To już wykracza poza moje możliwości - Handler nie działa i już.

    Znalazłem przykład w internecie przerwania na timerze , załadowałem i też nie ruszyło. Obawiam się że już żadne przerwanie mi nie ruszy. Szkoda bo bawienie się tymi rejestrami , i studiowanie tych różnych manual-i dawało mi dużo frajdy. Sporo jeśli nie większość różnych rzeczy jest robiona na przerwaniach więc nie ma sensu abym ćwiczył to dalej.
    ***
    W Poradniku jest błąd. Nie w tym konkretnym kodzie a raczej w wyniku niedomówienia, niedopowiedzenia autora o czymś o czym "przecież wszyscy wiedzą".

    Niestety nie zostawię prawidłowego rozwiązania problemu.

    Dziękuje wszystkim za pomoc.
    Temat zamknięty.

  • #18 19 Mar 2017 01:02
    Piotrus_999
    Poziom 40  

    marek1972_2 napisał:
    Znalazłem przykład w internecie przerwania na timerze , załadowałem i też nie ruszyło. Obawiam się że już żadne przerwanie mi nie ruszy. Szkoda bo bawienie się tymi rejestrami
    Nie rozumiem podejścia ale czy HAL i nie HAL to i tak dojdzesz do innej ściany, a będzie ona dużo trudniejsza niż to

  • #19 19 Mar 2017 09:17
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Po raz "enty" mówię więc, żebyś wrzucił CAŁY projekt, ale skoro wolisz marudzić jak to bardzo coś Ci nie działa i jak to cały świat jest temu winny, to proszę bardzo.

  • #20 25 Mar 2017 12:15
    marek1972_2
    Poziom 3  

    Witam wszystkich,
    Po dwóch a może trzech tygodniach poszukiwań znalazłem błąd. Nie odkryłem samodzielnie tylko znalazłem tu na forum :

    STM32 - I2C na przerwaniach

    Piszę w SystemWorkbench for STM32. Przy tworzeniu kodu w STM32CubeMX (czyli na bibliotekach HAL) program dodawał za mnie wszystko co potrzebne żeby działało podczas ekportu projektu do System Workbench for STM32.

    Gdy pisałem samodzielnie na rejestrach to tworzyłem samodzielnie nowy projekt w SW, dodałem odpowiednie pliki *.h i to wszystko.

    Problem w tym że podczas tworzenia takiego projektu system nie robił mi dobrego pliku startup. Dokładnie plik ten znajduje się w ...nazwa_projektu\SW4STM32\startup_stm32f407xx.s po eksporcie z Cube i ma 25kB. Mój z SW był ...nazwa_projektu\startup\startup_stm32.s. i miał jakieś 5kB. Dwa inne pliki - zawartość podobna ale nie pełna. W tym tworzonym przez SW nie było definicji przerwań typu :
    .word EXTI0_IRQHandler /* EXTI Line0 */

    oraz
    .weak PVD_IRQHandler
    .thumb_set PVD_IRQHandler,Default_Handler

    Dodałem i program ożył.
    Dziękuje wszystkim za pomoc. Zamieszczam jeszcze raz ten poprawny kod który u mnie działa, z takimi moimi uwagami z boku - może się komuś przyda.

    Kod: c
    Zaloguj się, aby zobaczyć kod

  • #21 25 Mar 2017 12:25
    Freddie Chopin
    Specjalista - Mikrokontrolery

    marek1972_2 napisał:
    Po dwóch a może trzech tygodniach poszukiwań znalazłem błąd.

    Gdybyś wrzucił CAŁY projekt, tak jak o to prosiłem dokładnie 3 razy, to miałbyś informację po 10-ciu minutach w czym jest problem. Zresztą jakbyś opisał dokładniej problem (bo w debuggerze Twój program na 10000000% wpadał w default handler), to pewnie też. No ale...

  • #22 09 Cze 2017 17:07
    marek1972_2
    Poziom 3  

    Problem rozwiązany więc zamykam temat.

 Szukaj w ofercie
Zamknij 
Wyszukaj w ofercie 200 tys. produktów TME