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

Jak odczytać dane z MAX1288 przez SPI na Atmega32?

_MaY_ 03 Lut 2008 19:38 1840 6
REKLAMA
  • #1 4766974
    _MaY_
    Poziom 16  
    Posty: 283
    Pomógł: 3
    Ocena: 19
    Witam

    Wiem że to śmieszne ale nie potrafię sobie poradzić z odczytem danych z układu MAX1288. Napisałem procedurę która powinna inicjować układ i przeprowadzić odczyt z układu łącznie ze zlepieniem dwóch bajtów w 16bitów i zwróceniem tej wartości do głównego programu. Ale jak to zwykle w życiu bywa nie bardzo chce to działać.

    Tu pdf do układu:
    http://datasheets.maxim-ic.com/en/ds/MAX1286-MAX1289.pdf

    Układ ma mierzyć napięcie z jednego wejścia i wyświetlać na LCD. Wszystko oparte jest na atmedze 32 z zegarem 4MHz.

    
    // DEFINICJE DLA SPI
    #define CNVST_ON          PORTB |=   0x08 ; 	
    #define CNVST_OFF         PORTB &= ~(0x08);
    
    //----------------------------- ODCZYT Z AC ----------------------------------//
    
    
    void spi_init(void)  //inicjacja spi jako master, czestotliwosc 31250Hz
    {
     	 DDRB  |= 0xB0;  // Ustawienie SCK, MOSI & SS jako wyjsc
         PORTB &= 0x5F;  // wyzerowanie MOSI, & SCK
     	 SPCR = 0x73; //konfiguracja rejestrow SPI
     	 SPSR = 0x00; 
    }	
     	 
    int spi_odczyt(void)
    {
    
     	 char i = 0x00;
    	 char pom_temp1 = 0x00;
    	 char pom_temp2 = 0x00;
    	 int wynik_ADC = 99; //zmienna 16 bit BEZ znaku dla wyyniku odczytu ???? moze powinna byc ze znakiem
    	 
    	//CNVST PB3
    	//DOUT MISO
    	
    	//PORTA |= 0x80;	// wlaczenie bitu 7 (msb)
       //PORTA &= ~0x80;	// wylaczenie bitu 7
    
    //////// Start transmisji 1-ego bajtu
    
    	 CNVST_ON; 	  			 // ustawienie CNVST na "1"
    	 	   for(i=0;i<6;i++) 		 // przytrzymanie CNVST przez 1,4us
    		   {
    		   	asm ("nop");
    		   }		   
    	 CNVST_OFF; 				 // ustawienie CNVST na "0"
    	       for(i=0;i<40;i++) 		 // odczekanie na koniec konwersji i gotowosc do wyslania
    		   {
    		   	asm ("nop");
    		   }
    	 
    	 SPDR = 0x00; 					 // wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
         while (!(SPSR & (1<<SPIF))); 	 // Sprawdzenie flagi konca transmisji
    	 pom_temp1 = SPDR; 				 // zapisanie 1-ego bajtu
    	 
    	 
    	 
    /////// Start transmisji 2-ego bajtu
    
    	 CNVST_ON; 	 	   		     // ustawienie CNVST na "1"
    	 	   for(i=0;i<6;i++) 		// przytrzymanie CNVST przez 1,4us
    		   {
    		   	asm ("nop");
    		   }		   
    	 CNVST_OFF; 				// ustawienie CNVST na "0"
    	       for(i=0;i<40;i++) 		// odczekanie na koniec konwersji i gotowosc do wyslania
    		   {
    		   	asm ("nop");			// dla zegara 1MHz 1us dla zegara 4MHz powinno byc 0,25us
    		   }
    	 
    	 SPDR = 0x00; 					// wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
    	 while(!(SPSR & (1<<SPIF)));    // Sprawdzenie flagi konca transmisji
    	 pom_temp2 = SPDR; 				// zapisanie 2-ego bajtu
    	 
    CNVST_ON; //ustawienie portu w stan wysoki zeby sie nie gryzl z drugim urzadzeniem
    
    //wartosci testowe
    //pom_temp1=0xFF; //MSB 
    //pom_temp2=0x00; //LSB 
    
    // scalenie MSB z LSB do jednej zmiennej 16 bitowej
    wynik_ADC = pom_temp1; 
    wynik_ADC <<=8; 
    wynik_ADC |= pom_temp2; 
    
    //zerowanie  trzech najstarszych bitow trzeba zrobic
    	 
    	 return (wynik_ADC + 256); //zwracanie wartosci zmierzonej ?? dlaczego wartosc zerowa rowna jest -256??                                                                                                                                                                                                                                        
    	 
    	 
    	 
    	 
    }	
    
    //--------------------------- KONIEC ODCZYTU Z AC ----------------------------//


    Byłbym bardzo wdzięczny za wszelkie sugestie co skopałem.
  • REKLAMA
  • #2 4769865
    wmartinez
    Poziom 11  
    Posty: 59
    Pomógł: 1
    Jesli uklad odpowiada jakimis danymi to juz dobrze:P
    Tak na szybko zerknalem na zapis do zmiennej 16-bitowej i..
    nie powinno byc tak?:

    
    // scalenie MSB z LSB do jednej zmiennej 16 bitowej
    wynik_ADC = pom_temp1;
    wynik_ADC <<=4;
    wynik_ADC |= (pom_temp2>>4)&0xF;
    


    konwerter wypluwa 12 kolejnych bitow, tak ze w drugim odebranym bajcie ostatnie bity odczytu znajduja sie w jego starszej czesci.

    no i w ogole CPOL=CPHA=0 jak by co:P

    i dlaczego return (wynik_ADC + 256); ? O co chodzi z tym +256?
  • REKLAMA
  • #3 4770346
    zbigel
    Poziom 12  
    Posty: 82
    Pomógł: 6
    Ocena: 11
    Witam.
    Wiesz wydaje mi się, że Twój problem polega na tym, iż niepotrzebnie generujesz impuls na linii CNVST przed transmisją drugiego bajtu. W datasheecie, który załączyłeś, na stronie 12 jest przebieg i jak widzisz impuls na CNVST występuje tylko raz na początku. Wygenerowanie impulsu po raz drugi wyzwala nową konwersję.
    Pozdrawiam.
    Zbigel
  • REKLAMA
  • #4 4774261
    _MaY_
    Poziom 16  
    Posty: 283
    Pomógł: 3
    Ocena: 19
    Witam zastosowalem sie do waszych sugestii ale nadal nic to nie daje. Ciagle jak zaklete na wyswietlaczu pojawia mi sie tylko 0. Sprobuje pozniej odlaczyc calkowicie uklad przetwornika od atmegi i zobacze co wtedy pokaze.
  • #5 4777849
    _MaY_
    Poziom 16  
    Posty: 283
    Pomógł: 3
    Ocena: 19
    No i lipa rece mi juz opadaja przy tym. Po odlaczeniu zasilania przetwornika nadal wynik rowny zero. Poprawilem kilka rzeczy ale nadal nic...
    Teraz program wyglada tak:
    
    #include <iom32v.h>
    #include <macros.h>
    #include <stdio.h>
    #include <BaseType.h>
    #include <stdlib.h>
    
    
    // DEFINICJE DLA SPI
    #define CNVST_ON			PORTB |=   0x08 ; 	
    #define CNVST_OFF           PORTB &= ~(0x08);
    
    // DEFINICJE DLA LCD
    #define RS 5
    #define E  6
    
    #define LCD_ON				0x0E   
    #define LCD_OFF				0x08
    #define LCD_HOME			0x02  
    #define LCD_CLEAR			0x01
    #define LCD_NOWA_LINIA   	0xC0
    
    #define DANE   				PORTA
    #define RSE_PORT 			PORTD 
    
    #define SET_E 				RSE_PORT|=(1<<E)  
    #define CLR_E 				RSE_PORT&=~(1<<E) 
    #define SET_RS 				RSE_PORT|=(1<<RS) 
    #define CLR_RS 				RSE_PORT&=~(1<<RS) 
    
    
    
    //----------------------------- ODCZYT Z AC ----------------------------------//
    
    
    void spi_init(void)  //inicjacja spi jako master, czestotliwosc 250kHz
    {
     	 DDRB  = 0xB0;  // Ustawienie SCK, MOSI & SS jako wyjsc
         PORTB = 0x00;   // wyzerowanie MOSI, & SCK
    	 
     	 SPCR = 0x51;   //konfiguracja rejestrow SPI
     	 SPSR = 0x00; 
    }	
     	 
    int spi_odczyt(void)
    {
    
     	 unsigned int i = 0x00;
    	 char pom_temp1 = 0xFF;
    	 char pom_temp2 = 0xFF;
    	 int wynik_ADC = 99; //zmienna 16 bit BEZ znaku dla wyyniku odczytu ???? moze powinna byc ze znakiem
    	 
    	//CNVST ->> PB3
    	//DOUT  ->> MISO
    
    //////// Start transmisji 1-ego bajtu
    
    	 CNVST_ON; 	  			 // ustawienie CNVST na "1"
    	 	   for(i=0;i<6;i++) 		 // przytrzymanie CNVST przez 1,4us
    		   {
    		   	asm ("nop");
    		   }		   
    	 CNVST_OFF; 				 // ustawienie CNVST na "0"
    	       for(i=0;i<256;i++) 		 // odczekanie na koniec konwersji i gotowosc do wyslania
    		   {
    		   	asm ("nop");
    		   }
    	 
    	 SPDR = 0x00; 					 // wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
         while (!(SPSR & (1<<SPIF))); 	 // Sprawdzenie flagi konca transmisji
    	 pom_temp1 = SPDR; 				 // zapisanie 1-ego bajtu
    	 
    /////// Start transmisji 2-ego bajtu
    
         asm ("nop");
    	 
    	 SPDR = 0x00; 					// wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
    	 while(!(SPSR & (1<<SPIF)));    // Sprawdzenie flagi konca transmisji
    	 pom_temp2 = SPDR; 				// zapisanie 2-ego bajtu
    	 
    
    
    
    // scalenie MSB z LSB do jednej zmiennej 16 bitowej
    /*wynik_ADC = pom_temp1; 
    wynik_ADC <<=8; 
    wynik_ADC |= pom_temp2; 
    */
    
    wynik_ADC = pom_temp1;
    wynik_ADC <<=4;
    wynik_ADC |= (pom_temp2>>4)&0xF; 
    
    //zerowanie  trzech najstarszych bitow trzeba zrobic
    	 
    	 return (wynik_ADC); //zwracanie wartosci zmierzonej                                                                                                                                                                                                                                       zx
    	 
    	 
    	 
    	 
    }	
    
    //--------------------------- KONIEC ODCZYTU Z AC ----------------------------//
    
    
    	 
    //------------------------ OBSLUGA LCD ---------------------------------------//
    
    void czekaj(unsigned int pt) //funkcja opoznienia
    { 
      	 unsigned int tp1; 
    	 for (;pt>0;pt--) 
    	 { 
      	   for (tp1=255;tp1!=0;tp1--); 
    	 }
    } 
    
     
    void ustaw_lcd(unsigned char ustaw) 
    { 
       DANE=ustaw; 
       CLR_RS; 
       czekaj(10); // minimum to 140ns 
       SET_E; 
       czekaj(10); // minimum to 450ns 
       CLR_E; 
       czekaj(10); // minimum to 20ns 
    } 
    
    
    void dane_lcd(unsigned char dana) 
    { 
       DANE=dana; 
       SET_RS; 
       czekaj (10); 
       SET_E; 
       czekaj(10); 
       CLR_E; 
       czekaj(10); 
    } 
    
    void LCD_init(void)  //inicjacja dla magistrali 8 bitow
    { 
      	 short int i;
    	 unsigned char j;
    	 
    	 DDRA=0xFF; //wyjscie 
    	 DDRD=0xE2; //wyjscie i wejscia dla klawiszy ustawione /////////////////////
       
      
    	 PORTD=0x00;
    
    	 
    	 
    	 DDRB |= 0x01;//ustawienie dla podswietlania pinu jako wyjscia
    	 PORTB &=~(0x01); //wylaczenie podswietlania
    	 
         DANE=0; 
         RSE_PORT=0; 
    
    	 CLR_RS; 
         CLR_E; 
    	 
    	 for(i=0;i<255;i++) //_delay_ms(20); 
         DANE=0x03;   
    	  
        
       for(j=0;j<3;j++) 
       {
       	 SET_E;
         CLR_E;
    	 for(i=0;i<255;i++);
       } 
       
        DANE=0x02; 
        SET_E; 
        CLR_E; 
       
       
       
       for(i=0;i<255;i++) //opoznienie (5); 
       ustaw_lcd(0x38); //function set - interfejs = 8 bit, linie = 2,font = 5x7 
       ustaw_lcd(0x0c); //kontrola wyswietlacza - wlaczenie wyswietlacza
       ustaw_lcd(0x06); //autoinkrementacja wyswietlanych znakow 
       ustaw_lcd(LCD_CLEAR); //czysczenie wyswietlacza
    
       	
    }	 
    
    void write_text(char * s) 
    { 
    while(*s) // do napotkania 0 
      { 
      dane_lcd(*s); // zapisz znak wskazywany przez s na LCD 
      s++; // zwieksz s (przygotuj nastepny znak) 
      } 
    } 
    
    
    void xy_lcd(unsigned char x, unsigned char y) //dla wyswietlacza 16*2 ustawianie miejsca/ 
    { 
          ustaw_lcd((x*0x40+y)|0x80); 
    } 
    	
    
    //-------------------------- KONIEC OBLUGI LCD -------------------------------//
    
    
    
    
    void main(void)
    {
    int i;
    int warunek = 33;
    int wynik   = 33; 
    char buffer[30]; 
     
    spi_init ();
    LCD_init ();
    
    
    ////////////////////////////////////////////////////////////////////////////////
    
    
    
     while (1) // nieskonczona petla z programem
          {
    	  
    	
    	  wynik = spi_odczyt(); // przepisanie wartosci zwracanej z SPI_ODZCZYT do zmiennej wynik
    	  ltoa ( buffer, wynik, 10 ); //konwersja zmiennej na string zeby mozna bylo wyswietlac
    	  
    	  
    	  xy_lcd(2,5);
    	  sprintf(buffer, "%d V", wynik); //wyswietlanie zmierzonej zmiennej
          write_text(buffer); 
    	  
    		//PORTA |= 0x80;	// wlaczenie bitu 7 (msb)
    		//PORTA &= ~0x80;	// wylaczenie bitu 7
    		//PORTA ^= 0x80;	// flip bit 7
    		//if ((PINA & 0x81) == 0)	// check bit 7 and bit 0
    		
        	  
    	  };
      
      
       
    
    }
    
    


    Dodano po 2 [godziny] 6 [minuty]:

    No i lipa rece mi juz opadaja przy tym. Po odlaczeniu zasilania przetwornika nadal wynik rowny zero. Poprawilem kilka rzeczy ale nadal nic...
    Teraz program wyglada tak:
    
    #include <iom32v.h>
    #include <macros.h>
    #include <stdio.h>
    #include <BaseType.h>
    #include <stdlib.h>
    
    
    // DEFINICJE DLA SPI
    #define CNVST_ON			PORTB |=   0x08 ; 	
    #define CNVST_OFF           PORTB &= ~(0x08);
    
    // DEFINICJE DLA LCD
    #define RS 5
    #define E  6
    
    #define LCD_ON				0x0E   
    #define LCD_OFF				0x08
    #define LCD_HOME			0x02  
    #define LCD_CLEAR			0x01
    #define LCD_NOWA_LINIA   	0xC0
    
    #define DANE   				PORTA
    #define RSE_PORT 			PORTD 
    
    #define SET_E 				RSE_PORT|=(1<<E)  
    #define CLR_E 				RSE_PORT&=~(1<<E) 
    #define SET_RS 				RSE_PORT|=(1<<RS) 
    #define CLR_RS 				RSE_PORT&=~(1<<RS) 
    
    
    
    //----------------------------- ODCZYT Z AC ----------------------------------//
    
    
    void spi_init(void)  //inicjacja spi jako master, czestotliwosc 250kHz
    {
     	 DDRB  = 0xB0;  // Ustawienie SCK, MOSI & SS jako wyjsc
         PORTB = 0x00;   // wyzerowanie MOSI, & SCK
    	 
     	 SPCR = 0x51;   //konfiguracja rejestrow SPI
     	 SPSR = 0x00; 
    }	
     	 
    int spi_odczyt(void)
    {
    
     	 unsigned int i = 0x00;
    	 char pom_temp1 = 0xFF;
    	 char pom_temp2 = 0xFF;
    	 int wynik_ADC = 99; //zmienna 16 bit BEZ znaku dla wyyniku odczytu ???? moze powinna byc ze znakiem
    	 
    	//CNVST ->> PB3
    	//DOUT  ->> MISO
    
    //////// Start transmisji 1-ego bajtu
    
    	 CNVST_ON; 	  			 // ustawienie CNVST na "1"
    	 	   for(i=0;i<6;i++) 		 // przytrzymanie CNVST przez 1,4us
    		   {
    		   	asm ("nop");
    		   }		   
    	 CNVST_OFF; 				 // ustawienie CNVST na "0"
    	       for(i=0;i<256;i++) 		 // odczekanie na koniec konwersji i gotowosc do wyslania
    		   {
    		   	asm ("nop");
    		   }
    	 
    	 SPDR = 0x00; 					 // wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
         while (!(SPSR & (1<<SPIF))); 	 // Sprawdzenie flagi konca transmisji
    	 pom_temp1 = SPDR; 				 // zapisanie 1-ego bajtu
    	 
    /////// Start transmisji 2-ego bajtu
    
         asm ("nop");
    	 
    	 SPDR = 0x00; 					// wlaczenie odbierania przez wpisanie wartosci do rejestru SPDR
    	 while(!(SPSR & (1<<SPIF)));    // Sprawdzenie flagi konca transmisji
    	 pom_temp2 = SPDR; 				// zapisanie 2-ego bajtu
    	 
    
    
    
    // scalenie MSB z LSB do jednej zmiennej 16 bitowej
    /*wynik_ADC = pom_temp1; 
    wynik_ADC <<=8; 
    wynik_ADC |= pom_temp2; 
    */
    
    wynik_ADC = pom_temp1;
    wynik_ADC <<=4;
    wynik_ADC |= (pom_temp2>>4)&0xF; 
    
    //zerowanie  trzech najstarszych bitow trzeba zrobic
    	 
    	 return (wynik_ADC); //zwracanie wartosci zmierzonej                                                                                                                                                                                                                                       zx
    	 
    	 
    	 
    	 
    }	
    
    //--------------------------- KONIEC ODCZYTU Z AC ----------------------------//
    
    
    	 
    //------------------------ OBSLUGA LCD ---------------------------------------//
    
    void czekaj(unsigned int pt) //funkcja opoznienia
    { 
      	 unsigned int tp1; 
    	 for (;pt>0;pt--) 
    	 { 
      	   for (tp1=255;tp1!=0;tp1--); 
    	 }
    } 
    
     
    void ustaw_lcd(unsigned char ustaw) 
    { 
       DANE=ustaw; 
       CLR_RS; 
       czekaj(10); // minimum to 140ns 
       SET_E; 
       czekaj(10); // minimum to 450ns 
       CLR_E; 
       czekaj(10); // minimum to 20ns 
    } 
    
    
    void dane_lcd(unsigned char dana) 
    { 
       DANE=dana; 
       SET_RS; 
       czekaj (10); 
       SET_E; 
       czekaj(10); 
       CLR_E; 
       czekaj(10); 
    } 
    
    void LCD_init(void)  //inicjacja dla magistrali 8 bitow
    { 
      	 short int i;
    	 unsigned char j;
    	 
    	 DDRA=0xFF; //wyjscie 
    	 DDRD=0xE2; //wyjscie i wejscia dla klawiszy ustawione /////////////////////
       
      
    	 PORTD=0x00;
    
    	 
    	 
    	 DDRB |= 0x01;//ustawienie dla podswietlania pinu jako wyjscia
    	 PORTB &=~(0x01); //wylaczenie podswietlania
    	 
         DANE=0; 
         RSE_PORT=0; 
    
    	 CLR_RS; 
         CLR_E; 
    	 
    	 for(i=0;i<255;i++) //_delay_ms(20); 
         DANE=0x03;   
    	  
        
       for(j=0;j<3;j++) 
       {
       	 SET_E;
         CLR_E;
    	 for(i=0;i<255;i++);
       } 
       
        DANE=0x02; 
        SET_E; 
        CLR_E; 
       
       
       
       for(i=0;i<255;i++) //opoznienie (5); 
       ustaw_lcd(0x38); //function set - interfejs = 8 bit, linie = 2,font = 5x7 
       ustaw_lcd(0x0c); //kontrola wyswietlacza - wlaczenie wyswietlacza
       ustaw_lcd(0x06); //autoinkrementacja wyswietlanych znakow 
       ustaw_lcd(LCD_CLEAR); //czysczenie wyswietlacza
    
       	
    }	 
    
    void write_text(char * s) 
    { 
    while(*s) // do napotkania 0 
      { 
      dane_lcd(*s); // zapisz znak wskazywany przez s na LCD 
      s++; // zwieksz s (przygotuj nastepny znak) 
      } 
    } 
    
    
    void xy_lcd(unsigned char x, unsigned char y) //dla wyswietlacza 16*2 ustawianie miejsca/ 
    { 
          ustaw_lcd((x*0x40+y)|0x80); 
    } 
    	
    
    //-------------------------- KONIEC OBLUGI LCD -------------------------------//
    
    
    
    
    void main(void)
    {
    int i;
    int warunek = 33;
    int wynik   = 33; 
    char buffer[30]; 
     
    spi_init ();
    LCD_init ();
    
    
    ////////////////////////////////////////////////////////////////////////////////
    
    
    
     while (1) // nieskonczona petla z programem
          {
    	  
    	
    	  wynik = spi_odczyt(); // przepisanie wartosci zwracanej z SPI_ODZCZYT do zmiennej wynik
    	  ltoa ( buffer, wynik, 10 ); //konwersja zmiennej na string zeby mozna bylo wyswietlac
    	  
    	  
    	  xy_lcd(2,5);
    	  sprintf(buffer, "%d V", wynik); //wyswietlanie zmierzonej zmiennej
          write_text(buffer); 
    	  
    		//PORTA |= 0x80;	// wlaczenie bitu 7 (msb)
    		//PORTA &= ~0x80;	// wylaczenie bitu 7
    		//PORTA ^= 0x80;	// flip bit 7
    		//if ((PINA & 0x81) == 0)	// check bit 7 and bit 0
    		
        	  
    	  };
      
      
       
    
    }
    
    
  • REKLAMA
  • #6 4779887
    _MaY_
    Poziom 16  
    Posty: 283
    Pomógł: 3
    Ocena: 19
    nikt nie potrafi pomoc??
  • #7 4788039
    _MaY_
    Poziom 16  
    Posty: 283
    Pomógł: 3
    Ocena: 19
    Witam
    I problem sie rozwiazal, okazalo sie ze bledne bylo uzycie funkcji ltoa tzn. nie zgadzaly sie typy zmiennych i przez to funkcja zwracala 0. Jeszcze tylko trzeba bedzie zrobic usrednianie oraz jakos to wykalibrowac zeby pokazywalo dobre wartosci.

Podsumowanie tematu

✨ Dyskusja dotyczy problemów z odczytem danych z 12-bitowego przetwornika analogowo-cyfrowego MAX1288 za pomocą interfejsu SPI na mikrokontrolerze Atmega32 z zegarem 4 MHz. Autor napisał procedurę inicjalizacji i odczytu danych, łącząc dwa bajty w 16-bitową wartość, jednak wynik na wyświetlaczu LCD pozostawał zerowy. Wskazano, że konwersja powinna być wyzwalana pojedynczym impulsem na linii CNVST na początku transmisji, a nie przed każdym bajtem, aby uniknąć ponownego startu konwersji. Zwrócono uwagę na poprawne scalanie 12-bitowych danych z dwóch bajtów, przesuwając i maskując odpowiednie bity. Ostatecznie problemem okazało się błędne użycie funkcji ltoa do konwersji typu zmiennych, co powodowało zwracanie wartości zero. Po poprawieniu tego błędu odczyty zaczęły działać poprawnie. W dalszym etapie planowane jest uśrednianie i kalibracja wyników pomiarów napięcia.
Wygenerowane przez model językowy.
REKLAMA