《SLAM机器人基础教程》第三章 单片机与STM32:定时器实验

3.7节 定时器实验

在上一节我们使用SysTick实现了延时,本节介绍使用定时器实现延时。

a.实验准备:USB转串口模块,ST-Llink下载器,CHEAPX机器人控制板

b.实验目的:使用定时器延时检验上一节SysTick延时函数的准确度

c.相关知识点:

STM32定时器和串口一样,具有中断函数。但我们打开定时器时,定时器就会按我们设置好的频率开始计数直到溢出,溢出会产生溢出中断。同样的,我们可以通过计数的数值转化为时间。STM32F1系列芯片的定时器的分辨率可以达到1/72us。

d.编程及运行

(1)初始化定时器TIM4,编写中断函数

void initTimeStamp(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);//开启TIM4时钟
    
    //TIM4
    TIM_TimeBaseStruct.TIM_ClockDivision = 0;  //时钟分割,不分割,即为该定制器时钟最大值72M
    TIM_TimeBaseStruct.TIM_Prescaler = 0;         //预分频值,不分频,即为该定制器时钟值72M
    TIM_TimeBaseStruct.TIM_Period = 65000-1;     //最大计数值,也是计数周期=1/72M*65000s=65000/72us
    TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStruct);//传入结构TIM_TimeBaseStruct,配置TIM4
    TIM_ClearFlag(TIM4, TIM_FLAG_Update);       //清除更新中断
    TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE );   //开启更新中断,计数器到达最大值65000-1,从该值转变至0时,会产生一次更新中断
    
    NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;           //通道值:定时器4
  NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级 0,最高
  NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;        //子优先级 1,次高
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;           //使能
  NVIC_Init(&NVIC_InitStruct);                           //传入结构体NVIC_InitStruct,配置NVIC

    TIM_ARRPreloadConfig(TIM4, ENABLE);//开启自动装载
    TIM_Cmd(TIM4, ENABLE);
}
void TIM4_IRQHandler(void) 
{
  if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET) //判断是否为更新中断
    {
        timerTSCount++;
      TIM_ClearITPendingBit(TIM4, TIM_IT_Update ); //清除更新中断标志 
    }
}

(2)编写SysTick测试函数。我们只需要记录SysTick实现的延时函数前后的TIM4计数值即可。

void testTimestamp(void)
{
    u32 T=0;
    u32 lastT=0;
    u32 deltaT=0;
    printf("Timestamp Test\n");
    while(1)
    {
        lastT=getTimestampUS();
        T=getTimestampUS();
        deltaT=T-lastT;
        
        lastT=getTimestampUS();
    delay_us(1);
        T=getTimestampUS();
        printf("cmd=1us,Real:%6fus;",((T-lastT-deltaT)/72.0f));
        
        lastT=getTimestampUS();
    delay_ms(1);
        T=getTimestampUS();
        printf("cmd=1000us,Real:%6fus\r\n",((T-lastT-deltaT)/72.0f));
        
        delay_ms(1000);

    }
}
volatile static u32   timerTS=0;       //TimeStamp(unit:1/72us)
volatile static u32   timerTSH=0;      //TimeStamp(unit:65000/72us)    
volatile static u8    timerTSCount=0;  //TimeStamp(unit:65000/72us)
/*** unit:1/72us ***/
u32 getTimestampUS(void)
{
    timerTSH+=timerTSCount;
    timerTS=timerTSH*65000+TIM4->CNT;
    timerTSCount=0;
    return timerTS;
}

(3)主函数

//定时器实验
int main(void)
{        
    
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //PriorityGroupConfig NVIC中断分组设置 组2(2位抢占优先级,2位响应优先级)
    initDebugSerial(500000);//初始化调试串口USART1,波特率500000
    initSysTick();//初始化滴答定时器和TIM4定时器
    showVersion();//显示版本
    
    while(1)
    {
        ;
    }
    
}

(4)实验结果:

扫描二维码关注公众号,回复: 11440267 查看本文章

e.实验总结:TIM定时器除了定时外还可以用于输出PWM等,是STM32芯片中很重要的外设资源。因此,我们常用SysTick系统滴答定时器实现延时。

猜你喜欢

转载自www.cnblogs.com/Baron-Lu/p/13378565.html