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

[Atmega32][C]Przerwanie i dziwne zachowanie zmiennej

osa123456 18 Sie 2011 23:30 2156 18
  • #1 9839155
    osa123456
    Poziom 11  
    Witam, ostatnio podłączyłem do Atmegi wyświetlacz od nokii 3310 i postanowiłem pouczyć się trochę timerów i przerwań. Chciałem napisać prosty programik liczący impulsy i wyświetlać je na LCD. W przerwaniu od INT0 zliczam impulsy, a w drugim przerwaniu co sekundę przepisuje ilość impulsów do zmiennej i kasuję liczbę impulsów. Problem pojawia się gdy chcę wyświetlić zmienną z liczbą impulsów na sekundę na wyświetlaczu, na LCD bowiem wyświetla się wynik 256*n, dodam, że jeśli wyświetlę liczę impulsów bez zapisywania jej do zmiennej w przerwaniu od timera to wszystko jest ok.

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

    Konfiguracja timerów, przerwań i linii I/O:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Przerwania:

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


    Gdy próbuję wyświetlić zmienną "impulsy2" pojawia się ten problem, a gdy wyświetlam zmienną "impulsy" wszystko jest ok, ładnie zwiększa się o 1 co każdy impuls.
    Macie jakieś pomysły dlaczego tak jest i jakieś sugestie jak to naprawić:?:
  • #2 9839512
    omicronNs
    Poziom 21  
    Wrzuć program do debuggera i szukaj momentu w którym zawartość zmiennej się sypie.
  • #4 9839695
    mirekk36
    Poziom 42  
    snnaap napisał:
    Pokaż cały program a nie tylko wyrywki. Przydałoby się zobaczyć co się dzieje podczas wysyłania zmiennej impulsy2 na wyświetlacz.


    Panowie, gdyby do tak prostych rzeczy trzeba było używać debugera to w zasadzie człowiek by się posuwał z pisaniem i tworzeniem projektów wolniej niż zółw a często by się w ogóle zatrzymał i porzucił wszystko - np na prockach na których nie ma jak skorzystać z debugera.

    Analiza błędów na takim poziomie (szczególnie takich - typu miganie diodą - jak ten tutaj) bez debugera to jest dopiero nauka programowania. Trzeba się nauczyć samemu analizować i rozwiązywać takie problemy a po debugera jak już to sięgać przy czymś skomplikowanym - np. przy błędach obsługi stosu TCP, czy jakichś innych projektach gdzie skompilowany kod przekracza powiedzmy 128kB - chociaż i to nie zawsze konieczne przy tak małych prockach jak AVR'ki.

    Tak jak pisał snnaap - panie autor - pokaż jeszcze inne fragmenty kodu - bo tobie się wydaje, że tu leży błąd - a niestety jest on gdzieś indziej.
  • #6 9840115
    tmf
    VIP Zasłużony dla elektroda
    Pokaż przynajmniej jak wygląda to wyświetlanie. Pamiętasz, że do twoich zmiennych w programie musisz zapewnić dostęp atomowy, poprzez zastosowanie sekcji krytycznych? Akurat w przerwaniach przypadkiem robi się to automatycznie, ale w pętli głównej programu już nie.
  • #8 9840410
    osa123456
    Poziom 11  
    Kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Warningi:

    
    linijka 9: built-in function 'index' declared as non-function
    linijka 14: function declaration isn't a prototype
    linijka 49 i 53: array subscript is above array bounds
    
  • Pomocny post
    #9 9840455
    dondu
    Moderator na urlopie...
    Zacznij używać TAB-ulatora w kodzie bo analiza Twojego kodu to katorga.
    Popraw i załącz ponownie.

    Mamy się domyślać w których liniach występują warningi?

    Dla Ciebie Warning = Błąd: : http://mikrokontrolery.blogspot.com/2011/04/bledy-kompilacji-programu.html
  • #10 9840511
    osa123456
    Poziom 11  
    Dzięki za tą uwagę o warningach, myślałem, że one są mało ważne, ale teraz widzę, że nie. Przekraczałem wymiary tablicy, po zmianie tego wszystko działa jak trzeba.
    Jeszcze raz dzięki wszystkim, teraz będę zwracał większą uwagę na warningi. ;)
  • #11 9840573
    mirekk36
    Poziom 42  
    osa123456 napisał:
    Dzięki za tą uwagę o warningach, myślałem, że one są mało ważne, ale teraz widzę, że nie. Przekraczałem wymiary tablicy, po zmianie tego wszystko działa jak trzeba.
    Jeszcze raz dzięki wszystkim, teraz będę zwracał większą uwagę na warningi. ;)


    Ja bym proponował zamiast zwracać większą uwagę na warningi to traktować je jako poważne błędy, które trzeba usunąć. Przynajmniej na tym etapie nauki języka C. A na pewno można je pousuwać zawsze ;) .... to wyjdzie ci na zdrowie i mniej czasu stracisz na przyszłość na szukaniu takich błędów.
  • #12 9840701
    tmf
    VIP Zasłużony dla elektroda
    osa123456 napisał:
    Dzięki za tą uwagę o warningach, myślałem, że one są mało ważne, ale teraz widzę, że nie. Przekraczałem wymiary tablicy, po zmianie tego wszystko działa jak trzeba.
    Jeszcze raz dzięki wszystkim, teraz będę zwracał większą uwagę na warningi. ;)


    Warningi warningami, ale masz tam także inne błędy. Obstawiam na kolejny post wkrótce "dlaczego na LCD czasami wyświetla mi błędne wyniki" :)
  • #13 10280810
    natrek
    Poziom 11  
    Podepnę się do tematu.

    Wykonałem projekt trackloggera rejestrującego dane gps i zapisującego je na karcie SD. Całość wykonałem na atmedze644 i śmiga bardzo dobrze.
    Pragnąłem dalej rozwinąć ten projekt i podłączyć wszystko do atmegi32, dodając jeszcze wyświetlacz.

    Podczas testów zmienionego pod atmegę32 kodu zaczęły się dziać dziwne rzeczy.
    Z gpsem komunikuję się poprzez przerwanie usart. Odbieram w przerwaniach ramkę nmea znak po znaku, a potem zapisuję współrzędne na karcie.

    Oto więc zamiast odbierać z gpsu ramki nmea zczytuję z udr zawartość wskaźnika w którym zawarłem fragment xmla który zapisuję w pliku.

    Dla wyjaśnienia kod obsługi przerwania usart:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Objaśnienie zmiennych:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dowiedziałem się o tym zapisując w pliku tekstowym na karcie odczytywane znaki z rejestru udr. Tekst który się pojawia jest zawartością wskaźnika 'naglowek'.

    Zmieniłem inicjalizację usartu zgodnie z notą katalogową atmegi:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Prędkość 9600,8bit,n,1, taktowanie uc 8MHz na wewnętrznym oscylatorze.

    Pętli głównej nie pokazuję, ponieważ przy pomocy przycisku włączam i wyłączam tam jedynie obsługę przerwań, aby regulować zapis na karcie.

    Czy ma ktoś pomysł co może być przyczyną takiej sytuacji? Siedzę nad tym od kilku dni i nie mogę nic wymyśleć.
    Najbardziej zastanawia mnie fakt, że praktycznie ten sam kod działa bezbłędnie na atmedze644...
    [/code]
  • #14 10280871
    janbernat
    Poziom 38  
    ATMega644 ma dwa razy większą pamięć niż ATMega32.
    A stos narasta od końca pamięci w dół.
    I pewnie w końcu wchodzi w dane.
    A sprawdzić to trudno.
  • #15 10281048
    natrek
    Poziom 11  
    Zmniejszyłem zarówno naglowek jak i stopke do kilku znaków i niestety nic nie pomogło. Przerwania pojawiają się, ale w rejestrze UDR jest teraz pusto...

    Ponowna zmiana na starą konfigurację powoduje ten sam efekt co wcześniej.

    Charakterystyki kompilacji:
    przed zmianą:
    - Program 13552 bytes (41,1%)
    - Data 1281 bytes (62,5%)

    po zmianie:
    - Program 39,9%
    - Data 39,7%
  • #16 10281147
    janbernat
    Poziom 38  
    Ale to nie oto chodzi.
    Program się mieści, po kompilacji podaje Ci tylko ile w RAM (data) zajmują zmienne zdeklarowane bodajże jako zmienne statyczne (zaraz ktoś mnie opieprzy- i słusznie- że podaję to niedokładnie).
    A w każdym wywołaniu funkcji zmienne lokalne są umieszczane na stosie.
    Każde przerwanie umieszcza na stosie w prologu rejestry itp.
    Jak funkcja jest rekurencyjna- to już nieszczęście.
    Data- czyli RAM masz zajęty w 62%.
    Czyli zostaje na stos jakieś 700 bajtów.
    A zobacz po kompilacji na AT644 ile zostaje.
    To jak sprawdzić tmf podaje w swojej książce- ale chyba żaden ze sposobów nie jest lekarstwem na 100%.
  • #17 10281264
    natrek
    Poziom 11  
    Kompilacja Atmegi644:
    Program 22,7%
    Data 31,5%

    Hmm ok rozumiem co masz na myśli. Chodzi Ci o tą książkę?
    Link

    Szukałem o jaką książkę może chodzić i tylko ta mi pasuje :)

    Czyli mam rozumieć, że pozostaje mi odchudzenie programu i sprawdzenie czy działa?
    Jeżeli po odchudzeniu tych zmiennych odbierałem znaki puste w udr, to nie znaczy że problem leży gdzie indziej?
  • #18 10281318
    janbernat
    Poziom 38  
    Tak, o tę książkę.
    Ale rozwiązania w niej podane nie dają raczej 100% gwarancj że w pełni panujesz nad stosem.
    Nie chodzi o odchudzenie programu ale raczej o sprawdzenie ile wywoływane funkcje, przerwania, wielkość buforów zajmuje stosu.
    Bo komunikaty po kompilacji nic o tym nie mówią.
    Ja tylko podejrzewam- jeśli na AT644 działa a na AT32 nie- albo dziwnie działa- to jest to ten problem.
  • #19 10281334
    natrek
    Poziom 11  
    Atmega644: 4096 *(100-31,5)/100 = 2806 bytes wolnych

    Atmega32a:
    2048 *(100-62,5)/100 = 768 bytes wolnych przed zmianą
    2048 *(100-39,7)/100 = 1234 bytes wolnych po zmianie
REKLAMA