AnsweredAssumed Answered

1MHz timebase messing with PWM frequency

Question asked by digital_dreamer on Jan 30, 2012
Latest reply on Feb 4, 2012 by digital_dreamer

(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);


Outcomes