利用定时器中断方式控制led灯的闪烁速度_stm32学习之基本定时器--TIM

本文详细介绍了STM32F1系列中基本定时器TIM6/7的工作原理及应用,包括定时器的配置、时钟源、预分频器、计数器等关键概念,并通过实例演示如何实现1秒定时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

STM32f1系列,有基本定时器、通用定时器、高级定时器三类tiM定时器。其中,TIM6/7是本文要讲的基本定时器。
  基本定时器TIM6/7是16位的只能向上计数的定时器,只能用于定时。而通用定时器和高级定时器有更多的功能,如还可以进行输出比较、输入捕捉等功能,相关的介绍会写在后面的文章,这里只讲基本定时器。
  先看看基本定时器的框图,如图24-1。

ebac03c635183a551ed236495238303a.png


  图24-1时钟
  我们查阅参考手册RCC章节的时钟树可以知道,RCC的定时器时钟TIMxCLK,即内部时钟CK_INT是由APB1预分频器分频后提供。如图24-2所示,如果APB1预分频系数为1,,则频率不变,否则频率为2倍。即此时用于分频的APB1的预分频系数为2,所以TIMxCLK = 36 * 2 = 72MHz。


  图24-2计数器时钟
  如图24-1的框图,计数器时钟由内部时钟CK_INT提供,经过PSC预分频器后得到CK_CNT。PSC是一个16位的预分频器,可以对定时器时钟TIMxCLK进行1~65536之间的任何一个数进行分频。分频后的CK_CNT值的计算在参考手册TIMx_PSC寄存器描述里有提到,如图24-3。

ef4081e4be630ac32e734cc7e3bb79b8.png


  图24-3
  即CK_CNT = CK_PSC/(PSC[15:0]+1)。
  计数器
  计数器CNT是一个16位的计数器,只能往上计数,最大计数值为65535。
  自动重装载寄存器TIMx_ARR
  TIMx_ARR寄存器里存着最大的计数值,当计数到该值时,会产生中断。当然了你得使能了中断才可以。
  定时时间计算
  计一个数的时间是1/CK_CNT,产生一次中断的时间为(ARR+1)/CK_CNT。如果在中断服务程序里设置一个变量time用于记录中断次数,则定时时间为:(ARR+1)/CK_CNT*time。
  TIM_TimeBaseInitTypeDef
  如图24-4为基本定时器TIM_TimeBaseInitTypeDef结构体定义。

6edae09c702df4033b7411850bca3e53.png

  图24-4

  TIM_Prescaler:指定定时器预分频器数值,由TIMx_PSC寄存器配置,可设置范围为0x0000~0xFFFF,即0~65535;

  TIM_CounterMode:计数模式,可分为向上计数、向下计数以及三种中心对齐模式。而基本定时器只能向上计数;

  TIM_Period:计数器周期,即自动重装载寄存器TIMx_ARR的值,在事件生成时更新到影子寄存器,由TIMx_CR1寄存器的ARPE位配置是否使能缓冲;

  TIM_clockDivision:时钟分频,配置定时器时钟CK_INT频率与数字滤波器采样时钟频率分频比,基本定时器没有这个功能,不用设置;

  TIM_RepetitionCounter:重复计数器,属于高级控制寄存器专用寄存器位,利用它可以很容易控制输出PWM个数,这里不用设置。

  定时1s实验

  例如,需要做一个1s的定时,CK_PSC=72MHz,则PSC=71,那么CK_CNT=1MHz,

  计一个数时间:1/CK_CNT = 1/1MHz = 1us,

  中断一次的时间:(ARR+1)/CK_CNT = (999+1)/1MHz = 1ms,

  则定时时间:(ARR+1)/CK_CNT*time = 1ms*1000 = 1s

  我们用LED的亮灭状态变化来展示1s的定时。

  初始化TIM_TimeBaseInitTypeDef

  前文提到的TIM_TimeBaseInitTypeDef结构体有5个成员,但基本定时器TIM6/7只用到了TIM_Prescaler和TIM_Period这两个成员,其他三个是通用定时器和高级定时器才会用到的。(时钟系统)http://makeru.com.cn/live/1392_1082.html?s=45051

IF">

  1.   /**
  2.   * [url=home.php?mod=space&uid=2666770]@Brief[/url] 基本定时器配置
  3.   * [url=home.php?mod=space&uid=3142012]@param[/url] 无
  4.   * @retval 无
  5.   */
  6.   static void BASIC_TIM_Mode_Config(void)
  7.   {
  8.   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
  9.   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); // 内部时钟72MHz
  10.   TIM_TimeBaseStructure.TIM_Period = 999; // 自动重装载寄存器的值
  11.   TIM_TimeBaseStructure.TIM_Prescaler= 71; // 预分频器数值
  12.   TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
  13.   TIM_CleaRFlag(TIM6, TIM_FLAG_Update); // 清除计数器中断标志位
  14.   TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE);
  15.   TIM_Cmd(TIM6, ENABLE);
  16.   }

复制代码

  中断优先级配置

  有关中断配置相关已经在之前的文章介绍过,有不清楚的地方可移步阅读。这里只说几个配置的关键点。可配置中断优先级分组为0,即0位抢占优先级,4位子优先级。配置中断源为TIM6_IRQn。(32中断系统)http://makeru.com.cn/live/1392_1124.html?s=45051

  1.   /**
  2.   * @brief 中断优先级配置
  3.   * @param 无
  4.   * @retval 无
  5.   */
  6.   static void BASIC_TIM_NVIC_Config(void)
  7.   {
  8.   NVIC_InitTypeDef NVIC_InitStructure;
  9.   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
  10.   NVIC_InitStructure.NVIC_IRQChannel = TIM6_IRQn;
  11.   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  12.   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
  13.   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  14.   NVIC_Init(&NVIC_InitStructure);
  15.   }

复制代码

  中断函数
  中断函数在stm32f10x_it.c文件里配置。

  1.  extern volatile uint32_t time; // 该变量定义在main()函数里
  2.   void TIM6_IRQHandler(void)
  3.   {
  4.   if(TIM_GetITStatus(TIM6, TIM_IT_Update) != RESET)
  5.   {
  6.   time++; // 每中断一次,time值加1,中断一次时间为1ms,需要中断1000次才可定时1s,即time值为1000
  7.   TIM_ClearITPendingBit(TIM6, TIM_FLAG_Update);
  8.   }
  9.   }

复制代码

  最后在main()函数里调用led和定时器的初始化配置函数,在一个循环里判断time变量的值是否为1000,如果已经达到1000,则led灯状态变化(亮或灭)一次,并且time变量值重赋为0,以便继续判断及定时。更多交流学习可以私我昵称wx号

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值