实验内容:利用STM32的一个通用定时器(TIM2)产生4路频率相同(1KHz)占空比不同的PWM。Ch1占空比75%,Ch2占空比50%,Ch3占空比25%,Ch4占空比10%。四路输出分别对应PA端口的PA0,PA1,PA2,PA3。
实验目的:掌握通用定时器的基本应用。(PWM的频率和占空比的计算)
STM32的定时器是个强大的模块,定时器使用的频率也是很高的,定时器可以做一些基本的定时,还可以做PWM输出或者输入捕获功能。
补充一个前期时钟源问题:
名为TIMx的定时器有8个,其中TIM1和TIM8挂在APB2总线上,而TIM2-TIM7则挂在APB1总线上。其中TIM1&TIM8称为高级控制定时器. APB2可以工作在72MHz下,而APB1最大是36MHz。
定时器的时钟不是直接来自APB1或APB2,而是来自于输入为APB1或APB2的一个倍频器。(这个问题纳闷了好久才找到的,主要是没有在意时钟树,唉!)
下面以定时器2~7的时钟说明这个倍频器的作用:当APB1的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB1的频率;当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1的频率两倍。
假定AHB=36MHz,因为APB1允许的最大频率为36MHz,所以APB1的预分频系数可以取任意数值;当预分频系数=1时,APB1=36MHz,TIM2~7的时钟频率=36MHz(倍频器不起作用);当预分频系数=2时,APB1=18MHz,在倍频器的作用下,TIM2~7的时钟频率=36MHz。
有人会问,既然需要TIM2~7的时钟频率=36MHz,为什么不直接取APB1的预分频系数=1?答案是:APB1不但要为TIM2~7提供时钟,而且还要为其它外设提供时钟;设置这个倍频器可以在保证其它外设使用较低时钟频率时,TIM2~7仍能得到较高的时钟频率。
再举个例子:当AHB=72MHz时,APB1的预分频系数必须大于2,因为APB1的最大频率只能为36MHz。如果APB1的预分频系数=2,则因为这个倍频器,TIM2~7仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设计这个倍频器的初衷。
一下是定时器的配置代码:
/*使用一个定时器产生4路不同占空比的PWM波型 */
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE); //打开定时器时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
//定时器2 设置 360分频 1KHz 向上计数
TIM_TimeBaseStructure.TIM_Period =199; //1KHz,16位的值,最大65536
TIM_TimeBaseStructure.TIM_Prescaler =359; //360分频 即为200KHz,16位的值,最大65536
TIM_TimeBaseStructure.TIM_ClockDivision =0x00; //时钟分频系数,不分频
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); //初始化定时器
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //主定时器TIM2为PWM1模式
TIM_OCInitStructure.TIM_OutputState =TIM_OutputState_Enable;//使能输出比较状态
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
//ch1 配置项
TIM_OCInitStructure.TIM_Pulse = 150;
TIM_OC1Init(TIM2, & TIM_OCInitStructure); //ch1占空比75%
TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能的预装载寄存器
//ch2 配置项
TIM_OCInitStructure.TIM_Pulse = 100;
TIM_OC2Init(TIM2, & TIM_OCInitStructure); //ch2占空比50%
TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能的预装载寄存器
//ch3 配置项
TIM_OCInitStructure.TIM_Pulse = 25;
TIM_OC3Init(TIM2, & TIM_OCInitStructure); //ch3占空比25%
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能的预装载寄存器
//ch4 配置项
TIM_OCInitStructure.TIM_Pulse = 10;
TIM_OC4Init(TIM2, & TIM_OCInitStructure); //ch4占空比10%
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable); //使能的预装载寄存器
TIM_ARRPreloadConfig(TIM2,ENABLE); //使能TIM2在ARR上的预装载寄存器
TIM_ITConfig(TIM2,TIM_IT_CC1,ENABLE); //开定时器中断
TIM_CtrlPWMOutputs(TIM2,ENABLE); //使能TIM2的外设的主输出
TIM_Cmd(TIM2,ENABLE); //使能定时器2
}
一下说一下PWM频率的计算问题:
分频值=TIM_TimeBaseStructure.TIM_Prescaler +1,所以如果要分360分频,只要将TIM_Prescaler=359即可。
//定时器2 设置 360分频 1KHz 向上计数
TIM_TimeBaseStructure.TIM_Period =199; //1KHz,16位的值,最大65536
TIM_TimeBaseStructure.TIM_Prescaler =359; //360分频 即为200KHz,16位的值,最大65536
PWM频率(1KHz)=TIM2时钟/( TIM_Prescaler+1)*(TIM_Period+1);所以:TIM2时钟=72M;TIM_Period =199; TIM_Prescaler =359。
工程文件:
tim1_test.zip
效果图:
通道1、2
通道3、4
晒晒我的板: