赞
踩
通过HAL库实现定时器定时中断需要在
开启中断前清除中断标志位
,否则一开启定时器中断就会进入一次中断。要解决这个问题很简单,就是调用函数__HAL_TIM_CLEAR_IT(&htim6, TIM_IT_UPDATE);
完成中断标志位的清除。这个细节大家根据需要看是否要处理掉。
为了实现LED每隔0.5s进行一次翻转,且不阻塞主程序。
STM32所有
非内核外设
都有时钟驱动,所以在配置外设的时候都需要先配置时钟树。
我使用的是STM32F407ZGT6,时钟树配置如下图所示:
配置好时钟树后我们就需要根据时钟总线频率(APB1=84Nhz)
设计参数。
这里有个问题就是定时器TIM6挂载在哪个时钟总线上?对于具体外设挂载在哪个时钟总线上我们可以打开对应芯片的
数据手册
。例如我用的是STM32F407ZGT6打开数据手册我们可以看到一个具体的系统框图(截取一部分)。
通过这张图,我们可以看到TIM6和TIM7都是挂载到APB1上,再结合上面我们配置时钟树是APB1=84Mhz,所以我们可以知道定时器TIM6时钟输入频率为84Mhz。
在知道定时器输入频率后,我们就正式进入参数设计阶段。到这里我们先看一下Cube中有哪些参数需要我们设计:
可以看到一共有四个参数需要我们去配置:
Prescaler:预分频,参数范围0-65535
Counter Mode:计数模式,TIM6只有向上计数模式(UP)
Counter Period:计数周期,参数范围0-65535
auto-reload preload:是否启用预先
自动重装载,建议选择Enable
本次实利用定时器实现每隔一段时间去完成某一件事,这段时间为:
T
o
u
t
=
(
(
a
r
r
+
1
)
∗
(
p
s
c
+
1
)
)
/
T
c
l
k
Tout=((arr+1)*(psc+1))/Tclk
Tout=((arr+1)∗(psc+1))/Tclk
arr为计数周期(999)
psc为分频系数(41999)
Tclk为接入定时器的时钟总线(Tclk=APB1=84Mhz=84000000)
Tout表示每个多长时间触发一次定时中断(0.5s)
把上图中我设计的参数带入计算可以得到:
T
o
u
t
=
(
999
+
1
)
∗
(
41999
+
1
)
/
84000000
=
0.5
s
Tout=(999+1)*(41999+1)/84000000=0.5s
Tout=(999+1)∗(41999+1)/84000000=0.5s
对于不同的计数模式,我看了中文参考手册,发现TIM6只有向上计数模式(UP),下面就是各个定时器计数模式截图:
推荐启用Enable,这个问题我单独写一篇博客解释为什么推荐开启自动重载预装载功能
HAL库对中断进行了再封装,我们不再从中断向量指向的函数执行具体动作,而是通过
回调函数
来完成我们想完成的动作。HAL的封装帮我们简化了开发流程,只需要写业务逻辑,不需要我们去完成清除中断标志,HAL已经帮我们封装好了。
想要具体了解怎么个原理可以参考这篇博客。
Cube生成的代码会将回调函数写到main.c文件中。例如本次实验的定时器中断回调函数Cube在main.c中生成的代码:
在这里我就完成了两件事:
一是确定中断来源,也就是那两句if语句。
二是编写业务代码,也就是LED0翻转。
Cubemx生成的代码并不会自动帮我们打开定时器中断,需要我们手动打开。
需要调用函数HAL_TIM_Base_Start_IT(&htim6);
来帮助我们开启定时器中断。
在开启定时器中断前有一个细节,在文章最开头我已经说明了,在启动定时器中断前如果不
手动清除中断
,那么一旦启动定时器中断,系统就会马上执行一次中断
。也就是一旦开启LED灯状态就会进行一次翻转。
下面这些仅作了解
HAL_TIM_Base_Start_IT(&htim6);`
1.用于启动定时器基本定时中断
2.当定时器的计数器溢出时,会触发中断
3.适用于需要周期性触发中断的应用,如定时器中断用于操作系统的任务调度
还有一个类似的函数是:
HAL_TIM_IC_Start_IT(&htim6);`
用于启动输入捕获(Input Capture)模式下的定时器中断
当输入信号发生边沿变化时,会触发中断
适用于需要测量输入信号频率或脉冲宽度的应用,例如测量超声波HC05高电平时长来测距
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。