cancel
Showing results for 
Search instead for 
Did you mean: 

1MHz timebase messing with PWM frequency

digital_dreamer
Associate II
Posted on January 30, 2012 at 08:06

(I'm posting this ''again'' as it doesn't look like it posted. :-/)

Hi,

I've been using the PWM Output example for my PWM jobs. The timebase was setup as follows (with variables replaced with actual perimeters):

  PrescalerValue = ((168000000 /2) / 21000000) - 1;

  PreCalPeriod = 21000000 / 20000;

Now, all this works fine and dandy. I changed to a 6MHz timebase and everything continues as expected. However, I wanted to use a 1MHz timebase for rpm calculations, using the following:

  PrescalerValue = ((168000000 /2) / 1000000) - 1;

  PreCalPeriod = 1000000 / 20000;

I haven't actually tested the timebase for the 1MHz output, but the PWM output frequency is a little off. The oscilloscope shows 20.53KHz, instead of the 20.0KHz I had been getting. Is the a rounding error I've overlooked here? I know 168MHz is evenly divisible by 84 as the Prescaler. And, 1MHz is evenly divisible by the period (50). So, where am I getting this discrepancy?

Just to be sure, this 20KHz PWM output frequency is really no big deal at all. But, the error reveals I've missed something in my calculations and that is why I want to figure this out. Things like this keep me up at night. 😉

The following is the full code:

// Enable TIM3 and GPIOC clocks

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

// Configure PC6-PC9 pins as AF, Pull-Down

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;

GPIO_Init(GPIOC, &GPIO_InitStructure);

// Connect TIM3 pins to AF2 for each GPIO pin

GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_TIM3);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_TIM3);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource8, GPIO_AF_TIM3);

GPIO_PinAFConfig(GPIOC, GPIO_PinSource9, GPIO_AF_TIM3);

// Compute prescaler value for timebase

PrescalerValue = (uint16_t) ((SystemCoreClock /2) / 1000000) - 1;

PreCalPeriod = 1000000 / Freq;

// Setup timebase for TIM3

TIM_TimeBaseStructure.TIM_Period = PreCalPeriod;

TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;

TIM_TimeBaseStructure.TIM_ClockDivision = 0;

TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

// Initialize TIM3 for 4 channels

TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OCInitStructure.TIM_Pulse = (PreCalPeriod * Duty_Cycle) / 100;

TIM_OC1Init(TIM3, &TIM_OCInitStructure);

TIM_OC2Init(TIM3, &TIM_OCInitStructure);

TIM_OC3Init(TIM3, &TIM_OCInitStructure);

TIM_OC4Init(TIM3, &TIM_OCInitStructure);

// Enable TIM3 peripheral Preload register on CCR1 for 4 channels

TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);

TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

// Enable TIM3 peripheral Preload register on ARR.

TIM_ARRPreloadConfig(TIM3, ENABLE);

// Enable TIM3 counter

TIM_Cmd(TIM3, ENABLE);

4 REPLIES 4
Posted on January 30, 2012 at 14:05

TIM_TimeBaseStructure.TIM_Period = PreCalPeriod - 1;

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
digital_dreamer
Associate II
Posted on January 30, 2012 at 18:11

Yep, that was it. Thank you!

I decided to look at other examples with this in mind and I see it now, unfortunately after the fact.

However, I'm left with this one question: Why did it work without the ''-1'' for the other values? Or, am I'm missing something again?

Thanks, again, clive1. You're a great asset here.

MAJ

Posted on January 31, 2012 at 19:20

The period and prescale divide by N values are always set as N-1, ie counter go from 0 to N-1.

Depending on the prescale value, the impact of this on the output signal can be minimal, to more profound, but should be measurable.

The width can be set between 0 and N, where 0 is always off, and N is always on.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
digital_dreamer
Associate II
Posted on February 04, 2012 at 06:21

Thanks for that, clive1.

I see it now. The previous TIM_Period was 1050, where a ''-1'' would create a less than .1% change. The 1MHz timebase required a TIM_Period of 50, where ''-1'' would represent a 2% or 400Hz difference.

I absolutely love this STM32F4! Now, I'm ready to move on and start driving a LCD.

MAJ