2012-01-29 11:06 PM
(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);
2012-01-30 05:05 AM
TIM_TimeBaseStructure.TIM_Period = PreCalPeriod - 1;
2012-01-30 09:11 AM
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.MAJ2012-01-31 10:20 AM
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.2012-02-03 09:21 PM
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