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

[GCC]Położenie funkc. w progr. odwoł.się do tabl.komunikatów

Pawel1812 12 Maj 2009 15:01 1878 11
  • #1 6520646
    Pawel1812
    Poziom 26  
    Witam
    Piszę program, w którym jest konieczne odwołanie się w funkcji do tablicy komunikatów, która musi być umieszczona po main(). Rozwiązałem to, umieszczając te nieszczęsne funkcje w ciele programu po main(). Niestety, okazało sie konieczne odwołanie się do tych funkcji w innych funkcjach umieszczonych normalnie przed main()
    Próbowałem umieścić na początku programu umieścić deklaracje zmiennych i przenieść na początek nieszczęsne funkcje odwołujące się do tablic komunikatów. Problem w tym, zę program choć się skompilował, to zaczał działać inaczej - generować smieci na LCD.
    Będę wdzięczny za jakiekolwiek rady - jak uporządkować tak zbudowany program?


    Czy umieszczenie deklaracji tablicy zmiennych i tekstów tam zawartych w innym pliku niż main.c będzie coś zmieniało?
  • Pomocny post
    #2 6520675
    Dr.Vee
    VIP Zasłużony dla elektroda
    A dlaczego tablica/komunikaty musi być umieszczona "po main()"?

    Pozdrawiam,
    Dr.Vee
  • #3 6520745
    Pawel1812
    Poziom 26  
    We wszystkich przykładowych programach tablice typu:
    
     char *tekst[]= {PSTR(" Przykładowy tekst"),
                       PSTR("Przykładowy tekst 2"),
    };
    

    są właśnie po main()

    Inaczej program się niestety nie skompiluje, zwróci komunikaty tupu:
    
    avr-gcc -c -mmcu=atmega162 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o 
    main.c:115: error: braced-group within expression allowed only inside a function
    main.c:116: error: braced-group within expression allowed only inside a function
    main.c:117: error: braced-group within expression allowed only inside a function
    main.c:118: error: braced-group within expression allowed only inside a function
    


    Umieszczenie tej tablicy w dowolnej funkcji (nie w funkcji main())spowoduje też błąd kompilacji na pierwszej funkcji używającej teblic.
  • Pomocny post
    #4 6520803
    Dr.Vee
    VIP Zasłużony dla elektroda
    PSTR nie można używać w tym kontekście, zobacz sobie na jego implementację w pliku nagłówkowym.

    Ten program kompiluje się jak trzeba:
    #include <avr/io.h>
    #include <avr/pgmspace.h>
    
    prog_char _s0[] PROGMEM = "alfa";
    prog_char _s1[] PROGMEM = "beta";
    
    const prog_char* strings[] PROGMEM =  {
        _s0, _s1,
    };
    
    int main(void)
    {
        PGM_P addr = pgm_read_word(&strings[0]);
        PORTB = pgm_read_byte(addr);
    }


    Edit: poprawka głupiego błędu - nazwa zmiennej.
    Edit 2: przeniesienie PROGMEM przed znak równości.

    Pozdrawiam,
    Dr.Vee
  • #5 6520849
    Pawel1812
    Poziom 26  
    A u mnie doklejenie dokładnie tego na początek mojego programu powoduje błąd:
    
    
    Compiling: main.c
    avr-gcc -c -mmcu=atmega162 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o 
    main.c:146: error: expected expression before '__attribute__'
    


    Zdaniem kompilatora błąd jest w tej linii
    
    const prog_char* strings[] = PROGMEM { 
    


    Natomiast kompilacja dokładnie takiego programu:
    
    
    #include <avr/io.h> 
    #include <avr/pgmspace.h> 
    
    prog_char _s0[] PROGMEM = "alfa"; 
    prog_char _s1[] PROGMEM = "beta"; 
    
    const prog_char* strings[] = PROGMEM { 
        _s0, _s1, 
    }; 
    
    int main(void) 
    { 
        PGM_P string_addr = pgm_read_word(&strings[0]); 
        PORTB = pgm_read_byte(addr); 
    
    while();
    }
    

    daje taki rezultat:
    
    avr-gcc -c -mmcu=atmega162 -I. -gdwarf-2 -DF_CPU=8000000UL  -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=main.lst  -std=gnu99 -MD -MP -MF .dep/main.o.d main.c -o main.o 
    main.c:8: error: expected expression before '__attribute__'
    main.c: In function 'main':
    main.c:14: warning: initialization makes pointer from integer without a cast
    main.c:15: error: 'addr' undeclared (first use in this function)
    main.c:15: error: (Each undeclared identifier is reported only once
    main.c:15: error: for each function it appears in.)
    main.c:17: error: expected expression before ')' token
    main.c:14: warning: unused variable 'string_addr'
    make.exe: *** [main.o] Error 1
    
    > Process Exit Code: 2
    > Time Taken: 00:00
    
  • Pomocny post
    #6 6520934
    Dr.Vee
    VIP Zasłużony dla elektroda
    Masz rację - progmem powinien znaleźć się przed znakiem równości, a drugi błąd to pomyłka w nazwie zmiennej addr.

    Ostatni błąd dodałeś sam omijając wyrażenie w nawiasie po while.

    Pozdrawiam,
    Dr.Vee
  • #7 6521055
    Pawel1812
    Poziom 26  
    Skompilować się udało, za co dziękuję, jednak na LCD teraz jest pusto :( Trzeba będzie zmodyfiować coś w funkcji, która pokazuje teksty na LCD, a na razie wygląda ona tak:


    
    void lcd_str_P(prog_char * string)
    {
    char ch;
    while((ch = pgm_read_byte(string++)))
      {
      GLCD_WriteChar(ch);
      }
    }
    

    w dołączonym gotowym pliku sterownika LCD, a tak wygląda wyświetlanie napisu w moim programie:
    
    lcd_str_P(strings[1]);
    

    Powrót do poprzedniego sposobu deklaracji zmiennej przywraca napisy na LCD, więc błąd jest właśnie na tym etapie.
    Niestety, nie rozumiem, jak to musi wyglądać, aby napisy się na LCD pojawiały przy nowym sposobie deklaracji zmiennej - który w moim dość złożonym programie jest konieczny.
    Dobrze by było, gdyby zmiana była tylko w pliku sterownika LCD, gdyż zapis
    
    lcd_str_P(strings[1]);
    

    powtarza się w bardzo wielu miejscach proogramu.
  • Pomocny post
    #8 6521165
    BoskiDialer
    Poziom 34  
    Jeśli ciągi znaków znajdują się w PROGMRM, to odwołujesz się do nich przez pgm_read_*, ale skoro tablicę strings też umieściłeś w pamięci PROGMEM, to ją też musisz odczytywać przez pgm_read_* - inaczej nie uzyskujesz poprawnego wskaźnika na ciąg.
  • Pomocny post
    #9 6522153
    Dr.Vee
    VIP Zasłużony dla elektroda
    Innymi słowy wyrzuć PROGMEM:
    const prog_char* strings[] = { _s0, _s1};
    W ten sposób wskaźniki zostaną skopiowane do RAMu przed uruchomieniem funkcji main() i będziesz miał do nich dostęp tak jak dawniej.

    Pozdrawiam,
    Dr.Vee
  • #10 6523317
    Pawel1812
    Poziom 26  
    Problem w tym, że nie mogę sobie pozwolić na załadowanie komunikatów do RAMu - nie zmieszczą się :(

    Zastanawiam się cały czas nad tym:
    
    
    void lcd_str_P(prog_char * string) 
    { 
    char ch; 
    while((ch = pgm_read_byte(string++))) 
      { 
      GLCD_WriteChar(ch); 
      } 
    } 
    

    odczyt jest przez pgm_read_byte, a jednak nic na LCD nie ma. Działa natomiast przy poprzednim sposobie zapisu zmiennej, która też korzysta z pamięci programu.
  • Pomocny post
    #11 6523358
    BoskiDialer
    Poziom 34  
    Widać nie rozumiesz o co chodzi. Ani ja ani Dr.Vee nie mówimy o przeniesieniu komunikatów do ramu, tylko tablicy wskaźników na komunikaty. Najpierw musisz pobrać wskaźnik z tablicy (ponieważ napisów jest więcej), potem dopiero wykorzystując wskaźnik odczytujesz ciąg z pamięci programu. Jeśli nie chcesz przenosić tablicy wskaźników, to niestety musisz zmienić wywołania postaci "lcd_str_P(strings[1]);" na "lcd_str_P(pgm_read_word(&strings[1]))" - tylko wtedy odczyt wskaźnika z tablicy będzie poprawny (gdyż tablica strings znajduje się w PROGMEM). Druga możliwość, to przenieść tablicę strings do pamięci RAM (usunięcie PROGMEM). Same ciągi znaków nadal pozostaną w pamięci PROGMEM.
  • #12 6523412
    Pawel1812
    Poziom 26  
    Zaczynam to po woli rozumieć, o co tu chodzi, a już na pewno zaczyna to działać. Na LCD po wpisaniu
    
    lcd_str_P(pgm_read_word(&strings[1]));
    

    pojawiły się napisy. Serdecznie dziękuję za wyjaśnienie tego problemu - sam bym sobie nie poradził.
REKLAMA