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

[stm32] problem z konfiguracją zegara TIM2

13 Lis 2010 21:23 2947 11
  • Poziom 14  
    Witam,
    Próbując się posiłkować reference manualem (RM0008) oraz książką "Mikrokontrolery stm32 w praktyce" próbowałem odpalić okresowe wykonywanie przerwania na TIM2 i niestety nic z tego nie wyszło.
    Proszę o rade gdzie szukać błedu.

    Wygląda to tak:
    Konfiguracja NVIC
    Code:

    // Wlacz przerwanie od Timera 2
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);


    Konfiguracja portów i timera (przyłączenie do magistrali), btw dlaczego TIM2 nie da się podłączyć do APB2?
    Code:

    // Wlacz taktowanie GPIOE i GPIOC i TIM2
    RCC_APB2PeriphClockCmd( RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOC , ENABLE);



    uruchomienie timera
    Code:

    // startujemy timer 2
       TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;

       TIM_TimeBaseInitStruct.TIM_Period = 65535;
       TIM_TimeBaseInitStruct.TIM_Prescaler = 2000;
       TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
       TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

       TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);

    // kanał 1.
    #define CH1_PULSE 32000

       TIM_OCInitTypeDef TIM_OCInitStructure;
       TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
       TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //?
       TIM_OCInitStructure.TIM_Pulse = CH1_PULSE ;
       TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

       TIM_OC1Init(TIM2, &TIM_OCInitStructure);
       TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Disable);
       //TIM_ARRPreloadConfig(TIM2, ENABLE);

       // włączenie przerwań od timerów
       TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);

       // włączenie timera
       TIM_Cmd(TIM2, ENABLE);


    i funkcja obsługi przerwania zdefiniowana normalnie w pliku main.c. Swoją drogą, czy to jest jakaś naming convension, że ona się tak musi nazywać, bo jeśli nie to pasowało by podać gdzieś jej adres?
    Code:

    // * przerwanie od TIM2

    void TIM2_CC_IRQHandler(void)
    {
       // sprawdzenie czy przerwanie jest od pierwszego kanału
       if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET )
       {
          //czysczenie bitu przerwania
          TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

          // miganie ledem
          GPIO_WriteBit(GPIOE, GPIO_Pin_12, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_12)));

          // ustawienie rejestru przepełnienia
          TIM_SetCompare1(TIM2, TIM_GetCapture1(TIM1) + CH1_PULSE  );
       }

    }


    z góry dziękuje za pomoc.
    Krzysiek
  • Poziom 23  
    Napisałeś o konfiguracji portów a pokazałeś tylko włączenie taktowania. Trzeba by daną końcówkę skonfigurować jako out PP czy OD.
    Co do TIM2 i APB-skoro w krzemie niet takiego drucika to nijak go nie włączysz. Zajrzyj do datasheeta, tam jest schemat blokowy pokazujący połączenia wewnętrzne.
    Tak z ciekawości, czemu to ma służyć?
    Cytat:

    TIM_SetCompare1(TIM2, TIM_GetCapture1(TIM1) + CH1_PULSE );
  • Poziom 14  
    Witam,

    Konfiguracja portu E wygląda tak
    Code:

         // Konfiguracja portu E
         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 ;
         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

         GPIO_Init(GPIOE, &GPIO_InitStructure);



    Co do fragmentu
    Code:

    TIM_SetCompare1(TIM2, TIM_GetCapture1(TIM1) + CH1_PULSE );


    To oczywiście jest tam błąd powinno byc TIM2 zamiast TIM1, niemniej nadal nie działa :(

    To skopiowałem z książki, mam wrażenie że ta linijka ładuje kolejną wartość do kanału pierwszego przy której zostanie wywołane przerwanie. Dla ogólności brakuje tam pewnie dzielenia modulo, ale TIM2 zlicza do 65535 wobec czego tego nie trzeba. Jeśli się mylę to daj znać.

    pozdrawiam
    Krzysiek
  • Specjalista - Mikrokontrolery
    qczek napisał:
    Konfiguracja portów i timera (przyłączenie do magistrali), btw dlaczego TIM2 nie da się podłączyć do APB2?

    RCC nie słuszy do "łączenia" tylko do "włączania" - TIM2 jest na konkretnej magistrali i koniec, nie możesz sobie go "podłączyć" do innej.

    Cytat:
    Code:

    // Wlacz taktowanie GPIOE i GPIOC i TIM2
    RCC_APB2PeriphClockCmd( RCC_APB1Periph_TIM2 | RCC_APB2Periph_GPIOE | RCC_APB2Periph_GPIOC , ENABLE);

    Komendą dla APB2 zapewne nie da się włączyć niczego na APB1, nie sądzisz?

    Widzę, że biblioteka ST już odmóżdżyła cały świat...

    A port ma być ustawiony na PP albo OD, tyle że nie OUT, a ALT... Ale żeby to wiedzieć, to trzeba czytać manuala, a nie opis funkcji do durnej biblioteki.

    4\/3!!
  • Poziom 14  
    Dzięki za wskazówki, niestety ostatnio nie myślę za dobrze ;)
    Jeśli chodzi o ALT to masz namyśli alternate function opisane w manualu ?

    Jak teraz włączaczam przerwania TIM2 to program gdzieś skacze w maliny, pewnie trzeba jeszcze gdzieś ustawić jakiś wektor, niemniej pytanie gdzie????

    Pozdrawiam
    Krzysiek
  • Poziom 23  
    Mogę się mylić, ale w tym przykładzie kolega miga diodką wykorzystując GPIO a nie podpinając do wyjścia timera, więc gpio out pp może chyba być.
    Czy kol. qczek przypadkiem na koniec nie konfigurujesz ch1 w tim2 jako capture, czyli "łapiącego" i liczącego impulsy z zewnątrz?
    Cytat:

    TIM_SetCompare1(TIM2, TIM_GetCapture1(TIM1) + CH1_PULSE );

    Poza tym nie zauważyłem ustalenia źródła przerwania w tim2, czy przepełnienie licznika, czy któryś z kanałów, czy może coś innego.
    p.s.
    jednak jest:

    TIM_ITConfig(TIM2, TIM_IT_CC1, ENABLE);


    Musi być włączona generacja przerwania przez konkretny podzespół timer, jeden, bądź więcej, a w przerwaniu sprawdza się w rejestrze TIMx->SR, które ze zgłoszeń od tego timera akurat wywołało przerwanie i jego obsługę się wykonuje a flagę kasuje.

    Cytat:

    Jak teraz włączaczam przerwania TIM2 to program gdzieś skacze w maliny, pewnie trzeba jeszcze gdzieś ustawić jakiś wektor, niemniej pytanie gdzie????

    Skąd wiesz, debugujesz jakoś? Może skonfigurował się tim ch1 jako capture i czeka na impulsy?
  • Specjalista - Mikrokontrolery
  • Poziom 23  
    Cytat:

    Kod:

    // * przerwanie od TIM2

    void TIM2_CC_IRQHandler(void)
    {
    // sprawdzenie czy przerwanie jest od pierwszego kanału
    if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET )
    {
    //czysczenie bitu przerwania
    TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);

    // miganie ledem
    GPIO_WriteBit(GPIOE, GPIO_Pin_12, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOE, GPIO_Pin_12)));

    // ustawienie rejestru przepełnienia
    TIM_SetCompare1(TIM2, TIM_GetCapture1(TIM1) + CH1_PULSE );
    }

    }

    Jeśli dobrze widzę, to na koniec tego przerwania ustawiasz cc1 w tryb capture. Jeśli nie dostale impulsów to więcej od niego przerwania nie uświadczysz.
  • Poziom 14  
    Co do ustawiania w tryb capture to chyba nie ustawiam.
    Funkcja TIM_SetCompare1 ustawia po prostu rejestr CCR1 a wg manuala
    "CCR1[15:0]: Capture/Compare 1 value
    If channel CC1 is configured as output:
    CCR1 is the value to be loaded in the actual capture/compare 1 register (preload value).
    It is loaded permanently if the preload feature is not selected in the TIMx_CCMR1 register (bit
    OC1PE). Else the preload value is copied in the active capture/compare 1 register when an
    update event occurs.
    The active capture/compare register contains the value to be compared to the counter
    TIMx_CNT and signaled on OC1 output."

    ten rejestr jest wykorzystywany do porównania z wartością licznika.....
    no chyba ze mi się coś pierd....

    co do skakania w maliny to znalazłem pliczek stm32f10x_hd.s w którym były nazwy i okazało się że to jest TIM2_IRQHandler

    Co do konfiguracji wyjścia to alternative nie działa natomiast out_pp działa wyśmielicie.

    Tak że dioda mruga sobie :)

    dzięki za pomoc
    krzysiek
  • Poziom 14  
    Witam,
    Mam jeszcze jedno pytanko, czy pomimo tego, że Timer 2 jest podłączony do magistrali APB1 taktowanej zegarem 36MHz (max) to i tak na jego prescaler wchodzi sygnał 72Mhz? (CK_INT)

    pozdrawiam
    Krzysiek
  • Pomocny post
    Specjalista - Mikrokontrolery
  • Poziom 14  
    Dzięki
    To wszystko wyjaśnia

    The timer clock frequencies are automatically fixed by hardware. There are two cases:
    1. if the APB prescaler is 1, the timer clock frequencies are set to the same frequency as
    that of the APB domain to which the timers are connected.
    2. otherwise, they are set to twice (×2) the frequency of the APB domain to which the
    timers are connected.


    Pozdrawiam
    Krzysiek