自动重装载值的计算.
如果单片机系统主频率为24M,现在需要用定时器Timer3实现一个100us的定时器,需要怎么配置,涉及到哪些计算,以STM32F407为例:
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
TIM_Cmd(TIM3,ENABLE); //使能定时器3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//定时器3中断服务程序
void TIM3_IRQHandler(void)
{
if(TIM3->SR&TIM_IT_Update)//溢出中断
{
lv_tick_inc(1);//lvgl的1ms心跳
}
TIM3->SR = (uint16_t)~TIM_IT_Update;
}
在如上代码中,TIM3_Int_Init()
函数实现定时器初始化,配置定时器的分频系数,重装载值,模式,中断等,其中重装载值是需要根据主频及中断产生间隔去计算的.
-
比如现在要实现一个100us产生一次中断的定时器.
设:
系统主频: freq = 24M
定时器时长 times = 100us
分频系数 24M的主频,可以将其先预分24得到1M的频率,也就是代码中 psc = 24
则时钟周期为1/1000000 S = 1us,也就是执行一条指令所需时间为1us,可以理解为定时器的计数值加1所需时间为1us.
如果是16位,则计数器从0计数到65535,最长可以65535us产生一次中断(计数模式为向上计数)
现在需要100us产生一次中断,则重装载值为 65535 - 100 = 65435;
备注:每次计数到65535溢出后产生中断,产生中断后arr计数重新加载为65435,计瞒100us后产生中断,达到定时器的效果. -
如果是现在需要实现一个1s的定时器呢?同样
系统主频: freq = 24M
定时器时长 times = 1000000us
分频系数 现在就不能预分频24了,因为分频24一次中断最大只能计时65.535ms.所以现在分频2400(如果支持),不能分频这么大则另行计算.
分频后时钟周期为 1/(24000000/2400) = 1 / 10000 S = 100us
现在就需要计算有多少个100us等于1s,即100us*X = 1000000us,X=10000
则重装载值为65535 - X = 65535 - 10000 = 55535.更简单的计算方式,这种方法适用于预分频系数可以为任意值:
定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us
Ft=定时器工作频率,单位:Mhz