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.

Dziwne wyświetlanie z USARTu ATmega64

TMEA 18 Gru 2012 19:22 1647 27
  • #1 18 Gru 2012 19:22
    TMEA
    Poziom 16  

    Witam Koleżanki i Kolegów

    Mam problem taki jak na filmiku:

    Link

    Gdy wchodzę do menu i wychodzę to po pewnym czasie jak widać pod koniec filmiku układ zaczyna wyświetlać głupoty. Procedura wysyłania do wyświetlacza to standardowa procedura z noty katalogowej Atmega64 i działa zawsze bezbłędnie ale odbieranie to koszmar. Program zajmuje ponad 49kB więc nie będę go wrzucał. Procedura odbioru znaków wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Nie wiem co może być. Męczę się z tym już 2 tydzień i mam dość. Może ktoś z Was wie co może być? Wyświetlacz to układ TFT HMI display firmy Bejing Stone. Wszystko wrzuca się jako obrazy BMP i rysuje przyciski które zwracają wartość po naciśnięciu jako kilka bajtów i zawsze 3 bajt jest wartością wciśniętego przycisku. Może nie kasuję czegoś w przerwaniu czy coś? przy każdej prędkości USARTu tak się dzieje.

    pozdrawiam :)

    0 27
  • #2 18 Gru 2012 19:34
    michalko12
    Specjalista - Mikrokontrolery

    RAMu to ci starcza na stos?

    0
  • #3 18 Gru 2012 19:47
    TMEA
    Poziom 16  

    na wyświetlanie wszystkich informacji starcza ale na odbieranie czyli naciskanie przycisków to...właśnie tak myślę , że coś się przepełnia ale jak sprawdzić czy ramu starcza? da się go jakoś wykasować?:) kilka razy jak widzisz Szanowny Kolego działa a potem zawias jest i zmienia mi nawet ustawienia temperatur.

    Dodano po 10 [minuty]:

    Build started 18.12.2012 at 19:13:33
    avr-gcc -mmcu=atmega64 -Wall -gdwarf-2 -std=gnu99 -DF_CPU=3686400UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT TCUv1.o -MF dep/TCUv1.o.d -c ../TCUv1.c
    avr-gcc -mmcu=atmega64 -Wl,-Map=TCUv1.map TCUv1.o -o TCUv1.elf
    avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature TCUv1.elf TCUv1.hex
    avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex TCUv1.elf TCUv1.eep || exit 0
    avr-objdump -h -S TCUv1.elf > TCUv1.lss

    AVR Memory Usage
    ----------------
    Device: atmega64

    Program: 49502 bytes (75.5% Full)
    (.text + .data + .bootloader)

    Data: 3245 bytes (79.2% Full)
    (.data + .bss + .noinit)


    Build succeeded with 0 Warnings...

    0
  • #4 18 Gru 2012 19:48
    michalko12
    Specjalista - Mikrokontrolery

    Takie "zjawiska" to zazwyczaj niezainicjalizowany wskaźnik lub niewystarczająca ilość miejsca na stos. Sądząc po stylu pisania to jedna i druga opcja jest wielce prawdopodobna z przewagą na brak stosu, gdyż nie wiadomo jak bardzo operujesz na wskaźnikach.
    Stos najlepiej jest sprawdzić podglądając RAM za pomocą debuggera, a jeśli nie masz takowego to w każdym przerwaniu zapamiętać gdzieś minimalną wartość wskaźnika stosu i go gdzieś co jakiś czas wyświetlić.

    0
  • #5 18 Gru 2012 19:51
    TMEA
    Poziom 16  

    hmm nigdy nie bawiłem się stosem bo niby po co jak sie robiło projekty kilka kB. a jak to zrobić aby ten stos zapamiętywać? bo szczerze to nie za bardzo wiem właśnie jak z tego stosu korzystać. A może jakaś funkcja że gdy naciskam strzałkę czyli wychodzę do wyboru strefy 1-5 to kasuje sie stos? :)

    0
  • #6 18 Gru 2012 19:53
    BlueDraco
    Specjalista - Mikrokontrolery

    1. Po co sprawdzasz w przerwaniu, które jest zgłaszane po odebraniu danej, czy odebrano daną?

    2. Dlaczego wysysasz dane z UARTa pod koniec obsługi przerwania, gubiąc je w ten sposób.

    3. Być może jakaś inna część kodu (obsługa innego przerwania) wykonuje się tak długo, że gubisz dane z UARTa.

    4. Jeśli masz jakąś procedurę, a w niej zadeklarowaną sporą tablicę (albo ogólnie dużo danych), to ta tablica może powodować przepełnienie stosu. Wtedy dostęp do innych danych zamazuje dane na stosie i program na ogół idzie w krzaki.

    0
  • #7 18 Gru 2012 19:57
    TMEA
    Poziom 16  

    Nie ma innego przerwania. Co dokładnie źle wysyłam i gubię? :)

    0
  • #8 18 Gru 2012 19:58
    BlueDraco
    Specjalista - Mikrokontrolery

    O to:
    unsigned char dummy;
    while ( UCSR0A & (1<<RXC0) ) dummy = UDR0;

    0
  • #9 18 Gru 2012 20:01
    TMEA
    Poziom 16  

    aaa to :) dodałem to dziś ale nie zmieniło to działania w ogole. Więc to wywalę ale nie pomoże to

    0
  • #10 18 Gru 2012 20:03
    BlueDraco
    Specjalista - Mikrokontrolery

    No to jeszcze sprawdź te tablice w procedurach, o których pisałem wyżej.

    Czy Twój kod modyfikuje gdzieś zawartość tablicy "sekwencja"?

    0
  • #11 18 Gru 2012 20:08
    TMEA
    Poziom 16  

    to pierwszy kod duży ktory zajmuje troche :)

    Kod: c
    Zaloguj się, aby zobaczyć kod



    a to kolejne co na filmiku widać
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodano po 1 [minuty]:

    ogolnie tablice mają po 48 elementów integer bo temperatura jest ustawiana co pół godziny. dodatkowo jest 8 programów i 5 stref dla każdej strefy można przypisać program

    0
  • #12 18 Gru 2012 21:29
    michalko12
    Specjalista - Mikrokontrolery

    Wycofuję się ze stwierdzenia, że to wina niezainicjalizowanych wskaźników!

    0
  • #13 18 Gru 2012 21:38
    BlueDraco
    Specjalista - Mikrokontrolery

    No to zacznij od zastąpienia każdych 8 szt if czymś takim:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    A jak już cały Twój program zmaleje 8 razy, to go zamieść i poszukamy błędów, których zapewne jest sporo.

    0
  • #14 18 Gru 2012 22:13
    TMEA
    Poziom 16  

    no szczerze to ta funkcja zabiera bardzo dużo pamięci. Odpowiada ona za przypisanie jednego z 8 programow do każdej z 8 stref i każdego z dnia tygodnia i to jeszcze co pół godziny więc taka straszna funkcja wyszła. ale ona nie zawiesza ukladu bo jest odczytywana co 5 sekund na ekranie podstawowym czyli gdy wyświetla temperature. w takim stanie nie zawiesza się nawet jak chodzi kilka godzin. Ale postaram się to zmienić tak jak napisałeś i mam nadzieję że zadziała wszystko. Ale to raczej nie rozwiąże niestety problemu :|

    0
  • #15 18 Gru 2012 22:17
    BlueDraco
    Specjalista - Mikrokontrolery

    Na moje oko ta funkcja może być 64 razy krótsza niż jest obecnie.

    0
  • #16 19 Gru 2012 16:42
    tehaceole

    Poziom 28  

    IMHO nie doszukiwałbym się tutaj problemu ze stosem. Stawiałbym raczej na wyjście któregoś z indeksów poza rozmiar tablicy. W razie czego zużycie stosu możesz sprawdzić np. tym kodem. Na pewno nie zaszkodzi taki eksperyment.
    Czy program całkowicie się zawiesza czy tylko na wyświetlacz trafiają bzdury?

    0
  • #17 20 Gru 2012 00:21
    TMEA
    Poziom 16  

    Zrobiłem dziś eksperyment. Dodałem tablicę z 478 danymi int co zajeło 3999B pamięci czyli około 97%. Tablica ta nic nie robiła poza zajmowaniem pamięci i problemy i krzaki zaczeły się od razu po włączeniu urządzenia. Normalnie mam zajęte około 75% pamięci dla danych. Ale czy może wskaźnik gdzieś pisać po pamięci po kilku razach dopiero? nie powinien od razu źle wyświetlać?

    0
  • #18 20 Gru 2012 04:10
    szulat
    Poziom 23  

    TMEA napisał:
    Ale czy może wskaźnik gdzieś pisać po pamięci po kilku razach dopiero? nie powinien od razu źle wyświetlać?

    jeżeli przerwanie pojawia się w momencie gdy na stosie jest dużo bo akurat działa funkcja z wieloma zmiennymi lokalnymi albo wiele funkcji wywołanych z siebie nawzajem to może już zabraknąć miejsca na stosie, a innym razem to samo przerwanie wywoła się gdy stos jest prawie pusty i nic złego sie nie dzieje

    0
  • #19 20 Gru 2012 08:58
    TMEA
    Poziom 16  

    No więc co w takim razie zrobić aby tak się nie działo? jest jakiś sposób na to? moją główną funkcją nie jest main. Main jest tylko ustawianiem wszystkiego. Główna funkcja to READY. To jak zrobić aby ten stos się opróżniał lub aby miał jakieś zabezpieczenie przed przepełnieniem? :)

    Dodano po 14 [minuty]:

    tehaceole napisał:
    IMHO nie doszukiwałbym się tutaj problemu ze stosem. Stawiałbym raczej na wyjście któregoś z indeksów poza rozmiar tablicy. W razie czego zużycie stosu możesz sprawdzić np. tym kodem. Na pewno nie zaszkodzi taki eksperyment.
    Czy program całkowicie się zawiesza czy tylko na wyświetlacz trafiają bzdury?

    na wyswietlacz trafiają bzdury, zmienne się zmieniają, przekaźniki wariują, temperatury źle pokazuje czyli ogólnie coś się w głowie procesorowi przestawia :D po restarcie procesora dane z eepromu też są pozmieniane często bo wyjście z funkcji strzałką " <--- " zapisuje w eepromie aktualne ustawienia.

    0
  • #20 20 Gru 2012 09:04
    BlueDraco
    Specjalista - Mikrokontrolery

    Po prostu zmniejsz kod i dane - w obecnej postaci wszystko jest nadmiarowe. Napisz to porządnie, a podejrzewam, że będziesz miał min. 5-krotnie mniejszą zajętość pamięci kodu i danych. Prawdopodobnie używasz wielu danych, które są stałymi, a zapisujesz je jako zmienne - w ten sposób wyżerasz pamięć RAM bez jakiejkolwiek potrzeby. Dwa ważne słoa kluczowe: const PROGMEM i jeszcze pseudofunkcja odczytu danych z pamięci ROM pgm_read_byte(). Jedna Twoja procedura, którą z grubsza przejrzałem, daje się skrócić ponad 50-krotnie - nie uważasz, że to przesada?

    0
  • #21 20 Gru 2012 09:23
    TMEA
    Poziom 16  

    BlueDraco napisał:
    No to zacznij od zastąpienia każdych 8 szt if czymś takim:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    A jak już cały Twój program zmaleje 8 razy, to go zamieść i poszukamy błędów, których zapewne jest sporo.


    nie działa to. Wywala błąd -'tabtempP' undeclared (first use in this function)
    Po 2 avr studio nie rozumie czegoś takiego tabtempP[x] bo już próbowałem dlatego napisałem to wszystko tyle razy :/

    0
  • #22 20 Gru 2012 09:28
    BlueDraco
    Specjalista - Mikrokontrolery

    Ocyzwiście że nie działa - zamast kilku tablic tabtempP zadeklaruj jedną dwuwymiarową - wtedy zadziała. AVR studio, a dokładniej kompilator, rozumie wszytskie zapisy języka C, o ile są poprawne. Masz źle zaprojektowane dane i algorytm. Uporządkuj to, a całość wejdzie pewnie i w ATmega8.

    0
  • #23 20 Gru 2012 09:39
    TMEA
    Poziom 16  

    ale dla każdego programu muszę mieć tablice 48 wymiarową więc jak na jednej zrobić 384 bo nie rozumiem tego trochę? co to zmieni jak i tak muszę mieć tyle zmiennych

    0
  • #24 20 Gru 2012 10:09
    BlueDraco
    Specjalista - Mikrokontrolery

    Nie, masz mieć tablicę dwuwymiarową czyli tabtempP[8][48], zamiast ośmiu tablic.
    A zmieni to tyle, że jeden fragment kodu będzie to kopiował, a nie 64 fragmenty robiące to samo, ale z innymi danymi.

    0
  • #25 20 Gru 2012 19:31
    TMEA
    Poziom 16  

    Odchudziłem 8 funkcji setprogram i zrobiłem z niej jedną tak jak poleciłeś. Program zmniejszył się o ponad 9kB a pamięci przybyło ponad 550B. Teraz potrzeba 2x tyle czasu aby układ się zawiesił :D

    Dodano po 1 [godziny] 31 [minuty]:

    Program odchudzony: wszystkie główne funkcje które się powtarzały zostały zrobione na 1 funkcję elektem jest zwolnione 21,5kB i 789B ale układ nadal się zawiesza przy zabawie w ustawianie programów.

    Kod: c
    Zaloguj się, aby zobaczyć kod

    0
  • #26 20 Gru 2012 19:47
    BlueDraco
    Specjalista - Mikrokontrolery

    Hmmm.. Miałeś na myśli coś takiego?

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dlacyego nie stablicujesz jako stałych wartości używanych w dalszej części kodu i nie zaindeksujesz ich zmiennymi "decyzyjnymi"? To dużo wydajniejsze niż rozchodzenie się na 8 "if" robiących to samo, ale z różnymi wartościami.

    0
  • #27 20 Gru 2012 19:52
    TMEA
    Poziom 16  

    yyy nie rozumiem tego po co tak napisałeś? :D

    0
  • #28 21 Gru 2012 16:55
    TMEA
    Poziom 16  

    już wiem co jest. Gdy z pulpitu wchodzę do funkcji, i dalej do funkcji to gdy chcę wrócić do poprzedniej to daje znów skok i tak dalej i tak dalej i przez co jest kilkadziesiąt zapętleń i się stos przepełnia. Próbuję użyć funkcję return ale wraca mi do miejsca gdzie program się skończył przez co nie zmienia ekranu, nie wyświetla wszystkiego (tego co jest poza pętlą). Jak zrobić aby po wpisaniu return lub czegoś innego wracał na początek funkcji a nie tam gdzie skończył? :)

    0