前言
在一些需要的情况下软件延时十分必要,有时为了测试方便大都直接用了while(–i)或者for循环大致延时下看看就可以了。当需要精确延时情况下一般需要定时器来定时,当然对于STM32系列单片机都有SysTick,一般都是用这个作为延时定时器。这两天突然想着用个基本定时器实现一个延时程序,想着几十分钟的解决的事情结果搞了一整天,所以写个博客纪念一下调试经历。
必须了解
想要正确使用定时器就不得不先了解两个必要内容:定时器的时钟频率和影子寄存器这两个内容。不止针对基本定时器其它定时器也是一样的。
定时器时钟频率
本着遇到问题就查数据手册的精神,首先来查阅《STM32F4xx中文参考手册》关于定时器章节发现基本上就说计数原理以及寄存器说明,对于时钟没说什么。没关系往上一层看,直接看STM32的时钟树,如下图:
先大致看了下有关于定时器时钟描述的,从图上看大致也就是如果APBx不分频(也就是APBx presc = /1),定时器时钟频率也就是APBx的时钟频率,反之就是对APBx时钟的×2倍频。然后继续往下看会看到这样的话:
可以看出跟我们的理解差不多。那么就到了下一步对于APBx的时钟怎么确定呢?那么一般情况下如果事自己配置的时钟自己应该直接就知道了,如果不是自己配置的我们会直接调用库函数的时钟初始化函数,那么此时有两种方法可以确定我们的APBx的时钟:
法一:还是这个图,首先一个前提我们都知道使用库函数时钟配置,SYSCLK为168MHZ,那么如果知道AHB和APBx的分频值,根据上述描述直接就可以得到定时器频率了。
问题来了,在哪里可以看到这个两个分频值勒,很简单库函数时钟配置在system_stm32f4xx.c,当然在这里找了。很简单不用看代码直接看@brief里面的第5条,找到自己F4的型号,以STM32F40xxx/41xxx devices为例,如下图:
可以看到AHB与APBx的分频值,根据确定上述判定,到APBx的时钟为168MHz,APBx的分频值也不是1,所以定时器时钟也就是APBx时钟的2倍数。以上就可以得到了定时器频率(这种方式可能有些人不清楚定时器挂载在哪一个APB上,简单看法就是直接看rcc里面开启外设时钟里面的参数可选值可以看到或者直接查看数据手册)。
法二:不说废话直接看手册,外设挂载图以及相应时钟(只对使用库函初始化的时钟配置可以,自己配置不可以)
直接看到APB1是42MHz,APB2是84MHz。分频值也不是1所以定时器6、7的时钟频率也就是84MHz。
影子寄存器
关于影子寄存器,我大致说下所谓影子寄存器就是定时器实际工作寄存器,而给与用户的操作的寄存器就是影子寄存器的本体,那么当我们操作寄存器时,需要一个条件去将写入寄存器值更新到影子寄存器中或者“直接操作”影子寄存器。(关于定时器的影子操作寄存器这个文章写的挺好:STM32定时器的预装寄存器及影子寄存器PSC—ARR-CCRx
)
代码设计
首先是初始化。
void tim7Init()
{
NVIC_InitTypeDef NVIC_InitStruct;
//开启相关时钟
RCC_APB1PeriphClockCmd(TIM_RCC_PERIPH, ENABLE);
//开启自动重装
TIM_ARRPreloadConfig(TIM_NAME, ENABLE);
//中断NVIC配置
NVIC_InitStruct.NVIC_IRQChannel = TIM7_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority