STM32F4使用定时器进行精准延时

2019-07-20 09:02发布

使用定时器进行精准延时从时钟树中我们可以得知 :(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);
​
}









0条回答

一周热门 更多>