已亲测,可以实现。
第一步:配置相关管脚输出,比如我的是配置到PB9,使用的是定时器4的第四通道。
void Pwm_Gpio_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
/*GPIOB_Pin_9, TIM4_Channel4 PWM*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_TIM4);//GPIOB_Pin9 TIM4_Ch4N,
}
第二步:配置定时器。
2.配置定时器:首先是像51单片机一样需要给出定时器一个初始值。而stm32的时钟比51的复杂。我们的STM32的定时器4使用的是APB1的时钟(使用APB1时钟有TIM2, TIM3 , TIM4 ,TIM5 , TIM6 ,TIM7,TIM12,TIM13,TIM14这些,最大频率为60MHZ。使用APB2时钟的有TIM1,TIM8最大的频率为120MHZ)。
2-1:当我们想配置我们的时钟频率为20000000hz。我们就需要设置预分频系数TIM_Prescaler ,从而使得高频率降到我们需要的频率。通过公式Prescaler = (TIM4CLK / TIM4 counter clock) - 1。我们的主时钟为120MHZ,APB1时钟是主时钟的2分频为60MHZ。所以TIM4CLK 是60MHZ。我们需要的TIM4 counter clock为20MHZ,所以得出我们的预分频系数Prescaler 为2,这样就可以取得TIM4的时钟输入频率为20MHZ了。
2-2:我们已经获得时钟频率,那么如何设置才可以让定时器出我们需要的定时呢?这个很简单,就像我们的51单片机一样,有了定时器的时钟,我们就知道他运算一次是多长时间,我们需要定时多久,就是要他运行多少次。举个例子:我们需要0.5秒的定时,而我们的定时器时钟为20MHZ。那么运行一次是1/20MHZ=0.05us。所以我们定时0.5秒需要定时器运行0.5/0.05us=10000000次。那么我们把计数寄存器(对于变量为TIM_Period )赋值为10000000,这样定时器定时为0.5秒了。
在我们需要向定时器里面填入初值,就可以设定频率。
2-3:这里还有一个参数需要配置,就是计数的模式,这里选择是向上计数模式。通俗点讲就是从0开始计数,计数到设定的初值TIM_Period 就产生一个事件(终端或者其他)。
2-4:执行TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);到目前为止定时器已经配置好了。
第三步:设置PWM
3-1.TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;设置PWM模式(有PWM1和PWM2模式,两个模式刚好相反)具体看《STM32中文参考手册》。
3-2.配置TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;以便和计数器比较产生PWM:
3-3.配置TIM_OCInitStructure.TIM_Pulse = 333;//设置占空比; 占空比 = [TIM_Pulse/TIM_Period)* 100 = 50%。
3-4.配置TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置有效极性,也就是设置比较输出的有效
电平。
详细见代码:
void Time4_Config(void)
{
/* -----------------------------------------------------------------------
TIM4 Configuration: generate 4 PWM signals with 4 different duty cycles.
In this example TIM4 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
since APB1 prescaler is different from 1.
TIM3CLK = 2 * PCLK1
PCLK1 = HCLK / 4
=> TIM4CLK = HCLK / 2 = SystemCoreClock /2
To get TIM4 counter clock at 20 MHz, the prescaler is computed as follows:
Prescaler = (TIM4CLK / TIM4 counter clock) - 1
Prescaler = ((SystemCoreClock /2) /20 MHz) - 1
To get TIM4 output clock at 30 KHz, the period (ARR)) is computed as follows:
ARR = (TIM4 counter clock / TIM4 output clock) - 1= 665
TIM4 Channel1 duty cycle = (TIM4_CCR1[TIM_Pulse]/ TIM4_ARR[TIM_Period])* 100 = 50%
----------------------------------------------------------------------- */
u32 PrescalerValue = 0;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//时能定时器时钟4
TIM_DeInit(TIM4);
/* Compute the prescaler value */
PrescalerValue = (uint16_t) ((120000000/2) / 20000000) - 1;
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 665;//ARR 计数初值设置PWM频率计数初值
TIM_TimeBaseStructure.TIM_Prescaler = PrescalerValue;//PSC 设置用来作为TIMx时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
/* PWM1 Mode configuration: Channel4 */
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 333;//设置占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置有效极性,也就是设置比较输出的有效电平。
TIM_OC4Init(TIM4, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM4, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM4, ENABLE);
/* TIM4 enable counter */
TIM_Cmd(TIM4, ENABLE);
/*
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM4, ENABLE);
TIM_CtrlPWMOutputs(TIM4, ENABLE);
*/
}