Skocz do zawartości

[C] [STM32] Timer odmierza dwa razy dłuższy czas niż powinien


Tail_Gunner

Pomocna odpowiedź

Witam,

Mam problem z odpowiednim ustawieniem timera w STM32. Potrafię go skonfigurować i uruchomić, ale odlicza czas dwa razy dłuższy niż powinien.

Konfiguracja timera:

void Timer2_cgf(void){
RCC_APB1PeriphClockCmd(RCC_APB1ENR_TIM2EN,ENABLE);
TIM_TimeBaseInitTypeDef timer2;
TIM_TimeBaseStructInit(&timer2);
timer2.TIM_ClockDivision = TIM_CKD_DIV1;
timer2.TIM_CounterMode = TIM_CounterMode_Up;
timer2.TIM_Period=1000; //odlicz 1 ms
timer2.TIM_Prescaler=168;
TIM_TimeBaseInit(TIM2,&timer2);
TIM_Cmd(TIM2,ENABLE);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE); // włączenie przerwana od timera2

NVIC_InitTypeDef NVIC_InitStr;
NVIC_InitStr.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStr.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStr.NVIC_IRQChannelPreemptionPriority =0;
NVIC_InitStr.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStr);
}

Jesli dobrze rozumiem to tak ustawiony timer będzie wywoływał przerwanie co 1ms. Mam płytkę stm32f4-discovery. Maksymalna częstotliwość zegara to 168M. Stąd wartość preskalera = 168 i okresu = 1000;

Funkcja przerwania

void TIM2_IRQHandler(void){
TIM_ClearFlag(TIM2,TIM_IT_Update);
cnt++;
if(cnt>=1000){
	dioda++;
	GPIO_ResetBits(GPIOD,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
	if(dioda==1)	GPIO_SetBits(GPIOD,GPIO_Pin_12);
	if(dioda==2) 	GPIO_SetBits(GPIOD,GPIO_Pin_13);
	if(dioda==3)	GPIO_SetBits(GPIOD,GPIO_Pin_14);
	if(dioda==4)	GPIO_SetBits(GPIOD,GPIO_Pin_15);
	dioda=dioda%4;
	cnt=0;
}
}

Funkcja ta powinna przełączać diody co 1000 przerwań czyli co 1s. Tymczasem diody przełączają się do 2 sekundy

Wcześniej robiłem to samo na SysTick_Config(SystemCoreClock/1000); i wszystko działało poprawnie

void SysTick_Handler(void){
cnt++;
if(cnt>=1000){
	dioda++;
	GPIO_ResetBits(GPIOD,GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);
	if(dioda==1)	GPIO_SetBits(GPIOD,GPIO_Pin_12);
	if(dioda==2) 	GPIO_SetBits(GPIOD,GPIO_Pin_13);
	if(dioda==3)	GPIO_SetBits(GPIOD,GPIO_Pin_14);
	if(dioda==4)	GPIO_SetBits(GPIOD,GPIO_Pin_15);
	dioda=dioda%4;
	cnt=0;
}
}

Mógłbym oczywiście ustawić okres na 500 i cieszyć się "działającym" timerem 😃 ale chciałbym wiedzieć dlaczego mój program nie działa. Spotkał się ktoś z podobnym problemem albo wie ktoś gdzie robię błąd?

Link do komentarza
Share on other sites

Hm, a może system nie pracuje na 168MHz tylko dwa razy wolniej? SysTick_Config() o tym "wiedział" i odpowiednio konfigurował okres a jeśli robisz to ręcznie w timerze, nie ma żadnego dowiązania do SystemCoreClock i reszty ustawień drzewa zegarów i stąd rozbieżność. Jednak dużo bardziej prawdopodobne jest to, że timer ma po prostu inny zegar niż jądro. Przejrzyj ustawienia bloku RCC, timery są napędzane z innej domeny zegara i nie mogą być taktowane szybciej niż 84MHz (domena APB2) lub 48MHz (APB1). Podzielniki dla prescalerów tych domen ustawiasz w RCC_CFGR. Prawie na pewno timer 2 pracuje u Ciebie z 84MHz.

I jeszcze mała uwaga: jeśli ustawisz TIMx_ARR na wartość 1000, to timer będzie liczył od 0 do 1000 włącznie, a więc będzie przechodził przez 1001 stanów i przez tyle będzie dzielił zegar ze swojego prescalera.

Link do komentarza
Share on other sites

marek170 Dzięki za info, nie pomyślałem o tym, że częstotliwości peryferiów mogą się różnić. Za manualem:

"The maximum frequency of the AHB domain is168 MHz. The maximum allowed frequency of the high-speed APB2 domain is 84 MHz. The maximum allowed frequency of the low-speed APB1 domain is 42 MHz"

Co ciekawe timer2 jest na APB1 czyli jego maksymalna częstotliwość to 42MHz. W moim programie układ działał dwa razy wolniej niż powinien co sugeruje że timer2 pracował z 84MHz... Jutro sprawdzę wszystko jeszcze raz.

Treker Dzięki za link, wrócę do kursu jak będę miał trochę czasu. Puki co przejrzałem do pobieżnie i wygląda ciekawie. Nie zauważyłem tylko opisu działania zegarów w STM32. Szkoda bo właśnie to sprawia mi największą trudność przy przejściu z Atmegi.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...