Timer是单片机中非常常见的一种外设组件,可以实现很多常用的功能,这篇文章就将对STM32中Timer的基础内容做个说明。
单片机中的Timer很多时候完整的表达是 定时/计数器 ,某种意义上来说Timer最基本的功能就仅仅只是计数而已,定时这个功能也只是在计数这个基础功能之上实现的。
下图是定时器基本功能的流程:
上图中最核心的部分就是计数器,计数器一端是信号的输出,另一端是计数值满足一定条件后的输入,围绕这这个我们就可以实现很多功能。比如从输入端来说我们可以用来统计外部信号的频率脉宽等;从输出端来说我们可以用来触发计数溢出中断、ADC采样、DAC输出、DMA传输等。在计数过程中放置一个中间值进行比较我们就可以以此来输出PWM信号。
Timer作为定时使用时信号来源通常使用内部时钟,这里的内部时钟指的是APB1、APB2这些。
下图是STM32F405/407 Datasheet 2.2节Device overview中的block diagram
从这个图中可以看到该系列芯片的Timer分别使用了APB1和APB2时钟
确定了时钟来源我们接着使用定时功能主要处理下面几项参数:
Prescaler
预分频系数CounterMode
计数模式Period
计数周期AutoReloadPreload
预装载Timer作为定时使用时信号来源通常使用内部时钟,当我们确定Timer的时钟信号频率后根据此设定实现定时某一时间周期所需要的参数了,这里主要涉及Prescaler和Period两个参数。Prescaler是对输入定时器的时钟信号进行分频,Period为一个周期中的计数值。
根据上面的内容Timer每计数一次的时间为 1秒 ÷ (时钟频率 ÷ (Prescaler + 1))
,定时器计数满一个周期的时间为 计数一次时间 × (Period + 1) 秒
。所以定时时间计算公式如下:
定时时间 = (Prescaler + 1) × (Period + 1) ÷ 时钟频率 单位:秒
STM32单片机中有很多个Timer,通常TIM6和TIM7称为基础定时器、TIM1和TIM8称为高级定时器、其余的被称为通用定时器。基础定时器基本上只有定时功能;通用定时器在定时基础上还支持外部输入捕获、比较、PWM输出等功能;高级定时器在通用定时器的基础上只要增加了用于电机控制等功能。
Timer作为定时功能使用时通常用于在定时时间到的时候触发中断、触发ADC转换、触发数据传输等功能,这里以触发中断作为演示:
下面图片看不清的话可以点击查看大图
上面演示中我使用了TIM7,启用了它的溢出中断,中断函数中翻转了PA2管脚的输出电平,最后使用示波器抓取该针脚电平作为演示。
根据上一章节的图表可知TIM7是在APB1总线上的,在上图中可以看到我的APB1给Timer的时钟频率为84MHz,这时如果设定Prescaler为83,即对时钟84分频,相当于给计数器的时钟为1MHz,每次计数时间为1us。上图中我设定Prescaler为8399,即对时钟8400分频,相当于给计数器的时钟为10KHz,每次计数时间为100us。
上图中我设定Period为9999,即每个计数周期为10000次计数,再根据时钟和Prescaler的设定,最终上图中一个计数周期为1秒中,中断为1秒触发一次。
在使用STM32CubeIDE配置TIM生成代码后,我们还需要手动添加中断回调处理:
void HAL_TIM_PeriodElapsedCallback (TIM_HandleTypeDef *htim)
{
if(htim == &htim7) // 判断触发溢出中断的定时器
{
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);
}
}
有了中断回调处理后我们启用TIM只要使用下面方法即可:
HAL_TIM_Base_Start_IT(&htim7);
有时候定时器启用后会立即进入中断,可以在启用TIM前使用下面方法清除中断:
// __HAL_TIM_CLEAR_FLAG(__HANDLE__, TIM_FLAG_UPDATE)
__HAL_TIM_CLEAR_IT(__HANDLE__, TIM_IT_UPDATE)
如果想要停止定时器运行可以用下面方法:
HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim)
如果想要在程序中动态修改Period可以使用下面方面:
__HAL_TIM_SET_AUTORELOAD(__HANDLE__, __AUTORELOAD__)
如果要在定时器已经启用的情况下修改Period的话建议使能AutoReloadPreload。下面是一个修改Period的演示:
上面演示中最大的改动就是TIM4是选取了Internal Clock才是使用定时功能,代码几乎没有改动。
要注意的是根据上一章节图表TIM1是在APB2下的,上图中APB2给Timer的时钟频率为168MHz,所以根据设定的参数计算出来一个定时周期为500ms,所以演示中每500ms会触发一次中断,翻转IO口电平。
Timer作为定时器使用是比较简单的,更多内容可以查看官方文档和例程。