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

[C][atmega88] Odczyt danych z tablicy.

Marcin_xx1 20 Paź 2008 22:00 1746 7
  • #1 5652037
    Marcin_xx1
    Poziom 21  
    Witam. Przy odczycie początkowych wartosci tablicy "cyfry" zamiast oczekiawanego wyniku ukazują mi się jakieś śmieci tabliczka po skompilowaniu zajmuje około 1KB w programie domyślam się ze ta tablica zajmuje za dużo miejsca w pamięci operacyjnej ale nie jestem pewny w każdym razie po jej obcięciu nie ma tego problemu , przy okazji może ktoś mi podpowie jak skompensować taką tablice?

    
    int licznik = 0 ;
    int i=0;
    int y=0;
    int x=0;
    int z=0;
    
    int cyfry[10][11][5]={
    {{0,0,1,0,0},{0,1,0,1,0},{0,1,0,1,0},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,0,1,0},{0,1,0,1,0},{0,0,1,0,0}},
    {{0,0,1,0,0},{0,1,1,0,0},{1,0,1,0,0},{1,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{0,0,1,0,0},{1,1,1,1,0}},
    {{0,0,1,0,0},{0,1,0,1,0},{1,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0},{0,0,1,0,0},{0,1,0,0,0},{1,0,0,0,0},{1,1,1,1,0}},
    {{0,0,1,0,0},{0,1,0,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,0,0,0,1},{0,0,0,1,0},{0,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}},
    {{0,0,0,1,0},{0,0,0,1,0},{0,0,1,0,0},{0,1,0,1,0},{0,1,0,1,0},{1,1,1,1,1},{0,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0},{0,0,0,1,0}},
    {{1,1,1,1,1},{1,0,0,0,0},{1,0,0,0,0},{0,1,0,0,0},{0,0,1,0,0},{0,0,0,1,0},{0,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}},
    {{0,0,1,0,0},{0,1,0,0,0},{1,0,0,0,0},{1,0,1,0,0},{1,0,0,1,0},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}},
    {{1,1,1,1,1},{0,0,0,0,1},{0,0,0,0,1},{0,0,0,1,0},{0,0,0,1,0},{0,0,1,0,0},{0,0,1,0,0},{0,1,0,0,0},{0,1,0,0,0},{1,0,0,0,0},{1,0,0,0,0}},
    {{0,0,1,0,0},{0,1,0,1,0},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,0},{1,0,0,0,1},{1,0,0,0,1},{1,0,0,0,1},{0,1,0,1,0},{0,0,1,0,0}},
    {{0,0,1,0,0},{0,1,0,1,0},{0,1,0,1,0},{1,0,0,0,1},{1,0,0,0,1},{0,1,1,1,1},{0,0,0,1,1},{0,0,0,1,1},{0,0,1,1,0},{0,1,1,0,0},{1,1,0,0,0}}}; 
    
     ISR (INT1_vect)
    //SIGNAL (SIG_INTERRUPT1) 
    
    {
    
    
    
    PORTB&=~_BV(0);
    
    licznik++;
    
    
    
    
    if(licznik == 120+y)
    {
    _delay_loop_2((55+10));
    
    for(i=0;i<5;i++){
    
    if (cyfry[z][y][i]==1){PORTB|=_BV(0);}else{PORTB&=~_BV(0);}
    
     }
     
     PORTB&=~_BV(0);
     y++;if(y==12){y=0;}
     
     
     }
    
    }
    
     ISR (INT0_vect)
    //SIGNAL (SIG_INTERRUPT0) 
    
    {
    licznik=0;y=0;x++;
    if(x==10){x=0;z++;}
    if(z==10){z=0;}
    
    }
    
    
    //////////////////////////////////////////////////////////////////
    int main(void){
    
    	DDRB&=~_BV(2);//wejscie synhro v
    	PORTB|=_BV(2);
    
    	DDRB&=~_BV(1);//wejscie synhro h
    	PORTB|=_BV(1);
    	
            DDRB|=_BV(0);//wyjscie sygnalu
    	PORTB&=~_BV(0);
    
    
    EIMSK = _BV(INT0)|_BV(INT1);
                            //włącz obsługę przerwań Int0 i Int1
      EICRA = _BV(ISC01)|_BV(ISC11);
                            // włącz generowanie przerwań przez
                            // rosnace zbocze na Int0 i Int1
    
      sei();              // włącz obsługę przerwań
    
    
    while(1){
    
    ;
    
    }
    }
    
    
    


    Poprawiłem tytuł - Regulamin. [c_p]
  • Pomocny post
    #2 5652090
    ciastek4
    Poziom 14  
    Aby zoptymalizować program możesz rozważyć poniższe podpunkty:
    1)Mozesz dać tablicę do flash-a.wystarczy dołączyć plik nagłówkowy <avr\pgmspace.h>
    sposób definicji zmiennej ładowanej do flash:
    np.
    
    static unsigned int LCD_SegTable[] PROGMEM =
    {
        0xEAA8,     // '*'
        0x2A80,     // '+'
        0x4000,     // ','
        0x0A00,     // '-'
        0x0A51,     // '.' Degree sign
        0x4008,     // '/'
    } 
    


    zeby odczytać tą tablicę wystarczy :
    
    pgm_read_word(&LCD_SegTable[4]) 
    



    2) zamiast int ( 16 bitów) dać unsigned char(8bitów) ( zmiejsza poamieć o połowę )

    3)zmienić reprezentację tej tablicy. Popatrz ile miejsca się marnuje w pamięci. Przechowujesz same 0 i 1. Nie prościej zastąpić zapis tablicy 3 wymiarowej 2 wymiarową ?
    popatrz :
    {0,0,1,0,0} = 0x04
    {0,1,0,1,0} = 0x0A itd.
    i teraz mamy taką definicję :
    unsigned char cyfry [10][11] = { {0x04,0x0A,0x0A,0x11 ... itd}}; ( typ zmiennej w RAM-ie)
    lub
    unsigned char cyfry [10][11] PROGMEM = {{0x04,0x0A,0x0A,....}};


    P.S. atmega88 posiada 1K Byte SRAM a Ty chcesz stworzyc tablice o rozmiarze około 4kB. Dlatego się sypie wszystko. Proszę pamiętać, o stosie który leży w RAM-ie :)
  • #3 5652412
    Marcin_xx1
    Poziom 21  
    Gratuluję wiedzy i Dziękuję za wyczerpującą odpowiedz, rzeczywiście zamieniając int na char wszytko ładnie śmiga, niestety zapis na flashu chyba czasowo się nie wyrabia z odczytem i mam krzaczki. Puki co przerobie tablice na dwu wymiarową .

    Dodano po 8 [minuty]:

    Aha coś sobie przypomniałem, co przeszkadza mi w zrobieniu dwu wymiarowej tablicy
    
    
    for(i=0;i<5;i++){
    
    if (cyfry[z][y][i]==1){PORTB|=_BV(0);}else{PORTB&=~_BV(0);}
    
     } 
     


    jak widać w instrukcji jest sprawdzane po kolei pięć bitów

    jeżeli zrobię tą dwu wymiarową tablice będę musiał jakoś zamienić hexy na bity by je sprawdzić wiec mam kolejne pytanie jak to zrobić? :)
  • Pomocny post
    #4 5652729
    Dr.Vee
    VIP Zasłużony dla elektroda
    Marcin_xx1 napisał:
    niestety zapis na flashu chyba czasowo się nie wyrabia z odczytem i mam krzaczki. Puki co przerobie tablice na dwu wymiarową .


    Tablice wielowymiarowe są problematyczne, bo:
    int[] to tablica intów, int[][] ...

    Edit - usunąłem błędne informacje o układzie tablic w pamięci.

    Marcin_xx1 napisał:

    Aha coś sobie przypomniałem, co przeszkadza mi w zrobieniu dwu wymiarowej tablicy
    
    
    for(i=0;i<5;i++){
    
    if (cyfry[z][y][i]==1){PORTB|=_BV(0);}else{PORTB&=~_BV(0);}
    
     } 
     


    jak widać w instrukcji jest sprawdzane po kolei pięć bitów ...


    Chyba miałeś na myśli _BV(i).
    jeśli tak, to po mojemu to by było jakoś tak (zakładając zgodność kolejności bitów):
    
    uint8_t mask = (_BV(5) - 1); /* 0x1f */
    PORTD = (PORTD & ~mask) | (cyfry[z][y] & mask); /* skopiuj 5 najmłodszych bitów cyfry[z][y] do PORTD */
    


    Pozdrawiam,
    Dr.Vee
  • Pomocny post
    #5 5652883
    szelus
    Poziom 34  
    Dr.Vee napisał:

    int[] to tablica intów, int[][] to jedna tablica ze wskaźnikami na tablice intów. [...itd.....]

    Nie no, kolega pomylił wielowymiarowe tablice z niezwymiarowanymi tablicami, które istotnie są wskaźnikami (ale tylko na jednym poziomie, tzn. int x[10][] to będzie to samo co int * x[10]).
    Tablice wielowymiarowe, o podanym rozmiarze, są normalnie ułożone w pamięci, tzn. wszystkie elementy pierwszego wiersza, następnie wszystkie elementy drugiedo wiersza itd.
    Cytat:

    Najprościej zamiast tego użyć tablicy jednowymiarowej i "na piechotę" obliczać adres elementu, np. zamiast int tablica2d[10][10] mamy int tablica1d[100], zamiast tablica2d[i][j] mamy tablica1d[10*i + j].

    Takie obliczenia właśnie wykonuje kompilator dla tablic wielowymiarowych.
  • Pomocny post
    #6 5653068
    Dr.Vee
    VIP Zasłużony dla elektroda
    Rzeczywiście, pomyliły mi się tablice dynamiczne ze statycznymi :) Po małych testach widzę, że:
    #include <stdio.h>
    
    int main(void)
    {
        char array2d[3][3];
    
        printf(" array2d         = 0x%08x\n", array2d);
        printf("&array2d         = 0x%08x\n", &array2d);
        printf(" array2d[0]      = 0x%08x\n",  array2d[0]);
        printf("&array2d[0]      = 0x%08x\n", &array2d[0]);
        printf("&array2d[0][0]   = 0x%08x\n", &array2d[0][0]);
        return 0;
    }
    

    Wypisuje wszystkie adresy takie same...

    Jak widać człowiek się uczy całe życie :)

    Pozdrawiam,
    Dr.Vee
  • #7 5654384
    Marcin_xx1
    Poziom 21  
    Cytat:

    Chyba miałeś na myśli _BV(i).
    jeśli tak, to po mojemu to by było jakoś tak (zakładając zgodność kolejności bitów):
    
    uint8_t mask = (_BV(5) - 1); /* 0x1f */
    PORTD = (PORTD & ~mask) | (cyfry[z][y] & mask); /* skopiuj 5 najmłodszych bitów cyfry[z][y] do PORTD */
    




    :| Nic z tego nie rozumiem :|

    proszę o wyjaśnienie na tym przykładzie:
    
    
    int cyfry[1]={0xAA}; //na przemian  zera i jedynki
    
     /* w pętli sprawdzam bity liczby AA , jeżeli jest 1,  PORTB,PIN 0  w stanie wysokim jezeli 0, w stanie niskim:
    */
    
    for(i=0;i<8;i++){
    
     if (XXXXXXX?){PORTB|=_BV(0);}else{PORTB&=~_BV(0);}
    
    }
    
    


    Dodano po 34 [minuty]:

    ciastek4 napisał:
    Aby zoptymalizować program możesz rozważyć poniższe podpunkty:
    1)Mozesz dać tablicę do flash-a.wystarczy dołączyć plik nagłówkowy <avr\pgmspace.h>
    sposób definicji zmiennej ładowanej do flash:
    np.
    
    static unsigned int LCD_SegTable[] PROGMEM =
    {
        0xEAA8,     // '*'
        0x2A80,     // '+'
        0x4000,     // ','
        0x0A00,     // '-'
        0x0A51,     // '.' Degree sign
        0x4008,     // '/'
    } 
    


    zeby odczytać tą tablicę wystarczy :
    
    pgm_read_word(&LCD_SegTable[4]) 
    



    2) zamiast int ( 16 bitów) dać unsigned char(8bitów) ( zmiejsza poamieć o połowę )

    3)zmienić reprezentację tej tablicy. Popatrz ile miejsca się marnuje w pamięci. Przechowujesz same 0 i 1. Nie prościej zastąpić zapis tablicy 3 wymiarowej 2 wymiarową ?
    popatrz :
    {0,0,1,0,0} = 0x04
    {0,1,0,1,0} = 0x0A itd.
    i teraz mamy taką definicję :
    unsigned char cyfry [10][11] = { {0x04,0x0A,0x0A,0x11 ... itd}}; ( typ zmiennej w RAM-ie)
    lub
    unsigned char cyfry [10][11] PROGMEM = {{0x04,0x0A,0x0A,....}};


    P.S. atmega88 posiada 1K Byte SRAM a Ty chcesz stworzyc tablice o rozmiarze około 4kB. Dlatego się sypie wszystko. Proszę pamiętać, o stosie który leży w RAM-ie :)



    Przede wszystkim przepraszam odnoŚnie powyższego postu, coś nie działało, ponieważ przy zapisywaniu tablicy do flasha niedopatrzylem słówka PROGMEM !!!
  • Pomocny post
    #8 5656208
    Dr.Vee
    VIP Zasłużony dla elektroda
    Marcin_xx1 napisał:

    proszę o wyjaśnienie na tym przykładzie:
    
    
    int cyfry[1]={0xAA}; //na przemian  zera i jedynki
    
     /* w pętli sprawdzam bity liczby AA , jeżeli jest 1,  PORTB,PIN 0  w stanie wysokim jezeli 0, w stanie niskim:
    */
    
    for(i=0;i<8;i++){
    
     if (XXXXXXX?){PORTB|=_BV(0);}else{PORTB&=~_BV(0);}
    
    }
    


    Trzeba było pisać, że chodzi o szeregowe wysyłanie bitów :)
    W poniższym przykładzie testujesz bity od najmłodszego do najstarszego:

    int cyfry[1]={0xAA}; 
    
    for(i = 0; i < 8; i++) {
       if (cyfry[1] & _BV(i)) {
          PORTB |=_BV(0);
       } else {
          PORTB &= ~_BV(0);
       }
    }
    


    Pozdrawiam,
    Dr.Vee
REKLAMA