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.

C - Używanie zmiennych tylko wtedy kiedy potrzebne. Atmega8

w1941s 23 Mar 2013 10:45 1884 12
  • #1 23 Mar 2013 10:45
    w1941s
    Poziom 14  

    Witam, mam problem z programem do matrycy led a mianowicie ze znakami. Chciałbym aby kompilator np. w tym przypadku tworzył zmienne tylko wtedy jeśli ja ich użyje w programie:
    a) 1 sposób zapisu znaków ( każdy znak w innej tablicy, niestety jeśli dodam to do programu to kompilator AVR Studio wywala błędy że niektóre zmienne są nie używane i program się nie kompiluje):

    Kod: c
    Zaloguj się, aby zobaczyć kod


    b) Natomiast tu mamy znowu inny zapis znaków, wszystko w jednej tablicy. Wydaje mi się mniej optymalny bo od razu z góry trzeba stworzyć całą tablice i użyć jej w programie.:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    PYTANIA:
    1. Czy da się trzymać zmienne znakowe z podpunktu a) w oddzielnym pliku (coś probowałem z #include ale mi nie wychodziło :/) i żeby nie kompilowały się zmienne których nie używam tj. chce np. napisać słowo DOM:
    /program głowny
    wypisz(f_d); /* funkcja rysująca tablice */
    wypisz(f_O);
    wypisz(f_M);
    /koniec programu

    Po co mają mi się dodawać do programu zmienne których nie używam (np. f_s,f_z,f_e,f_p i tak dalej) i zajmować miejsce w RAM Atmegi8 skoro w programie użyłem tylko f_d f_o f_m ?

    2. Który zapis znaków jest bardziej optymalny (wydaje mi się że z podpunktu b) lecz w tym przypadku musimy od razu ładować całą tablice w pamięci, ale znowu nie musimy deklarować tylu tablic. Mylę się??)?

    3. Jak można ograniczyć zużycie ramu. Optymalne przechowywanie znaków, sposoby?

    4. Czy dobrym rozwiązaniem jest zapisanie czcionki do pamięci EEPROM atmegi i pobieranie z niej danego znaku podczas wykonywania programu, tj. pobieram znak z eeprom --> zapisuje do tablicy znak[8] --> wyświetlam znak, znowu pobieram znak z eeprom zapisuje do tablicy znak[8] --> wyświetlam. Czy dzięki takiemu rozwiązaniu jeśli dobrze mowie w RAM będzie tylko jedna tablica znak[8]?

    0 12
  • #2 23 Mar 2013 13:19
    Dżyszla
    Poziom 42  

    Nie, jeśli definiujesz coś, to to coś musi być w pamięci. Nie ma możliwości wczytania czegoś do pamięci znikąd. Dlatego jakiekolwiek próby zmiany sposobu czy miejsca umiejscowienia stałej/zmiennej niczego nie zmienią. Jedyną opcją mogłoby być wczytywanie np z nośnika zewnętrznego, co akurat tu chyba nie wchodzi w grę.
    Co do umieszczenia w jednej tablicy czy kilku zmiennych/stałych - różnica będzie polegać tylko na rozmiarze przydzielonego bloku (albo jeden duży, albo kilka mniejszych). Sumarycznie bez zmian.

    --------
    Edit: Przyjąłem przypadek możliwości użycia wszystkiego. Jeśli faktycznie chcesz używać w programie tylko kilku, to zastosowanie stałych powinno rozwiązać problem - brak użycia powinien powodować, że nie zostaną one wkompilowane. Aczkolwiek nie znam dobrze kompilatora, więc nie gwarantuję, że tak jest.
    ----------

    Może pomyśl o innej metodzie przechowywania znaków, np każdy znak budowany z innego zestawu. Zapoznaj się z siatkami karnaugha, które można wykorzystać także w programowaniu.

    Odnośnie 4 się nie wypowiem, bo nie mam doświadczenia.

    0
  • #3 23 Mar 2013 13:22
    McMonster
    Poziom 32  

    1. Kompilator sam zadba o to, żeby w pliku wynikowym nie znalazły się nieużywane zmienne, nie trzeba nic kombinować poza upewnieniem się, że jest włączona optymalizacja.

    2. Optymalny to tutaj raczej złe słowo, nie powinno być różnic. Za to druga opcja powinna być wygodniejsza do używania w kodzie.

    3. "Najprostszy" sposób to kompresja danych. Przy czym nie ma się zwykle co w to bawić na mikrokontrolerach, jeśli potrzeba więcej pamięci, to zmienia się mikrokontroler, a jeśli mimo to jej dalej brakuje, to trzeba się zastanowić, co w ogóle chcemy osiągnąć i co jest rzeczywiście potrzebne. To oczywiście przy założeniu, że sam program jest napisany co najmniej poprawnie. Niestety ciężko jest o uniwersalne rady. Na przykład w tym temacie można by się spróbować zastanowić, czy dałoby się rysować znaki wektorowo. Zapis wektorowy w porównaniu do rastrowego zajmuje bardzo mało przestrzeni, ale wymaga dość intensywnych dla takiego małego 8-bitowca obliczeń i może być problem z osiągnięciem wszystkich kształtów.

    4. Tok myślenia jak najbardziej prawidłowy. Przy czym możesz też użyć pamięci flash i z niej pobierać po znaku. Tylko trzeba będzie sprawdzić, czy prędkość operacji odczytu jest wystarczająca do wyrysowania wszystkiego w odpowiednim czasie.

    0
  • #4 23 Mar 2013 15:19
    w1941s
    Poziom 14  

    McMonster napisał:
    1. Kompilator sam zadba o to, żeby w pliku wynikowym nie znalazły się nieużywane zmienne, nie trzeba nic kombinować poza upewnieniem się, że jest włączona optymalizacja.



    Właśnie i tu jest problem bo kompilator wywala mi błędy że są nieużywane zmienne ale nie usuwa zmiennych, tylko zwyczajnie wypisuje błędy że mam nie używane zmienne i program się nie kompiluje. :/

    Co do pamięci eeprom, faktycznie jest to chyba najlepszy sposób.

    Ja te znaki wyświetlam na matrycy LED 8x8.

    0
  • #5 23 Mar 2013 15:23
    McMonster
    Poziom 32  

    Wyczyść projekt, skompiluj jeszcze raz i wklej tutaj pełne wyjście z konsoli.

    0
  • #7 23 Mar 2013 17:06
    w1941s
    Poziom 14  

    Sprawdzę z tymi stałymi i dam znać.

    0
  • #8 23 Mar 2013 22:30
    dondu
    Moderator Mikrokontrolery Projektowanie

    Co to znaczy, że ich nie używasz?
    Jeśli ich nie używasz, to po co je pakujesz do mikrokontrolera?

    A jeżeli jednak używasz (bo program w końcu może je potrzebować) i są to definicje znaków, to ich właściwym miejscem jest pamięć programu, czyli FLASH: http://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html

    w1941s napisał:
    ... niestety jeśli dodam to do programu to kompilator AVR Studio wywala błędy że niektóre zmienne są nie używane i program się nie kompiluje):

    Co najwyżej generuje warning, a nie error, więc musi się kompilować.

    Zamiast opisywać pokaż program i ewentualnie komunikaty kompilacji.

    0
  • #9 23 Mar 2013 23:26
    krru
    Poziom 32  

    Musiałbyś zapisać bitmapę każdej literki w oddzielnym pliku (.c), każdy niezależnie skompilować, połączyć to w bibliotekę (.a) i ją linkować do projektu. W takiej konfiguracji linker wybiera z biblioteki tylko używane moduły.

    0
  • #10 24 Mar 2013 09:38
    w1941s
    Poziom 14  

    Ale gafa. Dzisiaj postanowiłem jeszcze raz sprawdzić ten program, wszystko się skompilowało AVR studio wywala ostrzeżenie że są nie używane zmienne (po czym je usuwa) i wszystko działa. Powodem braku kompilacji był znak ; którego brakowało, gdyż w tylu ostrzeżeniach po prostu mi umkną error :(.

    Ale i tak wasze odpowiedzi rozjaśniły mi parę rzeczy. Dziękuje bardzo i przepraszam za kłopot :/. Myślę że znaki będę trzymał w eepromie i pobierał odpowiedni w czasie wykonywania programu.

    Dodano po 1 [minuty]:

    krru napisał:
    Musiałbyś zapisać bitmapę każdej literki w oddzielnym pliku (.c), każdy niezależnie skompilować, połączyć to w bibliotekę (.a) i ją linkować do projektu. W takiej konfiguracji linker wybiera z biblioteki tylko używane moduły.


    Dziś obczaję ten sposób. Jeszcze raz dziękuję.

    0
  • #11 27 Mar 2013 11:53
    Ostry23
    Poziom 18  

    McMonster napisał:
    Kompilator sam zadba o to, żeby w pliku wynikowym nie znalazły się nieużywane zmienne, nie trzeba nic kombinować poza upewnieniem się, że jest włączona optymalizacja.


    Nieprawda. Po pierwsze nie kompilator o to zadba, tylko linker (kompilator nie wie, czy inne pliki nie używają danej zmiennej, funkcji globalnej). Poza tym zadba tylko pod tym warunkiem, że kompilatorowi przekażesz przy kompilacji flagi -ffunction-sections i -fdata-sections (wówczas każda funkcja i zmienna globalna lub static zostanie umieszczona w swojej własnej sekcji). Poczytaj w manualu do gcc o tych flagach.
    A linkerowi musisz przekazać -Wl,--gc-sections (czyli "garbage collect unused sections").

    Używam tego w każdym programie i nie przejmuję się tym, że moje pliki biblioteczne i inne frameworki zawierają w sumie funkcje zajmujące więcej niż mam pamięci w MCU - linker usuwa mi na końcu nieużywane funkcje, dane i wszystko się mieści. Bez tej "garbage collection" linker musi dołączyć do programu wynikowego cały plik obj, nawet jeśli z danego modułu używamy tylko jednej funkcji czy zmiennej.
    Włączenie tych flag ma tylko jedną wadę - dłużej się wszystko kompiluje.

    krru napisał:
    Musiałbyś zapisać bitmapę każdej literki w oddzielnym pliku (.c), każdy niezależnie skompilować, połączyć to w bibliotekę (.a) i ją linkować do projektu. W takiej konfiguracji linker wybiera z biblioteki tylko używane moduły.


    Patrz moja powyższa wypowiedź. Rozbijanie każdej literki na oddzielne pliki c to przecież strasznie żmudna robota, a po drugie bardzo zaciemniająca kod programu. Lepiej trzymać wszystkie takie tablice w jednym miejscu.
    Czasem można w necie znaleźć "biblioteki", których twórcy umieszczają w jednym pliku c jedną funkcję - to ci, którzy nie znają powyższych flag.

    0
  • #12 27 Mar 2013 12:13
    BlueDraco
    Specjalista - Mikrokontrolery

    Obawiam się, że więcej bajtów stracisz w kodzie wyświetlającym oddzielnie każdą literkę, niż na definicji obrazów nieużywanych liter. Mając to w jednej tablicy możesz po prostu indeksować obrazy kodem litery. Inaczej skazujesz się na koszmarny, wolny i wielki switch () w kodzie, który ma spore szanse zająć więcej miejsca niż tablica obrazów wszystkich znaków.

    0
  • #13 06 Maj 2013 16:10
    w1941s
    Poziom 14  

    Wszystko działa temat rozwiązany. Dziękuje za odpowiedzi.

    0