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

[c] Atmega32 źle działające Progmem

oskar777 24 Paź 2011 02:14 1630 4
  • #1 10059620
    oskar777

    Poziom 26  
    Witam Was taki malutki problemik :/. Tworze sobie menu tak więc dalem
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Wywołuje w w głównej pętli tak
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    To mi wywala jakieś małe śmieci
    jak dam np
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    To działa poprawnie.
    numer jest typu unsigned char

    LCD_WriteTextP jest przeróbką radzia kodu, który to znalazłem na forum.
    Ma postać.

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


    Wie ktoś jak to zrobić poprawnie?

    Pozdrawiam serdecznie
  • Pomocny post
    #2 10059858
    Andrzej__S
    Poziom 28  
    Przykład jest podany w avr-libc manual. Tutaj (link) podałem go z komentarzami.
  • #3 10060762
    oskar777

    Poziom 26  
    Dzięki za przykład działa dobrze, tylko nadal mnie zastanawia czemu to nie działa, tym bardziej że ten kod powyżej jest o wiele łatwiejszy.
  • Pomocny post
    #4 10061221
    Andrzej__S
    Poziom 28  
    oskar777 napisał:

    Dzięki za przykład działa dobrze, tylko nadal mnie zastanawia czemu to nie działa, tym bardziej że ten kod powyżej jest o wiele łatwiejszy.

    Chyba wartość kodu ocenia się w pierwszej kolejności na podstawie jego skuteczności, a nie tego, czy jest łatwiejszy. No bo co z tego, że jest łatwiejszy, jeśli nie działa?

    Przykład, który podałem nie jest mojego autorstwa, jak już zresztą wcześniej zaznaczyłem. Pochodzi z "AVR Libc User Manual". Ja go tylko opatrzyłem komentarzami. Nie chcesz chyba zarzucić autorom AVR libc, że piszą jakiś nieefektywny kod lub podają złe przykłady?

    Nie ma nic dziwnego w tym, że Twój kod nie działa. Nie możesz w ten sposób podać do funkcji wskaźnika zapisanego w pamięci flash. W deklaracji
    char* Menu_wskaznik[] PROGMEM = {Menu_1,Menu_2,Menu_3};
    pomiń atrybut PROGMEM (tablica wskaźników wyląduje wtedy w pamięci RAM, ale Twój kod powinien działać prawidłowo).
    Jak masz tablicę wskaźników zapisaną we flash, to musisz to zrobić tak, jak w podanym przeze mnie przykładzie, pomimo tego, że jest to trudniejsze :)

    P.S. Uprzedzę może jeszcze pytanie, dlaczego działa ze stałymi indeksami (LCD_WriteTextP(Menu_wskaznik[1]);), a nie działa ze zmienną w indeksie (LCD_WriteTextP(Menu_wskaznik[numer]);). Otóż kompilator w przypadku podania stałej jako indeksu tablicy znając zawartość tej tablicy wymieni w czasie kompilacji Menu_wskaznik[1] na wartość wskaźnika Menu_2. Jak użyjesz jako indeksu zmiennej, to już nie może tego zrobić, bo nie jest w stanie podczas kompilacji ustalić, którego wskaźnika w danym momencie użyjesz (jaka będzie wartość zmiennej indeksującej). Musisz więc ten wskaźnik odczytać programowo, a ponieważ jest on w pamięci flash, nie da się tego zrobić bezpośrednio, jak w przypadku zmiennych w RAM Menu_wskaznik[i]. Najlepiej do tego użyć:
    memcpy_P(&tekst, &Menu_wskaznik[i], sizeof(const char *));
    Dopiero wtedy możesz użyć zmiennej 'tekst' do odczytywania ciągu znaków z pamięci flash, tak jak to zrobiłeś.
  • #5 10062983
    oskar777

    Poziom 26  
    To właśnie chciałem wiedzieć czemu tak się dzieje, temat pozostaje otwarty bo menu będę rozbudowywał. Jeszcze raz dzięki za poświęcony czas.
REKLAMA