搜索
bottom↓
回复: 51

九九的STM32笔记(一)TIM模块定时器向上溢出 & 输出比较

[复制链接]

出0入0汤圆

发表于 2009-2-18 19:23:51 | 显示全部楼层 |阅读模式
九九的STM32笔记(一)TIM模块定时器向上溢出 & 输出比较

首先我们必须肯定ST公司的实力,也承认STM32的确是一款非常不错的Cortex-M3核单片机,但是,他的手册实在是让人觉得无法理解,尤其是其中的TIM模块,没有条理可言,看了两天几乎还是不知所云,让人很是郁闷。同时配套的固件库的说明也很难和手册上的寄存器对应起来,研究起来非常费劲!功能强大倒是真的,但至少也应该配套一个让人看的明白的说明吧~~
  两天时间研究了STM32定时器的最最基础的部分,把定时器最基础的两个功能实现了,余下的功能有待继续学习。
  首先有一点需要注意:FWLib固件库目前的最新版应该是V2.0.x,V1.0.x版本固件库中,TIM1模块被独立出来,调用的函数与其他定时器不同;在V2.0系列版本中,取消了TIM1.h,所有的TIM模块统一调用TIM.h即可。网络上流传的各种代码有许多是基于v1版本的固件库,在移植到v2版本固件库时,需要做些修改。本文的所有程序都是基于V2.0固件库。

  以下是定时器向上溢出示例代码:

C语言: TIM1模块产生向上溢出事件
//Step1.时钟设置:启动TIM1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

//Step2.中断NVIC设置:允许中断,设置优先级
NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQChannel;    //更新事件
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;   //抢占优先级0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;          //响应优先级1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             //允许中断
NVIC_Init(&NVIC_InitStructure);                             //写入设置

//Step3.TIM1模块设置
void TIM_Configuration(void)
{
TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;


//TIM1 使用内部时钟
//TIM_InternalClockConfig(TIM1);

//TIM1基本设置
//设置预分频器分频系数71,即APB2=72M, TIM1_CLK=72/72=1MHz
//TIM_Period(TIM1_ARR)=1000,计数器向上计数到1000后产生更新事件,计数值归零
//向上计数模式
//TIM_RepetitionCounter(TIM1_RCR)=0,每次向上溢出都产生更新事件
TIM_BaseInitStructure.TIM_Period = 1000;
TIM_BaseInitStructure.TIM_Prescaler = 71;
TIM_BaseInitStructure.TIM_ClockDivision = 0;
TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

//清中断,以免一启用中断后立即产生中断
TIM_ClearFlag(TIM1, TIM_FLAG_Update);
//使能TIM1中断源
TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

//TIM1总开关:开启
TIM_Cmd(TIM1, ENABLE);
}

//Step4.中断服务子程序:
void TIM1_UP_IRQHandler(void)
{
GPIOC->ODR ^= (1<<4);                         //闪灯
TIM_ClearITPendingBit(TIM1, TIM_FLAG_Update); //清中断
}

  下面是输出比较功能实现TIM1_CH1管脚输出指定频率的脉冲:

C语言: TIM1模块实现输出比较,自动翻转并触发中断
//Step1.启动TIM1,同时还要注意给相应功能管脚启动时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

//Step2. PA.8口设置为TIM1的OC1输出口
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);

//Step3.使能TIM1的输出比较匹配中断
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);

//Step4. TIM模块设置
void TIM_Configuration(void)
{
    TIM_TimeBaseInitTypeDef TIM_BaseInitStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;


    //TIM1基本计数器设置
    TIM_BaseInitStructure.TIM_Period = 0xffff;                      //这里必须是65535
    TIM_BaseInitStructure.TIM_Prescaler = 71;                       //预分频71,即72分频,得1M
    TIM_BaseInitStructure.TIM_ClockDivision = 0;
    TIM_BaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_BaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM1, &TIM_BaseInitStructure);

    //TIM1_OC1模块设置
    TIM_OCStructInit(& TIM_OCInitStructure);
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;             //管脚输出模式:翻转
    TIM_OCInitStructure.TIM_Pulse = 2000;                           //翻转周期:2000个脉冲
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //使能TIM1_CH1通道
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //输出为正逻辑
    TIM_OC1Init(TIM1, &TIM_OCInitStructure);                        //写入配置

    //清中断
    TIM_ClearFlag(TIM1, TIM_FLAG_CC1);

    //TIM1中断源设置,开启相应通道的捕捉比较中断
    TIM_ITConfig(TIM1, TIM_IT_CC1, ENABLE);

    //TIM1开启
    TIM_Cmd(TIM1, ENABLE);
    //通道输出使能
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

Step5.中断服务子程序
void TIM1_CC_IRQHandler(void)
{
    u16 capture;
    if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET)
    {
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 );
        capture = TIM_GetCapture1(TIM1);
        TIM_SetCompare1(TIM1, capture + 2000);
        //这里解释下:
        //将TIM1_CCR1的值增加2000,使得下一个TIM事件也需要2000个脉冲,
        //另一种方式是清零脉冲计数器
        //TIM_SetCounter(TIM2,0x0000);
    }
}

  关于TIM的操作,要注意的是STM32处理器因为低功耗的需要,各模块需要分别独立开启时钟,所以,一定不要忘记给用到的模块和管脚使能时钟,因为这个原因,浪费了我好多时间阿~~!
下一回,将介绍TIM模块PWM的功能!

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

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2009-3-4 13:59:37 | 显示全部楼层
今天对比了一下,固件库手册跟固件库2.0里面的例子的TIM使用,对寄存器的定义对不上号!对TIM无从下手呀!

出0入0汤圆

发表于 2009-3-15 22:09:28 | 显示全部楼层
/* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 65535;         
  TIM_TimeBaseStructure.TIM_Prescaler =200;      
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;   
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

/* Output Compare Toggle Mode configuration: Channel1 */
   TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Toggle;         
  TIM_OCInitStructure.TIM_Channel = TIM_Channel_1;         
  TIM_OCInitStructure.TIM_Pulse =1;  
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OCInit(TIM3, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);

这个例程里面怎么调整TIM_OCInitStructure.TIM_Pulse都没有用,LED闪烁的速度都一样,郁闷ing,不知道哪位高手能指点下。

出0入0汤圆

发表于 2009-3-18 06:59:25 | 显示全部楼层
回复2楼,有可能是没有开启比较中断,这样每次计到65535才产生中断一次,可以改变65535看地否能改变灯闪的频率

出0入0汤圆

发表于 2009-9-27 11:49:11 | 显示全部楼层
2楼的,我的也是这个情况,弄好了没啊,给大家说一下啊。

出0入0汤圆

发表于 2009-11-4 16:17:29 | 显示全部楼层
TIM_BaseInitStructure.TIM_Period = 1000;

这个在计算时是否要加1,或在设置时是否要减1?

数值大影响不大,但是数值小了就影响大了

出0入0汤圆

发表于 2010-1-6 11:22:08 | 显示全部楼层
Step5.中断服务子程序
void TIM1_CC_IRQHandler(void)
{
    u16 capture;
    if(TIM_GetITStatus(TIM1, TIM_IT_CC1) == SET)
    {
        TIM_ClearITPendingBit(TIM1, TIM_IT_CC1 );
        capture = TIM_GetCapture1(TIM1);
        TIM_SetCompare1(TIM1, capture + 2000);
        //这里解释下:
        //将TIM1_CCR1的值增加2000,使得下一个TIM事件也需要2000个脉冲,
        //另一种方式是清零脉冲计数器
        //TIM_SetCounter(TIM2,0x0000);
    }
}
在中断服务子程序的 TIM_SetCompare1(TIM1, capture + 2000);   要改变相应的数值  才能够改变中断的频率

出0入0汤圆

发表于 2010-1-11 18:12:21 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-2-17 11:32:06 | 显示全部楼层
【楼主位】 jjldc 九九

各模块需要分别独立开启时钟,所以,一定不要忘记给用到的模块和管脚使能时钟,因为这个原因,浪费了我好多时间阿~~!
-----------------------------------------------------------------------

用下面这个指令是不是就没有这个麻烦了?
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ALL, ENABLE);

出0入0汤圆

发表于 2010-3-10 10:48:07 | 显示全部楼层
回复【楼主位】jjldc 九九
-----------------------------------------------------------------------

我按您的程序做试验,设置:TIM_BaseInitStructure.TIM_Period = 1000;
TIM_BaseInitStructure.TIM_Prescaler = 71000;想实现1S延时,可是发现不准啊,您能给解释一下不?

出0入0汤圆

发表于 2010-3-10 11:35:56 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-19 02:07:47 | 显示全部楼层
MARK

出0入0汤圆

发表于 2010-3-20 19:46:16 | 显示全部楼层
问下楼主:为什么说  “TIM_BaseInitStructure.TIM_Period = 0xffff;”  这里必须是65535  ???

出0入0汤圆

发表于 2010-5-19 15:46:44 | 显示全部楼层
mark下

出0入46汤圆

发表于 2010-5-24 11:05:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-31 11:36:45 | 显示全部楼层
markt

出0入0汤圆

发表于 2010-8-20 11:16:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-26 12:14:38 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-10-26 19:04:33 | 显示全部楼层
谢谢分享

出0入0汤圆

发表于 2010-10-26 19:05:41 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2010-10-26 21:45:21 | 显示全部楼层
回复【12楼】bingobravo
问下楼主:为什么说  “tim_baseinitstructure.tim_period = 0xffff;”  这里必须是65535  ???

-----------------------------------------------------------------------

继续提问

出0入0汤圆

发表于 2010-10-28 16:15:59 | 显示全部楼层
很牛啊。。。。。。。。。。

出0入0汤圆

发表于 2010-12-2 01:00:21 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-12-14 10:03:48 | 显示全部楼层
回复【20楼】jclwd8263 一片机
回复【12楼】bingobravo  
问下楼主:为什么说  “tim_baseinitstructure.tim_period = 0xffff;”  这里必须是65535  ???  
-----------------------------------------------------------------------
继续提问
-----------------------------------------------------------------------

我也想问这个问题~,

大虾帮我看看这个问题吧,调了N久了都不知道为啥调不出来..
http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=4452140&bbs_page_no=1&bbs_id=3020

出0入0汤圆

发表于 2011-3-10 13:50:11 | 显示全部楼层
回复【9楼】yaowang_hao
-----------------------------------------------------------------------

TIM_BaseInitStructure.TIM_Prescaler = 71000;
这个好像越界了

出0入0汤圆

发表于 2011-6-1 19:14:29 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-6-9 22:00:21 | 显示全部楼层
Thx

出0入0汤圆

发表于 2011-7-1 14:41:08 | 显示全部楼层
mark!

出0入0汤圆

发表于 2011-7-6 20:14:27 | 显示全部楼层
回复【20楼】jclwd8263 一片机
回复【12楼】bingobravo  
问下楼主:为什么说  “tim_baseinitstructure.tim_period = 0xffff;”  这里必须是65535  ???  
-----------------------------------------------------------------------
继续提问
-----------------------------------------------------------------------

我现在也想知道为什么 这里就必须是65535 ,我换为60000,中断时间出问题,不知道什么原因?????

出0入8汤圆

发表于 2011-7-6 21:49:53 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-8-18 16:14:23 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-11-22 22:54:24 | 显示全部楼层
学习了,正需要这方面的资料。

出0入0汤圆

发表于 2011-11-24 08:23:50 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-1 10:52:18 | 显示全部楼层
标记下 需要这方面的知识

出0入0汤圆

发表于 2011-12-1 20:18:46 | 显示全部楼层
菜鸟向各位大侠学习

出0入0汤圆

发表于 2011-12-9 10:57:41 | 显示全部楼层
MARK

出0入0汤圆

发表于 2011-12-9 16:40:43 | 显示全部楼层
再顶一次,好贴解渴!

出0入0汤圆

发表于 2011-12-9 20:59:56 | 显示全部楼层
mark!!!!

出0入0汤圆

发表于 2011-12-13 11:23:39 | 显示全部楼层
我已在搞TIM1的中断,搞了半天也中断不了,郁闷呀国.
谢谢楼主的分享

出0入0汤圆

发表于 2011-12-24 14:32:35 | 显示全部楼层
学习。

出0入0汤圆

发表于 2012-1-16 18:24:26 | 显示全部楼层
学习一下!

出0入0汤圆

发表于 2012-3-30 22:20:24 | 显示全部楼层
好帖子。讲得很详细。多谢分享。

出0入0汤圆

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

出0入0汤圆

发表于 2012-10-25 17:25:46 | 显示全部楼层
非常感谢分享

出0入0汤圆

发表于 2013-1-23 10:03:08 | 显示全部楼层
回复【20楼】jclwd8263 一片机
回复【12楼】bingobravo  
问下楼主:为什么说  “tim_baseinitstructure.tim_period = 0xffff;”  这里必须是65535  ???  
-----------------------------------------------------------------------
回复【29楼】hnnzhh
继续提问
-----------------------------------------------------------------------

我现在也想知道为什么 这里就必须是65535 ,我换为60000,中断时间出问题,不知道什么原因?????

-----------------------------------------------------------------------
哪位高手可以解答一下吗???

出0入8汤圆

发表于 2014-10-27 15:14:01 | 显示全部楼层
计数器已经让我疯狂了~

出0入0汤圆

发表于 2014-11-1 17:15:26 | 显示全部楼层

mark

出0入0汤圆

发表于 2015-1-28 10:55:50 | 显示全部楼层
学习                  

出0入0汤圆

发表于 2018-8-31 19:50:10 | 显示全部楼层
链接失效

出0入0汤圆

发表于 2018-8-31 20:53:30 | 显示全部楼层

  MARK  方便查找

出0入0汤圆

发表于 2018-12-19 21:01:04 | 显示全部楼层
谢谢分享,学习了

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-4-26 07:57

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

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