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

[STM32] Konfiguracja SPI2. Działa tylko po resecie.

hamilton32 21 Gru 2011 20:22 2723 22
REKLAMA
  • #1 10289121
    hamilton32
    Poziom 11  
    Posty: 62
    Witam

    Mam dziwny problem z moim STM32.

    Układ składa się z mikrokontrolera i układu podłączonego do SPI2 (kostka ADS7843).

    1. Zasilanie wyłączone
    2. Włączam zasilanie
    3. Spi nie działa, wysyłam ramki ale w odpowiedzi dostaje śmieci (Nie mam peności czy spi wysyła cokolwiek)
    4. Reset mikrokontrolera (ADS7843 cały czas zasilany, nie resetuje sie)
    5. Wszystko działa poprawnie !!

    SPI2 Zaczyna się komunikować dopiero po resecie mikrokontrolera. Dodawałem opóźnienia, podćiągłem pin CS do plusa i ciągle to samo.

    void SPI2_Start(void)
    {
    /* GPIO INIT */
       HW_GPIO_Config(GPIOB, 10,(GPIO_MODE_50MHZ|GPIO_CNF_OUT_PP)); //CS
       HW_GPIO_Config(GPIOB, 13,(GPIO_MODE_50MHZ | GPIO_CNF_AF_PP )); //SCK
       HW_GPIO_Config(GPIOB, 14,(GPIO_MODE_IN    | GPIO_CNF_IN_FLO)); //MISO
       HW_GPIO_Config(GPIOB, 15,(GPIO_MODE_50MHZ | GPIO_CNF_AF_PP )); //MOSI
       TOUCH_CS_SET;
    
    /* SPI2 ON */
       SPI2->CR1 =  SPI_CR1_SSM  | SPI_CR1_SSI  |
    		        SPI_CR1_BR_2 | SPI_CR1_BR_1 |
    		        SPI_CR1_MSTR;
       SPI2->CR1 |= SPI_CR1_SPE;
    
    
    }


    uint8_t Touch_send_byte(uint8_t byte) //send control byte
    {
     while(SPI2->SR & (1<<7)); // while spi busy
     SPI2->DR = byte;
     while(SPI2->SR & (1<<7)); // while spi busy
    
     return 1;
    }
    
    uint8_t Touch_read_byte(void) 
    {
     uint8_t get;
     SPI2->DR = 0;
     while((SPI2->SR & (1<<0))==0); //RX not buffer empty
     get =  SPI2->DR;
     return get;
    }


    Po Resecie zawsze wszystko działa dobrze. Nie mam już pomysłu co może być nietak.
  • REKLAMA
  • #2 10289878
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    hamilton32 napisał:
    podćiągłem pin CS do plusa i ciągle to samo.


    Przecież CS ma być LOW żeby móc komunikować się z tym ADS'em.
    Sprawdzasz pin BUSY z ADS'a?
  • #3 10290026
    hamilton32
    Poziom 11  
    Posty: 62
    markosik20 napisał:


    Przecież CS ma być LOW żeby móc komunikować się z tym ADS'em.
    Sprawdzasz pin BUSY z ADS'a?



    Podczas komunikacji CS jest w stanie niskim. Podciągam go do plusa aby CS nie był w stanie niskim zanim SPI sie uruchomi, myślałem że to pododuje wysłanie jakiś śmieci.

    Na pin BUSY nie czekam. Mam programowe opóźnienie. Ale to raczej nie stanowi problemu ponieważ po resecie wszystko dziala idealnie
  • REKLAMA
  • #4 10290593
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Zamiast sprawdzać flagi busy od SPI to sprawdzaj te które trzeba - RXNE i TXE. Busy można (należy) sprawdzać przed przestawianiem CSa na stan nieaktywny.

    No i pokaż więcej kodu, a nie 3 funkcje.

    4\/3!!
  • REKLAMA
  • #5 10293765
    hamilton32
    Poziom 11  
    Posty: 62
    funkcja wywoływana w main():
    
    void Touch_Init(void)
    {
     SPI2_Start();
     TOUCH_CS_SET;
     TOUCH_CS_SET;
     Touch_read();
    }
    


    funkcja czytająca dane dotyku x i y
    
    punkt_t Touch_read(void)
    {
     punkt_t p;
     TOUCH_CS_CLR;
     delay_us(10);
     Touch_send_ctrl(TOUCH_DIR_X);
     delay_us(50);
     p.x = Touch_read_byte();
      Touch_send_ctrl(TOUCH_DIR_Y);
     delay_us(50);
     p.y = Touch_read_byte();
     delay_us(10);
     TOUCH_CS_SET;
     return p;
    }
    
    
    uint8_t Touch_send_ctrl(uint8_t dir) //send control byte
    {
     /* Bit7(MSB)  Bit6  Bit5  Bit4  Bit3   Bit2     Bit1  Bit0(LSB)
    	S          A2    A1    A0    MODE   SER/DFR  PD1   PD0       */
     if(TOUCH_DIR_X == dir)
     {
        Touch_send_byte(TOUCH_START     | TOUCH_8BIT | TOUCH_X
    		          | TOUCH_MODE_DIFF | TOUCH_PWD	);
     }
     else
     {
    	 Touch_send_byte(TOUCH_START     | TOUCH_8BIT | TOUCH_Y
        		       | TOUCH_MODE_DIFF | TOUCH_PWD );
     }
     return 1;
    }
    
    


    wywołanie dwukrotne funkcji Touch_Init() nie pomaga.
    Reset SPI i ponowne zainicjowanie też nie pomaga.
    Zmiana miejsca wywołania Touch_init() w main() też nie pomaga.
    Tylko reset pomaga w jakiś magiczny sposób.

    Dodatkowo Touch_read() wywoływana jest podczas przerwania od PEN_IRQ i po resecie działa dobrze. Bez resetu zaraz po zasileniu PEN_IRQ losowo zmienia stan.
    Przerwanie PEN_IRQ jest oczywiście uruchamiane dopiero po uruchomieniu SPI.
  • Pomocny post
    #7 10294321
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    Reasumując:
    1. Włączasz zasilanie = nie działa
    2. Wykonujesz reset STM'a = działa
    ?

    Mógłbyś jeszcze "main'a" pokazać, albo najlepiej odchudź kod do obsługi tylko SPI i wrzuć cały projekt.
  • #8 10295093
    hamilton32
    Poziom 11  
    Posty: 62
    markosik20 napisał:
    Reasumując:
    1. Włączasz zasilanie = nie działa
    2. Wykonujesz reset STM'a = działa
    ?

    Mógłbyś jeszcze "main'a" pokazać, albo najlepiej odchudź kod do obsługi tylko SPI i wrzuć cały projekt.


    dokładnie...

    Wydaje mi sie że SPI po uruchomieniu mikrokontrolera nic nie wysyła, dopiero po resecie. Nie mam oscyloskopu aby to potwierdzić.
    
    int main(void)
    {
       SystemInit(); //rcc init
    
       NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
       NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0);
       RCC_APB2PeriphClockCmd( RCC_APB2Periph_SPI1, ENABLE);
       RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP |RCC_APB1Periph_SPI2, ENABLE);  // Uruchomienie zegara
       HW_Init_GPIO();  // CS W stan wysoki
    
       Tim1_Init();  // timer 1 strart
       delay_ms(500);
       LCD_init_SPI1();  // uruchomienie wyświetlacza SPI1. TX only
       Touch_Init();   // Funkcja opisana powyżej
       Tim2_Init();     // timer do debouncingu dotyku
       HW_Init_EXTI();  // przerwanie EXTI dla PEN_IRQ
    
      while (1)
      {  }
    }
    
    
    

    SPI1 podłączone do wyświetlacza działa zawsze. ZMianieałem kolejność w funkci main() i czasami działa zaraz po włączeniu zasilania. Ale jest to zupełnie przypadkowe zachowanie bez logiki.
  • Pomocny post
    #9 10295210
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    No ubaw jest pierwszej klasy... Wrzucisz w końcu tyle kodu, żeby była w nim KOMPLETNA inicjalizacja wszystkiego? Przecież nikt tutaj nie wie, co jest w Twojej funkcji HW_Init_GPIO(), ani w pozostałych (System_Init()?), które mogą coś jednak zmieniać w SPI2 czy istotnych GPIO. A jeśli uważasz, że nic nie zmieniają, to zakomentuj je i potem wywal z tego co wrzucasz na forum.

    Dlaczego?

    A dlatego, że zwykle 3/4 tematów z tego typu problemami kończy się konkluzją autora, że sam znalazł błąd, bo gdzieś coś źle przestawił, zdefiniował, pomieszał, zapomniał, zmienił czy zaczarował. Twoje ewentualne zapewnienia, że "tam na pewno jest dobrze, nie będę wrzucał" nie są w przypadku problemów wiele warte.

    Reasumując:
    1. Wywal wszystko co niepotrzebne i niezwiązane z problemem (ustawianie priorytetów przerwań nie jest potrzebne i nie jest związane z problemem).
    2. Sprawdź, czy dalej objaw jest ten sam.
    3. Wrzuć WSZYSTKO na forum.

    4\/3!!
  • REKLAMA
  • #10 10295302
    hamilton32
    Poziom 11  
    Posty: 62
    System init mam jeszcze z tych głupich bibliotek ST. Uruchamia tylko zegary.

    HW_Init_GPIO
    ustawia wszytkie piny SPI2 i jakieś ledy. Najpierw ustawiam piny SPI2 jako out PP aby CS nie był w stanie nikim, a zegar musi być wysokim zanim uruchomię SPI.

    
    void HW_Init_GPIO(void)
    {
    	GPIO_InitTypeDef IO;
    	RCC->APB2ENR |= (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN);
    
    	/*** PORT B ****/
        HW_GPIO_Config(GPIOB, 10,(GPIO_MODE_50MHZ|GPIO_CNF_OUT_PP));
        HW_GPIO_Config(GPIOB, 13,(GPIO_MODE_50MHZ|GPIO_CNF_OUT_PP));
        HW_GPIO_Config(GPIOB, 1,(GPIO_MODE_50MHZ|GPIO_CNF_OUT_PP));
        HW_GPIO_Config(GPIOB, 2,(GPIO_MODE_50MHZ|GPIO_CNF_OUT_PP));
    
    	/*** PORT C ****/
    	/*** INIT STATE ***/
    	GPIOB->BRR = GPIO_Pin_13;
    	TOUCH_CS_SET;
    	LED1_ON;
    	LED2_ON;
    }


    Wysłałem prawie cały kod.
    Wykomentowałem już prawie wszystko. Jedyne co zostało to ten SystemInit, uruchomienie zegara SPI2 i GPIO i uruchomienie SPI i urichomienie Tomera_1 (jest potrzebny do funkcji delay_ms() .

    Jak mogę sprawdzić czy SPI2 cokolwiek wysyła?

    Jeśli będę cały czas wysyłał na spi (0x0F) i voltomierz na MOSI pokaże 1,6 V mogę uznać że się wysyła?

    Popołudniu zrobie testy. Jak nic nie wywnioskuję zamieszczę cały spakowany kod.

    Pozdrawiam i dziękuję za dotychczasową pomoc
  • #11 10295352
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Możesz spróbować wysyłać przez pewien czas same 0, potem same 0xFF, potem 0xAA - powinno to dać odpowiednio 0, VCC i VCC/2. Zamiast woltomierza może być dioda LED (z rezystorem).

    Możesz też próbować zrobić loopbacka (zewrzyj MOSI i MISO) i sprawdź czy odbierasz to co wysyłasz.

    4\/3!!
  • #12 10296001
    hamilton32
    Poziom 11  
    Posty: 62
    wygląda na to że SPI2 wysyła zawsze dane. Ale kostka ADS7843 zaczyna działać dopiero po resecie mikrokontrolera. Wygląda na to że problemem jest pin CS w satanie nikim zaraz po włączeniu zasilania zanim wystartuje mikrokontroler. Ale podciągniecie pinu CS do plusa (10k ohm) nie pomaga. Program ograniczony do minimum, ale przebieg programu zawsze jest taki sam niezależnie czy jest POWER ON czy RESET.
  • #14 10296087
    nsvinc
    Poziom 35  
    Posty: 2870
    Pomógł: 262
    Ocena: 88
    To nadal jest "ubaw pierwszej klasy" ;]
    Czyżbyś nie wiedział, że ten twój CS jest w stanie nieustalonym gdy procesor jest w resecie? Zewnętrzne podciąganie CS jest koniecznie w 99% przypadków...

    Skoro SPI zawsze wysyła dane, to problem nie raczy leżeć w procesorze, tylko w ADS7843. Może udostępnij nam schemat połączeń, lub chociaż rozpis, gdzie który pin scalaka jest podłączony pod procesor?

    CS nie ma prawa iść w stan niski w losowym momencie - musisz mieć nad tym pinem 100% kontroli. Jeśli istnieje chociażby jedna sytuacja, kiedy tak nie jest - proszisz się o problemy.

    Poza tym, nie komunikujesz się ze scalakiem w zalecany sposób. Nie widzę u ciebie czekania na zbocze opadające na pinie BUSY między wysłaniem bajtu kontrolnego a odbieranie m danych. Fig. 5 na stronie ósmej datasheeta się kłania.
    Uwierz, gdybyś kazał procesorowi komunikować się ze scalakiem tak jak to zalecają, nie miałbyś problemów.
  • #15 10297365
    hamilton32
    Poziom 11  
    Posty: 62
    pisałem powyżej że Mam zewnętrzny pull Up na pinie CS.

    Jaki jest sens czkania na pin bussy? Mam oczekiwanie zaprogramowane. Po resecie jakoś działa.

    połączenie
    DCLK <- PB13
    DOUT-> PB14
    DIN <- PB15
    BUSY ->
    CS <- PB10 | PullUp 10K
    PENIRQ -> PB11

    Moze ta kostka wymaga zminy stanu pinu CS ? Przebieg programu jest ten sam zawsze i po resecie działa ZAWSZE. Więc nie robie pewnie czegoś podczas uruchomienia... Nie pomaga nawet wykonaie kodu z main(), odczekanie 2 sekund i pownowne wykonanie kodu main().
  • #16 10298286
    markosik20
    Poziom 33  
    Posty: 2261
    Pomógł: 208
    Ocena: 147
    hamilton32 napisał:
    .. i po resecie działa ZAWSZE. Więc nie robie pewnie czegoś podczas uruchomienia...


    To zrób warunkowy programowy reset na końcu main'a skoro nie robisz tego "czegoś" podczas uruchomienia.
  • #18 10308275
    hamilton32
    Poziom 11  
    Posty: 62
    Freddie Chopin napisał:
    Zamiast tak cudować, to zrób jednak te timeouty...

    4\/3!!


    Timeouty są robione. Wysyłam tylko dane przez SPI co 100 ms jeśli PENIRQ jest w stanie niskim.

    Ale znalazłem inny BARDZO ciekawy trop.
    Zawsze jak inicjalizuję SPI2 to CPOL = 0 czyli linia zegarowa powinna być w stanie niskim kiedy nic nie wysyłam, a u mnie jest czasami W STANIE WYSOKIM zaraz po uruchomieniu SPI2 bez wysyłania czegokolwiek. I zauważyłem zależność że jeśli CLK jest w stanie wysokim to poprostu odbieram śmieci, a jeśli w stanie niskim to wszystko działa jak trzeba.
    Więc wina jednak jest po stronie mikrokontrolera (SPI). Nie rozumię dlaczego SCK po włączeniu SPI miałby być kiedykolwiek w stanie wysokim? Kiedy SPI wisi w powietrzu sprawa wygląda podobnie. :cry: coś tu nie gra
  • Pomocny post
    #19 10308342
    piti___
    Poziom 23  
    Posty: 623
    Pomógł: 67
    Ocena: 9
    Być może problemem jest inicjalizacja pinów z SPI ? w gpio_init ustawiasz CLK na wyjście (może ustawia tez 1).. i zaraz potem zmieniasz na AF_PP. Nie znam procesora ale na LPC miałem problemy z SPI gdy przez przypadek wyłączałem podciąganie lini SPI.

    Korzystam z TSC2046 (bardzo podobny układ) i nie sprawdzam busy. Co 20ms wywołuję funkcję:
    
    
    tsc2046_response_t read_tsc2046(void)
    {
      u8 i;
      u16 _y,_x,_z;
      _y = 0;
      _x = 0;
      _z = 0;
    
      tsc2046_response_t response;
    
    
      GPIO0->FIOCLR = (1<<16);
    
      for(i=0;i<PETLE;i++)
      {
        ts_txrx(Conv_Y);
        _y +=((u16)ts_txrx(0)<<5) | ((u16)ts_txrx(0)>>3);
      }
      response.y = _y/PETLE;
    
      for(i=0;i<PETLE;i++)
      {
      	ts_txrx(Conv_X);
        _x += ((u16)ts_txrx(0)<<5) | ((u16)ts_txrx(0)>>3);
      }
    
      response.x = _x/PETLE;
    
      for(i=0;i<PETLE;i++)
      {
     		ts_txrx(Conv_Z2);
        _z += ((u16)ts_txrx(0)<<5) | ((u16)ts_txrx(0)>>3);
      }
    
      response.z2 = _z/PETLE;
    
      GPIO0->FIOSET = (1<<16);
    
      return response;
    }
  • #20 10312267
    hamilton32
    Poziom 11  
    Posty: 62
    dzięki za zainteresowanie ale nie mam już pomysłu jak inaczej ustawić te piny.

    zaraz po ustawieniu pll i APB1/APB2 (tylko tu korzystam z biblioteki ST) ustawiam porty tak:
    void[b] HW_Init_GPIO[/b](void)
    {
      GPIO_InitTypeDef IO;
      RCC->APB2ENR |=
          (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN);
    
      /*** PORT B ****/
      //SPI2
      HW_GPIO_Config(GPIOB, TOUCH_CS_IO, (GPIO_MODE_50MHZ | GPIO_CNF_OUT_PP));   // CS
      HW_GPIO_Config(GPIOB, SPI2_SCLK_IO, (GPIO_MODE_50MHZ | GPIO_CNF_AF_PP));   //SCK
      HW_GPIO_Config(GPIOB, SPI2_MISO_IO, (GPIO_MODE_IN    | GPIO_CNF_IN_FLO));  //MISO
      HW_GPIO_Config(GPIOB, SPI2_MOSI_IO, (GPIO_MODE_50MHZ | GPIO_CNF_AF_PP));   //MOSI
    
      HW_GPIO_Config(GPIOB, LED1_IO, (GPIO_MODE_50MHZ | GPIO_CNF_OUT_PP));
      HW_GPIO_Config(GPIOB, LED2_IO, (GPIO_MODE_50MHZ | GPIO_CNF_OUT_PP));
      //EXTI
      HW_GPIO_Config(GPIOB, EXTI_TOUCH_IO, (GPIO_MODE_IN | GPIO_CNF_IN_PU));
    
      /*** PORT C ****/
      /*** INIT STATE ***/
      GPIOB->BRR = GPIO_Pin_13;
      TOUCH_CS_SET;
      LED1_OFF;
      LED2_OFF;
    }
    
    void [b]HW_GPIO_Config[/b](GPIO_TypeDef* GPIOx, uint8_t pin, uint8_t mode)
    {
      if (pin < 8)
      {
        GPIOx->CRL &= ~(GPIO_CR_MASK << (pin << 2));
        GPIOx->CRL |= (mode << (pin << 2));
      }
      else
      {
        GPIOx->CRH &= ~(GPIO_CR_MASK << ((pin - 8) << 2));
        GPIOx->CRH |= (mode << ((pin - 8) << 2));
      }
    
    }
    


    następnie włączam Timer aby mieć funkcje delay_ i następnie uruchamiam SPI

    
    void [b]SPI2_start[/b](void)
    {
      /* clock on */
      RCC->APB1ENR |= RCC_APB1ENR_SPI2EN;
      /* GPIO INIT */
      HW_GPIO_Config(GPIOB, SPI2_SCLK_IO, (GPIO_MODE_50MHZ | GPIO_CNF_AF_PP));   //SCK
      HW_GPIO_Config(GPIOB, SPI2_MISO_IO, (GPIO_MODE_IN    | GPIO_CNF_IN_FLO));  //MISO
      HW_GPIO_Config(GPIOB, SPI2_MOSI_IO, (GPIO_MODE_50MHZ | GPIO_CNF_AF_PP));   //MOSI
      TOUCH_CS_SET;
    
      /* SPI2 INIT */
      [b]SPI2->CR1 = SPI_CR1_SSM | SPI_CR1_SSI | SPI_CR1_BR_1| SPI_CR1_MSTR;
      SPI2->CR1 |= SPI_CR1_SPE;[/b]
    }
    



    jest to maksymalnie odchudony kod. NIe widzę powodu dla którego SCK miało by być w stanie wysokim, nawet zaraz po uruchomieniu SPI nie wysyłając niczego. Zmieniając kod i robiąc częste resety uC widzę że czasami nawet po resecie nie działa (SCK = 1) a po power on raz na 10 razy działa. Ale zmiany w kodzie powodujące takie zmiany w tej kwastii nie majlą logicznego powiązania.
  • #21 10312290
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Ale po co ty ustawiasz piny od SPI drugi raz? Przecież właśnie wtedy one przełączają się na chwilę w inny tryb (analogowe wejście)...

    4\/3!!
  • #22 10313450
    hamilton32
    Poziom 11  
    Posty: 62
    Freddie Chopin napisał:
    Ale po co ty ustawiasz piny od SPI drugi raz? Przecież właśnie wtedy one przełączają się na chwilę w inny tryb (analogowe wejście)...

    4\/3!!


    ten fakt niczego nie zmiania. Wykomentowałem ponowną konfigurację GPIO z inicjalizacji SPI2 i problem pozostał.

    moją ostatnią nadzieją jest zrobienie nowej płytki i zrobinie nowego projektu od początku który tylko ustawia SPI2. Jeśli to zawiedzie to sie poddam. Jaka jest szansa że uszkodzony jest mikrokontroler?
  • #23 10313482
    Freddie Chopin
    Specjalista - Mikrokontrolery
    Posty: 13336
    Pomógł: 1712
    Ocena: 870
    Szansa jest bardziej taka, że robisz z igły widły - problem ten da się obejść choćby robiąc jakieś timeouty, puszczając wstępnie jakąś serię nieznaczących danych itd. Piny po resecie mogą mieć generalnie dowolny stan, chcesz mieć jakiś super konkretny, to dajesz pullupy. Jeśli pullup na CS nie wystarcza, to znaczy że układ z którym chcesz gadać jest co najmniej "dziwny".

    4\/3!!

Podsumowanie tematu

✨ Użytkownik zgłasza problem z komunikacją SPI2 w mikrokontrolerze STM32, który działa poprawnie tylko po resecie, mimo że zasilanie ADS7843 jest ciągłe. Po włączeniu zasilania SPI2 nie wysyła danych, a po resecie wszystko działa prawidłowo. Użytkownik próbował różnych rozwiązań, takich jak podciąganie pinu CS do zasilania oraz dodawanie opóźnień, ale problem nadal występuje. W dyskusji zasugerowano sprawdzenie flag RXNE i TXE, a także wprowadzenie timeoutów oraz testowanie stanu pinu CS. Użytkownik zauważył, że linia zegarowa SPI (SCK) czasami jest w stanie wysokim po uruchomieniu, co może być przyczyną problemów z komunikacją. Wskazano również na konieczność poprawnej inicjalizacji pinów oraz ewentualne problemy z samym układem ADS7843.
Podsumowanie AI na podstawie dyskusji. Może zawierać błędy.
REKLAMA