Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

STM32F103RBT6 - Problem z taktowaniem GPIO

konradzisko 23 Wrz 2015 11:34 807 6
  • #1 23 Wrz 2015 11:34
    konradzisko
    Poziom 2  

    Witam wszystkich,
    Rozpocząłem swoją przygodę z mikrokontrolerami stm32 od najprostszego z możliwych programów, a mianowicie miganie diodą.
    Po rozkręceniu PLL do 72 MHz, postanowiłem zmieniać stan diody co około 1s(w pętli opoźniającej zliczałem zmienną "int i" do 72000000). Problem polega na tym, ze stan diody zmienia się nie co 1s, a co kilka sekund. Podkreślam, że jestem bardzo początkujący w świecie mikrokontrolerów i bardzo proszę o wskazanie mi ,w czym tkwi bład , bo wyczerpały mi się wszystkie pomysły,zwłaszcza, że program skopiowany jest z przykładów do książki "STM32 Aplikacje i ćwiczenia w języku C.

    Code:
    #include "stm32f10x.h"
    

    void GPIO_Config(void);
    void RCC_Config(void);
    void NVIC_Config(void);

    int main(void)
    {
     int i;

      //konfiguracja systemu
      RCC_Config();
      NVIC_Config();
      GPIO_Config();
      /*Tu nalezy umiescic ewentualne dalsze funkcje konfigurujace system*/
      GPIO_ResetBits(GPIOB, GPIO_Pin_1);

      while (1) {
        /*Tu nalezy umiescic glowny kod programu*/
        GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET);
        for(i = 0; i <72000000; i++);            //okolo 0.5s przy 72MHz
         GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);

         for(i = 0; i < 72000000; i++);
        GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_RESET);
      };
      return 0;
    }


    void RCC_Config(void)
    //konfigurowanie sygnalow taktujacych
    {
      ErrorStatus HSEStartUpStatus;                          //zmienna opisujaca rezultat uruchomienia HSE

      RCC_DeInit();                                          //Reset ustawien RCC
      RCC_HSEConfig(RCC_HSE_ON);                             //Wlaczenie HSE
      HSEStartUpStatus = RCC_WaitForHSEStartUp();            //Odczekaj az HSE bedzie gotowy
      if(HSEStartUpStatus == SUCCESS)
      {
        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);//
        FLASH_SetLatency(FLASH_Latency_2);                   //ustaw zwloke dla pamieci Flash; zaleznie od taktowania rdzenia
                                                             //0:<24MHz; 1:24~48MHz; 2:>48MHz




        RCC_HCLKConfig(RCC_SYSCLK_Div1);                     //ustaw HCLK=SYSCLK
        RCC_PCLK2Config(RCC_HCLK_Div1);                      //ustaw PCLK2=HCLK
        RCC_PCLK1Config(RCC_HCLK_Div2);                      //ustaw PCLK1=HCLK/2
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); //ustaw PLLCLK = HSE*9 czyli 8MHz * 9 = 72 MHz
        RCC_PLLCmd(ENABLE);                                  //wlacz PLL
        while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);  //odczekaj na poprawne uruchomienie PLL
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);           //ustaw PLL jako zrodlo sygnalu zegarowego
        while(RCC_GetSYSCLKSource() != 0x08);                //odczekaj az PLL bedzie sygnalem zegarowym systemu

      /*Tu nalezy umiescic kod zwiazany z konfiguracja sygnalow zegarowych potrzebnych w programie peryferiow*/
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);//wlacz taktowanie portu GPIO B

      } else {
      }
    }

    void NVIC_Config(void)
    {
    //Konfigurowanie kontrolera przerwan NVIC
    #ifdef  VECT_TAB_RAM
      // Jezeli tablica wektorow w RAM, to ustaw jej adres na 0x20000000
      NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
    #else  // VECT_TAB_FLASH
      // W przeciwnym wypadku ustaw na 0x08000000
      NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
    #endif
    }

    void GPIO_Config(void)
    {
      //konfigurowanie portow GPIO
      GPIO_InitTypeDef  GPIO_InitStructure;

      /*Tu nalezy umiescic kod zwiazany z konfiguracja poszczegolnych portow GPIO potrzebnych w programie*/
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //wyjscie push-pull
      GPIO_Init(GPIOB, &GPIO_InitStructure);
    }
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0 6
  • #2 23 Wrz 2015 11:54
    Freddie Chopin
    Specjalista - Mikrokontrolery

    Jedyny błąd jest w Twoich założeniach, że rozkazy z tego pseudo-opóźnienia wykonują się w jednym takcie zegara. Przy okazji w Twojej pętli nie wiadomo po co dwa razy pod rząd ustawiasz pin na stan niski, co też raczej nie służy precyzji odliczania czasu.

    2
  • #3 23 Wrz 2015 20:46
    Badmaneq
    Poziom 23  

    Nie znam się na stm32, ale może uC nie jest taktowany częstotliwością 72 MHz, być może błędna inicjalizacja PLL.
    Nie uczy się tworzyć delay'ów na konstrukcjach for ponieważ nie wiadomo jaki kod asemblera wygeneruje kompilator. Opóźnienia tworzy się przy pomocy timera.

    0
  • #4 23 Wrz 2015 20:58
    tmf
    Moderator Mikrokontrolery Projektowanie

    Nie tylko nie wiadomo co z takiej pętli zrobi kompilator, ale przy co raz bardziej zaawansowanych rdzeniach CPU nie wiadomo jak rdzeń potraktuje takie nic nie robiące instrukcje. Przykładem jest nop, który po prostu może zostać zignorowany przez CPU. Od opóźnień są timery.

    1
  • #5 23 Wrz 2015 22:32
    BlueDraco
    Specjalista - Mikrokontrolery

    Jak napisano wyżej, do odmierzania czasu służą timery. Pomyśl, ile instrukcji musi zawierać pętla, która inkrementuje zmienną, porównuje ją ze stałą i zamyka się lub nie. Na moje oko minimum trzy, a może 5 lub więcej. Skąd więc pomysł, że 72000000 obiegi takiej pętli miałyby zająć procesorowi 72000000 cykli zegara, skoro jeden obieg musi zająć tych cykli pewnie nie mniej niż 4 (skok na Cortex-M wykonuje się ciut wolniej niż inne instrukcje)?

    1
  • #7 25 Wrz 2015 09:12
    alagner
    Poziom 25  

    Skompiluj z O3 albo Os (teraz jest pewnie O0), wtedy stawiam dolary przeciw orzechom, że opóźnienie całkowicie Ci znikine ;)
    Jak już musisz robić opóźnienia w pętli to niech ta zmienna sterująca (i) będzie volatile.

    1