STM32|STM32 通用定时器

STM32有8路寄存器,包括TIM1和TIM8两个高级定时器,TIM6和TIM7两个基本定时器,TIM2-TIM5四个通用定时器,定时器是完全独立的,而且没有互相共享任何资源,它们可以一起同步操作,所有TIMx定时器在内部相连,用于定时器同步或链接。当一个定时器处于主模式时,它可以对另一个处于从模式的定时器的计数器进行复位、启动、停止或提供时钟等操作。
定时器的时钟:
计数器时钟可由下列时钟源提供:
1:内部时钟(CK_INT)
2:外部时钟模式1:外部输入脚(TIx)
3:外部时钟模式2:外部触发输入(ETR)
4:内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。
这些时钟,具体选择哪个可以通过TIMx_SMCR寄存器的相关位来设置。这里的CK_INT时钟是从APB1倍频的来的,除非APB1的时钟分频数设置为1,否则通用定时器TIMx的时钟是APB1时钟的2倍,当APB1的时钟不分频的时候,通用定时器TIMx的时钟就等于APB1的时钟。这里还要注意的就是高级定时器的时钟不是来自APB1,而是来自APB2的。
定时器的核心:
说到定时器的核心,自然少不了两个,一个是计数时钟(每隔多长时间计一次),二是计多少次溢出,这两个就共同决定了溢出时间。
定时器的计数时钟根据定时器的不同分别来自APB1或APB2,计数时钟说白了就是要把一秒分成很多份,但由于总线时钟一般在数十兆,经过分频的APB也在数十兆,所以要把APB再分频至更低的频率,这就需要设置预分频寄存器。例如当前APB1为36MHz,上面加黑的一段已经说过,除非APB1的时钟分频数设置为1,否则通用定时器TIMx的时钟是APB1时钟的2倍,这时的TIMx时钟为72MHz,因此分频至10KHz需要设置预分频器寄存器TIMx_PSC(如下图)为7199,为什么是7199而不是7200呢?下面寄存器介绍说明了这点:计数器时钟CK_CNT等于TIMx时钟/(PSC+1),所以只需设置寄存器值7199就行了。这里10KHz的频率相当于把一秒分为10000份,即0.0001秒,定时器每隔0.0001秒涨一次。


注:因为PSC是16位寄存器,所以值范围为0-65535。
计数器自动重装载寄存器TIMx_PSC,该寄存器存放的就是计数器要增加的次数(计多少次溢出)。


注:因为ARR也是16位寄存器,所以值范围为0-65535。
这样这两个寄存器决定了溢出时间,接着上面的例子,如果设置ARR寄存器值为5000,那就是说定时器每隔0.0001秒涨一次,总共涨5000次,这样就是0.5秒溢出一次。
总结下来,定时器的溢出公式为:溢出时间(秒)= (ARR*(PSC+1))/ TIMx时钟CK_PSC(MHz)
通用定时器3初始化函数:
void Timerx_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<1; //TIM3时钟使能
TIM3->ARR=arr; //设定计数器自动重装值
TIM3->PSC=psc; //预分频器,得到计数时钟
//这两个寄存器要同时设置才可以使用中断
TIM3->DIER|=1<<0; //允许更新中断
TIM3->DIER|=1<<6; //允许触发中断
TIM3->CR1|=0x01; //使能定时器3
MY_NVIC_Init(1,3,TIM3_IRQChannel,2); //抢占1,子优先级3,组2
}
此函数为TIM3进行初始化函数,主函数中进入死循环等待TIM3溢出中断,当TIM3_CNT的值等于TIM3_ARR的值的时候,就会产生TIM3的更新中断,然后在中断里面执行完中断程序后,TIM3_CNT再从0 开始计数。
TIMx_CNT寄存器:该寄存器是定时器的计数器,该寄存器存储了当前定时器已经计数的次数。
上面还用到控制寄存器1(TIMx_CR1) 位0:


当定时器溢出时会在状态寄存器(TIMx_SR) 中的0位置一作为中断标志,当执行完中断程序后应由软件置零。


【STM32|STM32 通用定时器】新手上路,如有错误,欢迎指正。

    推荐阅读