你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32F103:定时器中断 time——通用定时器TIM3使用

[复制链接]
STMCU小助手 发布时间:2022-5-3 22:25
一、STM32F103定时器

U}CZ4YCWOWR(@]TXY~F3~X8.png

二、STM32F103通用定时器
1. 主要功能
通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:
位于低速的APB1总线上(注意:高级定时器是在高速的APB2总线上);
16位向上、向下、向上/向下自动装载计数器(TIMx_CNT);
16位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为1~65536之间的任意数值;
4个独立通道(TIMx_CH1~4),这些通道可以用来作为:输入捕获、输出比较、PWM生成(边缘或中间对齐模式)、单脉冲模式输出;
使用外部信号控制定时器和定时器互连的同步电路;
如下事件发生时产生中断/DMA:更新(计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发))、触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)、输入捕获、输出比较;
支持针对定位的增量(正交)编码器和霍尔传感器电路;
触发输入作为外部时钟或者按周期的电流管理;
每个通用定时器都是完全独立的,没有互相共享的任何资源。
2. 时基单元
时基单元包含:计数器寄存器(TIMx_CNT)、预分频器寄存器(TIMx_PSC)、自动装载寄存器(TIMx_ARR)三部分。
对不同的预分频系数,计数器的时序图为:

PKN[$BDPFW_036PR61X}}BM.png

3. 计数器模式
向上计数模式

B}RV2~$HAMFD[ZPC(1TE12K.png

向下计数模式

XB$CGMBDRM747}6~2TZ1Y9Y.png

中央对齐模式(向上/向下计数)


_R~%{0NJ5~{PU98ND0P[XK0.png

4. 时钟选择
计数器时钟可由下列时钟源提供:

内部时钟(TIMx_CLK)
外部时钟模式1:外部捕捉比较引脚(TIx)
外部时钟模式2:外部引脚输入(TIMx_ETR)
内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

内部时钟源

%~`O]HSK8Q74}2%I_HVQ_AP.png

从图中可以看出:由AHB时钟经过APB1预分频系数转至APB1时钟,再通过倍频器转至TIMxCLK时钟(即内部时钟CK_INT、CK_PSC),最终经过PSC预分频系数转至CK_CNT。

当APB1的预分频器系数为1时,这个倍频器就不起作用了,定时器的时钟频率等于APB1的频率;
当APB1的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个倍频器起作用,定时器的时钟频率等于APB1时钟频率的两倍。

默认情况下:
AHB总线时钟——STM32F103是72MHz,APB1时钟=36M。
所以APB1的分频系数=AHB/APB1时钟=2。
通用定时器时钟CK_INT=2*36M=72M。
最终经过PSC预分频系数转至CK_CNT。

时间计算
Tout= ((arr+1)*(psc+1))/Tclk;
Tclk:TIM3的输入时钟频率(单位为MHz)。
Tout:TIM3溢出时间(单位为us)。
例:计时1s,输入时钟频率为72MHz。
  arr = 9999,psc = 7199。
  Tout = ((arr+1)*(psc+1))/Tclk = ((9999+1) *(7199+1))/72=1M(us)=1(s)

H_007WUT62FXL2JQ7VKEYGN.png

5. 相关配置寄存器
计数器当前值寄存器(TIMx_CNT)

7@JWBF5XPB[1BWFH9VZOAD2.png

预分频寄存器(TIMx_PSC)

W$]]{%OED6{AFRCM6LGD]IT.png

自动重装载寄存器(TIMx_ARR)

V_QT0)X_}_J%$YMRMF$H.png

控制寄存器(TIMx_CR1)

~[6WPBO~LMO0OMW5_]ZL.png

]T$BA}P]8K$ZY[~17F5A{GC.png

DMA/中断使能寄存器(TIMx_DIER)

}6$MI-@RO7W@M~K}KX%{C.png

ZO}RIM8%({YU2[9QSX}[Z_7.png

三、编写定时器中断——time
1. 相关配置库函数

1个初始化函数
  1. void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
复制代码

作用:用于对预分频系数、计数方式、自动重装载计数值、时钟分频因子等参数的设置。

2个使能函数

  1. void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);        //使能定时器
  2. void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);        //使能定时器中断
复制代码

4个状态标志位获取函数

  1. FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//获取状态标志位
  2. void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//清除状态标志位
  3. ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);//获取中断状态标志位
  4. void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);//清除中断状态标志位
复制代码

2. 具体步骤

1.使能定时器时钟。调用函数:RCC_APB1PeriphClockCmd();
2.初始化定时器,配置ARR、PSC。调用函数:TIM_TimeBaseInit();
3.开启定时器中断,配置NVIC。调用函数:void TIM_ITConfig();NVIC_Init();
4.使能定时器。调用函数:TIM_Cmd();
5.编写中断服务函数。调用函数:TIMx_IRQHandler()。

3. 具体程序
time.h

  1. #ifndef __TIME_H
  2. #define __TIME_H         
  3. #include "stm32f10x.h"

  4. //创建一个时间结构体
  5. typedef struct
  6. {
  7.         u32     Tnum;
  8.         u8                T100ms;
  9.         u8           T200ms;
  10.         u8           T500ms;
  11.         u8                 T1s;
  12.         u8                 T5s;
  13.         u8           T1min;
  14. }TIME_t;

  15. extern TIME_t TIME;                //将时间结构体变量设为全局变量

  16. void TIM3_Init(u16 arr,u16 psc);

  17. #endif
复制代码

time.c

  1. #include "time.h"

  2. TIME_t TIME;

  3. //通用定时器 3 中断初始化
  4. //这里时钟选择为 APB1 的 2 倍,而 APB1 为 36M
  5. //arr:自动重装值。
  6. //psc:时钟预分频数
  7. //这里使用的是定时器 3!
  8. void TIM3_Init(u16 arr,u16 psc)
  9. {
  10.         TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  11.         NVIC_InitTypeDef NVIC_InitStructure;
  12.         RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟 TIM3 使能
  13.         //定时器 TIM3 初始化
  14.         TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值
  15.         TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
  16.         TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
  17.         TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
  18.         TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);  //初始化 TIM3
  19.         TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );  //允许更新中断
  20.         //中断优先级 NVIC 设置
  21.         NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3 中断
  22.         NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级
  23.         NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级 1 级
  24.         NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  //IRQ 通道被使能
  25.         NVIC_Init(&NVIC_InitStructure);   //初始化 NVIC 寄存器
  26.                
  27.         TIM_Cmd(TIM3, ENABLE);                  // TIM3
  28. }


  29. //定时器 3 中断服务程序
  30. void TIM3_IRQHandler(void) //TIM3 中断
  31. {
  32.         if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否
  33.         {
  34.                 TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志
  35.                 //每100ms一次。        
  36.                 //这里可以编写功能程序
  37.                
  38.                 if(TIME.Tnum>=24*60*60*10)        {        TIME.Tnum=0;        }        //一天的时间清零一次
  39.                 else                                                {        TIME.Tnum++;        }
  40.                 TIME.T100ms=1;
  41.                 if(TIME.Tnum%2==0)                        {        TIME.T200ms=1;        }
  42.                 if(TIME.Tnum%5==0)                        {        TIME.T500ms=1;        }
  43.                 if(TIME.Tnum%10==1)                        {        TIME.T1s=1;                }
  44.                    if(TIME.Tnum%30==2)                        {        TIME.T3s=1;                }
  45.                 if(TIME.Tnum%600==3)                {        TIME.T1min=1;        }

  46.                 //在中断中执行任务,优点是准时,缺点是容易打断其他任务,不建议在中断中执行任务,可以在主函数中执行任务。
  47.                 if(TIME.T100ms==1)
  48.                 {
  49.                         TIME.T100ms=0;
  50.                         //100ms要执行的任务
  51.                 }
  52.                 if(TIME.T200ms==1)
  53.                 {
  54.                         TIME.T200ms=0;
  55.                         //200ms要执行的任务
  56.                 }
  57.                 //。等
  58.                 //。中间省略
  59.                 //。等
  60.                 if(TIME.T1min==1)
  61.                 {
  62.                         TIME.T1min=0;
  63.                         //1min要执行的任务
  64.                 }
  65.         }
  66. }
复制代码

main.c
  1. #include "stm32f10x.h"
  2. #include "time.h"


  3. int main()
  4. {
  5.         /**
  6.         其它初始化省略
  7.         **/
  8.         TIM3_Init(1999,7199);        //10Khz的计数频率,计数到1000为100ms
  9.         
  10.         while(1)
  11.         {
  12.                 /**
  13.                         其他功能程序
  14.                 **/
  15.                
  16.                 if(TIME.T100ms==1)
  17.                 {
  18.                         TIME.T100ms=0;
  19.                         //100ms要执行的任务
  20.                 }
  21.                 if(TIME.T200ms==1)
  22.                 {
  23.                         TIME.T200ms=0;
  24.                         //200ms要执行的任务
  25.                 }
  26.                 //。等
  27.                 //。中间省略
  28.                 //。等
  29.                 if(TIME.T1min==1)
  30.                 {
  31.                         TIME.T1min=0;
  32.                         //1min要执行的任务
  33.                 }

  34.         }
  35. }
复制代码




收藏 评论0 发布时间:2022-5-3 22:25

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版