这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» STM32F103ZE学习笔记(TIM2生成4路不同占空比的PWM)

共19条 1/2 1 2 跳转至

STM32F103ZE学习笔记(TIM2生成4路不同占空比的PWM)

高工
2012-12-23 17:49:43 打赏
实验内容:利用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

晒晒我的板:



关键词: STM32F103ZE 学习 笔记 生成 不同

工程师
2012-12-23 18:45:43 打赏
2楼
学习~~~

高工
2012-12-23 20:03:11 打赏
3楼
一块学呗,遇到瓶颈也好商讨一下下。。。

院士
2012-12-23 22:40:14 打赏
4楼
表扬一下,有图有文有代码……

高工
2012-12-24 12:55:25 打赏
5楼
顶,效果不错~

高工
2012-12-24 19:33:57 打赏
6楼
多谢长期以来的无私帮助,感激不尽。。。

高工
2012-12-24 19:34:29 打赏
7楼
多谢支持,哈哈哈

高工
2012-12-24 19:35:55 打赏
8楼
多谢大家的鼓励,继续努力中。。。

菜鸟
2012-12-28 21:06:20 打赏
9楼

版主,佩服有没有CAN的试验?


院士
2012-12-29 22:49:10 打赏
10楼
这个CAN实验 我也在考虑中,需要外接隔离器件,目前还在计划、测试中……

共19条 1/2 1 2 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]