使用定时器进行精准延时从时钟树中我们可以得知 :(1)高级定时器timer1, timer8以及通用定时器timer9, timer10, timer11的时钟来源是APB2总线
(2)通用定时器timer2~timer5,通用定时器timer12~timer14以及基本定时器timer6,timer7的时钟来源是APB1总线
从STM32F4的内部时钟树可知:当APB1和APB2分频数为1的时候,TIM1、TIM8~TIM11的时钟为APB2的时钟,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟;
而如果APB1和APB2分频数不为1,那么TIM1、TIM8~TIM11的时钟为APB2的时钟的两倍,TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍。
因为系统初始化SystemInit函数里初始化APB1总线时钟为4分频即42M,APB2总线时钟为2分频即84M,
所以TIM1、TIM8~TIM11的时钟为APB2时钟的两倍即168M,
TIM2~TIM7、TIM12~TIM14的时钟为APB1的时钟的两倍即84M。
知道定时器的时钟源频率我们用定时器做延时就很方便了,只要设定合适的分频系数即可,附一下用中断实现延时的公式:(摘自原子的STM32F4开发指南)
Tout = ((arr+1)*(psc+1))/Tclk;公式中psc就是分频系数,arr就是计数值,达到这个计数就会发生溢出中断,Tclk就是我上述分析的时钟源频率的倒数。
主函数,定时器的配置
void TIM2_Init(void )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
​
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
​
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
​
TIM_TimeBaseStructure.TIM_Period = 9999; // 计数值 arr
TIM_TimeBaseStructure.TIM_Prescaler = 839; //分频系数 psc
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
​
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM2, ENABLE);
​
}
中断函数
void TIM2_IRQHandler(void)
{
//加入一些要在中断里做的事
TIM_ClearFlag(TIM2,TIM_FLAG_Update);
}
这里还有一个使用定时器精准延时1us的函数
void BSP_Delay_Init(void )
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseStructure.TIM_Period = 1;
TIM_TimeBaseStructure.TIM_Prescaler = 41;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Down;
TIM_TimeBaseInit(TIM5, &TIM_TimeBaseStructure);
}
​
void BSP_Delay1us(uint32_t delayTime)
{
uint16_t TIMCounter = delayTime*2;
TIM_Cmd(TIM5, ENABLE);
TIM_SetCounter(TIM5, TIMCounter);
while (TIMCounter >= 1)
{
TIMCounter = TIM_GetCounter(TIM5);
}
TIM_Cmd(TIM5, DISABLE);
​
}
一周热门 更多>