搜索
bottom↓
回复: 47

九九的STM32笔记(二)TIM模块产生PWM

[复制链接]

出0入0汤圆

发表于 2009-2-18 19:25:19 | 显示全部楼层 |阅读模式
这个是STM32的PWM输出模式,STM32的TIM1模块是增强型的定时器模块,天生就是为电机控制而生,可以产生3组6路PWM,同时每组2路PWM为互补,并可以带有死区,可以用来驱动H桥。
  下面的代码,是利用TIM1模块的1、2通道产生一共4路PWM的代码例子,类似代码也可以参考ST的固件库中相应example
C语言: TIM1模块产生PWM,带死区
   
//Step1.开启TIM和相应端口时钟
//启动GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | \
                       RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD,\
                       ENABLE);
//启动AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//启动TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

//Step2. GPIO做相应设置,为AF输出
//PA.8/9口设置为TIM1的OC1输出口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//PB.13/14口设置为TIM1_CH1N和TIM1_CH2N输出口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

//Step3. TIM模块初始化
void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;
    TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

    //TIM1基本计数器设置(设置PWM频率)
    //频率=TIM1_CLK/(ARR+1)
    TIM_BaseInitStructure.TIM_Period = 1000-1;
    TIM_BaseInitStructure.TIM_Prescaler = 72-1;
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);
    //启用ARR的影子寄存器(直到产生更新事件才更改设置)
    TIM_ARRPreloadConfig(TIM1, ENABLE);


    //TIM1_OC1模块设置(设置1通道占空比)
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
    TIM_OCInitStructure.TIM_Pulse = 120;
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);
    //启用CCR1寄存器的影子寄存器(直到产生更新事件才更改设置)
    TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

    //TIM2_OC2模块设置(设置2通道占空比)
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = 680;
    TIM_OC2Init(TIM1, &TIM_OCInitStructure);
    //启用CCR2寄存器的影子寄存器(直到产生更新事件才更改设置)
    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
   
    //死区设置
    TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
    TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
    TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
    TIM_BDTRInitStructure.TIM_DeadTime = 0x90;  //这里调整死区大小0-0xff
    TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
    TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
    TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
    TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
   
    //TIM1开启
    TIM_Cmd(TIM1, ENABLE);
    //TIM1_OC通道输出PWM(一定要加)
    TIM_CtrlPWMOutputs(TIM1, ENABLE);

}
  
  其实,PWM模块还可以有很多花样可以玩,比方在异常时(如CPU时钟有问题),可以紧急关闭输出,以免发生电路烧毁等严重事故。

我的博客中本文的地址,内有语法高亮的代码,方便阅读

出0入0汤圆

发表于 2009-5-18 13:24:55 | 显示全部楼层
帮了大忙了,谢!

出0入0汤圆

发表于 2009-7-7 11:52:37 | 显示全部楼层
可不可以搞个TIM3 4 的PWM啊?我搞了很久都没PWM出来。

出0入0汤圆

发表于 2009-7-8 15:23:40 | 显示全部楼层
我最近也在研究TIM这一块,你的刹车设置那里有点看不懂,TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
这不是失能了刹车输入吗?

出0入0汤圆

发表于 2009-8-12 13:55:29 | 显示全部楼层
在吗???我试着用这你这个配置怎么没PWM输出呢??

出0入0汤圆

发表于 2009-8-12 13:55:54 | 显示全部楼层
大侠们帮帮忙呀???

出0入0汤圆

发表于 2009-8-15 00:39:22 | 显示全部楼层
老大...你有没有测试过你的程序再放出来...很害人的啊...

出0入0汤圆

发表于 2009-8-15 00:46:05 | 显示全部楼层
在V2.03里的原形:
/* TIM Output Compare Init structure definition */
typedef struct
{
  u16 TIM_OCMode;
  u16 TIM_OutputState;
  u16 TIM_OutputNState;
  u16 TIM_Pulse;
  u16 TIM_OCPolarity;
  u16 TIM_OCNPolarity;
  u16 TIM_OCIdleState;  // 这个没设
  u16 TIM_OCNIdleState; // 这个没设
} TIM_OCInitTypeDef;

加上

    TIM_OCInitStructure.TIM1_OCIdleState = ?;    //
    TIM_OCInitStructure.TIM1_OCNIdleState = ?; //

设置不完整少了这两句....不然没PWM输出.........

出0入0汤圆

发表于 2010-2-6 10:52:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-17 17:41:58 | 显示全部楼层
//TIM1基本计数器设置(设置PWM频率)
    //频率=TIM1_CLK/(ARR+1)
    TIM_BaseInitStructure.TIM_Period = 1000-1;
    TIM_BaseInitStructure.TIM_Prescaler = 72-1;
请问这里的1000-1
和72-1
分别是装载计数和分频 不解的事为什么都要减1?
谢谢

出0入0汤圆

发表于 2010-3-21 21:37:27 | 显示全部楼层
回复【9楼】huchengxtu 费米机器
-----------------------------------------------------------------------

TIMx的计数器到时频率为TIMxCLK/(Prescaler+1),这里加1,前面初值自然要减1啊!


TIM_BaseInitStructure.TIM_Period是最大的计数值,考虑到从0开始故而减1的吧!

出0入0汤圆

发表于 2010-8-15 02:59:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-8-24 10:49:57 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-7 09:26:33 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-7-9 19:54:09 | 显示全部楼层
不错,MARK!

出0入0汤圆

发表于 2011-7-9 20:51:24 | 显示全部楼层
我刚调试完一款电机H桥驱动,本来想利用单片机的pwm模块的,但是pwm不是互补的,用起来虽然简单,但我觉得还是用定时器更好,定时器可以加死区,我初步理解到,IR2103是利用同侧下管导通的时候来充电的,对侧下管开通,通过电机线圈来充电效率很低,所以用定时器做互补pwm能方便的控制上管导通然后下管导通充电和续流;不过我电机转速几千转,用1μF的电容足够维持一次导通时间了。

出0入0汤圆

发表于 2011-7-10 08:26:16 | 显示全部楼层
非常有意义

出0入8汤圆

发表于 2011-7-14 08:39:54 | 显示全部楼层
谢谢LZ,学习了!

出0入0汤圆

发表于 2011-8-26 19:02:58 | 显示全部楼层
测试过了,好用!

出0入0汤圆

发表于 2011-9-16 13:28:59 | 显示全部楼层
mark pwm

出0入0汤圆

发表于 2011-12-20 21:07:57 | 显示全部楼层
学习了

出0入0汤圆

发表于 2011-12-24 13:55:17 | 显示全部楼层
好东西,先学习了。

出0入0汤圆

发表于 2012-2-15 14:03:12 | 显示全部楼层
MK

出0入0汤圆

发表于 2012-2-16 10:13:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-3-31 11:36:56 | 显示全部楼层
正好能够用得上,谢谢!

出0入0汤圆

发表于 2012-4-12 21:46:37 | 显示全部楼层
谢谢楼主奉献

出0入0汤圆

发表于 2012-5-7 18:59:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-6-8 08:49:50 | 显示全部楼层
学习中。。。

出0入0汤圆

发表于 2012-6-8 14:28:38 | 显示全部楼层
对于我们这种入门级的来说是个天大的好事呀,我们只要求简单的东西。在这里谢谢了。

出0入0汤圆

发表于 2012-6-9 17:30:16 | 显示全部楼层
PWM最大输出频率可以达到多少?

出0入0汤圆

发表于 2012-8-13 17:42:52 | 显示全部楼层
不知道为什么CH1N与CH2N没有PWM输出。

出0入0汤圆

发表于 2012-8-14 13:46:46 | 显示全部楼层
值得好好学习!

出0入0汤圆

发表于 2012-9-5 21:47:14 | 显示全部楼层
mark                  

出10入0汤圆

发表于 2012-11-23 15:28:15 | 显示全部楼层
huchengxtu 发表于 2010-3-17 17:41
//TIM1基本计数器设置(设置PWM频率)
    //频率=TIM1_CLK/(ARR+1)
    TIM_BaseInitStructure.TIM_Peri ...

因为是0 开始 不是1开始

出0入0汤圆

发表于 2013-1-23 09:41:47 | 显示全部楼层
先留着了,谢谢。。。。

出0入0汤圆

发表于 2013-4-27 23:29:39 | 显示全部楼层
弱弱的问一句 那个电路怎么接。。能输出波形但不知道怎么控制h桥。。

出0入0汤圆

发表于 2014-2-14 17:17:06 | 显示全部楼层
MARK............

出0入0汤圆

发表于 2014-7-21 16:04:28 | 显示全部楼层
标记一下,好文

出0入0汤圆

发表于 2014-10-3 16:00:30 | 显示全部楼层
收好收好

出0入0汤圆

发表于 2015-3-11 22:21:39 | 显示全部楼层
正好需要

出0入0汤圆

发表于 2015-4-10 08:40:10 | 显示全部楼层
我想问一句,如何在运动过程中用TIM_SetCompare来控制互补PWM呢?是分别设为原先的50%,然后一个正,一个负么?

出0入0汤圆

发表于 2015-7-11 10:35:42 | 显示全部楼层
pwm.................
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-5 08:26

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表