STM32神舟III号 驱动直流电机学习(二)

看到一篇讲pwm讲得比较详细的STM32的PWM精讲http://wenku.baidu.com/view/edcde519227916888486d710.html

原文地址:http://cache.baiducontent.com/c?m=9d78d513d98207f059edc07d0f179f310

实验内容:利用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。

效果图:  
通道1、2


通道3、4




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值