Electronic – Understanding the the setup of a Timer on an STM32F10x

cmicrocontrollerstm32stm32f10x

I'm trying to understand how to correctly setup the timer on an STM32F10x.

The board is running with an external crystal of 16 MHz, and I'm using the PLL:

/* PLLCLK = 16MHz / 2 * 9 = 72 MHz */
RCC_PLLConfig(RCC_PLLSource_HSE_Div2, RCC_PLLMul_9);

so the board is running at 72Mhz. I'm configuring the timer as follows:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
TIM_TimeBaseInitTypeDef timerInitstructure;
timerInitstructure.TIM_Prescaler =72000-1;
timerInitstructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitstructure.TIM_Period=1;
timerInitstructure.TIM_ClockDivision = TIM_CKD_DIV1;
timerInitstructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(TIM3,&timerInitstructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3,ENABLE);

To make sure that I set the correct frequency I am toggling a pin using the interrupt, but when I measure with the scope I get 2.784 kHz. Can anyone tell me why I get this frequency?

Best Answer

I wrote up a longer answer, before I realized the simple solution. I'm including the full answer in case it's helpful.


The quick answer: The values passed into the TIM_TimeBaseInit() function are only 16-bit, so 69999 is an invalid value. You'll need to choose the period and prescaler such that they are both below 65536.

There is a second problem, however, so please continue reading :)


The detailed answer:

It looks like you're targeting a 1kHz (1ms) clock?

Here is the basic equation, where PSC is the prescaler and ARR is the period ("Auto Reload Register"):

(PSC+1)(ARR+1) = (EventTime)(ClkFreq)

For 1ms:

(PSC+1)(ARR+1) = (1ms)(72MHz) = 72000

Now, you can choose any set of values to make this true, as long as they don't exceed 16 bits each. I chose:

(PSC+1) = 2 and (ARR+1) = 36000,

which gives PSC = 1 and ARR = 35999.

Then finish setting up the clock as you have.

In your case, you choose ARR=1 and PSC=71999. Turning the equations around:

EventTime = (PSC+1)(ARR+1)/ClkFreq

EventTime = (1+1)(71999+1)/72MHz = 2ms, which isn't what you're looking for.

Of course, this isn't actually what you're getting either, because of the earlier-mentioned problem with the size of the prescaler.


Incidentally, as @ScottSeidman points out, often the timer is set up correctly but the clock itself isn't. The clock trees are surprisingly complicated! One way to verify the clocks is to use the RCC_MCOConfig() function (or see the RCC_CFGR register). They can be used to output the internal clocks directly onto the MCO pin.

Good luck!