Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

[STM32][C] ARM Cortex - SPI dane dluzsze niz 16b

hardtmuth 28 Mar 2010 19:36 3281 7
Computer Controls
  • #1
    hardtmuth
    Level 20  
    Potrzebuje czytac dane z adc zewnetrznego, lacznie 32 bity.

    Code:

    void spi_init(void){

       GPIO_InitTypeDef GPIO_InitStructure;
       SPI_InitTypeDef SPI_InitStructure;

       GPIO_InitStructure.GPIO_Pin = /*GPIO_Pin_12 |*/ GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
       GPIO_Init(GPIOB, &GPIO_InitStructure);

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
       GPIO_Init(GPIOB, &GPIO_InitStructure);

       GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
       GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
       GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
       GPIO_Init(GPIOB, &GPIO_InitStructure);


       RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);

       SPI_I2S_DeInit(SPI2);

       SPI_StructInit(&SPI_InitStructure);
       SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
       SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
       SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
       SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
       SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
       SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
       SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
       SPI_InitStructure.SPI_CRCPolynomial = 7;
       SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_32;


       SPI_Init(SPI2,&SPI_InitStructure);
       SPI_Cmd(SPI2,ENABLE);
    }


    i uzycie:

    Code:

    GPIOB->BRR = 1<<12; // CS
       while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
       SPI_I2S_SendData(SPI2, 0x0000); // Send SPI1 data
       while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);     
       buf1 = SPI_I2S_ReceiveData(SPI2); // Read SPIz received data
       while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
       SPI_I2S_SendData(SPI2, 0x0000); // Send SPI1 data
       while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);     
       buf2 = 0;
       buf2 = SPI_I2S_ReceiveData(SPI2); // Read SPIz received data
       
       /*if(SPI2->SR & 0x0040){
          buf2=buf2;

       }*/
       GPIOB->BSRR = 1<<12;


    Na oscyloskopie widze prawidlowa transmisje, lecz do buf1 i buf2 wpisuje te same wartosci - jedynie pierwsze 16b, ktore ADC zwraca. Dane odebrane zgadzaja sie z tym co widze na oscyloskopie, wiec teoretycznie mam te 16b, ale przydaloby sie uzyskac wieksza rozdzielczosc przetwornika...

    Pewnie da sie to zrealizowac przy pomocy DMA, ale czy ktos ma pomysl jak uzyskac te 32b bez DMA.
  • Computer Controls
  • #2
    kred
    Level 19  
    Nie miałem do czynienia z STM32, ale co ta linia robi:
    Code:
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
    ?
  • Computer Controls
  • #3
    hardtmuth
    Level 20  
    Ustala dlugosc danych, nie ma opcji 32b, nie ma tak latwo;)

    EDIT: Teraz sprawdzielem i widze, ze mam OVR (overun) czyli nadchodza kolejne dane a jak ich nie odczytuje. Jaki moze byc powod, gdzie mam zla kolejnosc polecen lub cos zle robie? Zmniejszylem predkosc zegara spi do 250 kHz do 500 kHz i to samo.

    Dosc pilnie potrzebuje pomocy:)
  • #4
    SnowBizz
    Level 14  
    Podaj model przetwornika..
    Komenda 0x0000 inicjuje start konwersji? Jeśli tak to buf1 i buf2 zawiera praktycznie te same dane.. Bo odczytujesz tylko 16b i inicjujesz start od nowa i pobierasz znów tylko 16b..

    Może powinno być tak:
    ....
    SPI_I2S_SendData(SPI2, 0x0000); // Send SPI1 data
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);
    buf1 = SPI_I2S_ReceiveData(SPI2); // Read SPIz received data
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    buf2 = SPI_I2S_ReceiveData(SPI2); // Read SPIz received data
    while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
    ...

    Ale bez noty ADC ciężko coś wymyślić, bo nie wiadomo jak wygląda ramka danych.. Czy ADC porostu napiera pod rząd te 32b, czy może w dwóch połówkach po 16b a między nimi musi iść jakaś komenda..
  • #5
    hardtmuth
    Level 20  
    LTC2442, obojetnie co mu wysle, zawsze bedzie robil przetwarzanie i czy 0000 wysle czy cos innego to jedynie parametry zmienie.

    Komenda sterujaca ma niecale 16b, reszta idzie jako zera by wyzwolic zegar dla spi. Jak pisalem na oscyloskopie mam ciagle 32b zegara i danych. To mikroprocesor nie odbiera tego drugiego slowa (ustawia bit OVR w rejestrze statusu SPI). Tu jest problem, ale czy da sie go obejsc BEZ dma?
  • #6
    Freddie Chopin
    MCUs specialist
    Odczytaj dane normalnie, a nie przez te funkcje które nie-wiadomo-co robią...

    Upewnij się, że nie masz jakiegoś błędu ZANIM w ogóle zaczynasz coś wysyłać...

    Po co ustawiasz cokolwiek od CRC w inicjalizacji, skoro z tego nie korzystasz, nie wiadomo też co robi z tym ta fantastyczna biblioteka? Może wysyła sumę CRC po każdej transmisji?

    4\/3!!
  • #7
    hardtmuth
    Level 20  
    Sprobuje dzis bezposrednio jeszcze odczytac, dobry pomysl, moze cos sie zmieni. CRC inicjalizuje sie, ale jest wylaczone mimo to.

    Na osc transmisja w dwie strony jest prawidlowa, jak wyslam dwie komendy kazda 16b 0x0000 to tak wysylam, bo sprawdzilem na osc.
  • #8
    hardtmuth
    Level 20  
    Dodalem na wypadek przed odczytem 3-krotne odczytanie rejestru DR, by wyzerowane zostaly poprzednie bledy. Dodatkowo przepisalem calosc na bezposredni dostep do rejestrow i... ruszyl. ADC czyta prawidlowo, na biurku z wiszacymi przewodami udalo uzyskac sie efektywna rozdzielczosc 19 bitow:). Dziekuje za wszystkie rady. Chyba czas zaczac rezygnowac z pomocy biblioteki. Troche mnie to zaskakuje, bo w tym funkcjach od stm`a jedynie nadmiarowe bylo:
    - funkcja assert od sprawdzania poprawnosci danych
    - samo wywolanie funkcji, a nie odczyt bezposrednio z rejestru

    Czy takie cos moglo az tak pogorszyc szybkosc, czy sposob obslugi rejestrow, ze procesor nie nadazal z odbiorem? Szczegolnie, ze bledy byly i przy SCK 250 kHz i przy 1,1MHz. Dziwne.

    Jeszcze raz dzieki za rady.

    dla potomnych, by bylo im latwiej:
    Code:

    GPIOB->BRR = 1<<12;
    dummy = SPI2->DR;
    dummy = SPI2->DR;
    dummy = SPI2->DR;

    while((SPI2->SR & 0x0002) == 0){}
    SPI2->DR = cmd;
    while((SPI2->SR & 0x0001) == 0){}
    buf1 = SPI2->DR;
    while((SPI2->SR & 0x0002) == 0){}
    SPI2->DR = 0x0000;
    while((SPI2->SR & 0x0001) == 0){}
    buf2 = SPI2->DR;

    GPIOB->BSRR = 1<<12;


    TEMAT DO ZAMKNIECIA