深入了解stm32F103C8T6上三种常用延时函数的原理

STM32的三种延时函数

  • 非精准延时
  • TIM延时
  • SysTick延时
  • 非精准延时

    非精准延时的方式就是使用空循环,循环内容为空。

    优点是无需配置定时器,直接就能拿来使用。

    缺点也很明显,就是无法实现精准延时,只能估摸着个大概,并且会造成CPU空转,不如使用硬件的方式。

    void delay_us(u16 time)
    {    
       u16 i=0;  
       while(time--)
       {
          i=10;
          while(i--) ;    
       }
    }
    //毫秒级的延时
    void delay_ms(u16 time)
    {    
       u16 i=0;  
       while(time--)
       {
          i=12000;
          while(i--) ;    
       }
    }
    

    TIM延时

    以下是以TIM3为例:
    初始化步骤与GPIO引脚使能一样,都是先定义一个初始化结构体用于保存配置函数,编辑完配置后使用GPIO_Init(GPIOx,&GPIO_InitStruct)TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure)

    #include "stm32f10x.h"
    
    void TIM3_Init(void)
    {
    	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
    	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟
    	TIM_TimeBaseInitStructure.TIM_Period    = 50000-1; 	//自动重装载值
    	TIM_TimeBaseInitStructure.TIM_Prescaler = 60-1;     //定时器分频
    	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
    	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; 
    	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
    }
    
    //微秒级延时
    void TIM3_Delayus(u16 xus)
    {
    	TIM_Cmd(TIM3,ENABLE); //启动定时器
    	while(TIM3->CNT < xus);
    	TIM3->CNT = 0;
    	TIM_Cmd(TIM3,DISABLE); //关闭定时器
    }
    
    //毫秒级延时
    void TIM3_Delayms(u16 xms)
    {
    	int i;
    	for(i=0;i<xms;i++)
    	{
    		TIM3_Delayus(1000);
    	}
    }
    

    SysTick延时

    使用SysTick延时需要先为它分配时钟源:

    #include "stm32f10x.h"
    
    //计数个数
    int f_us=9;
    int f_ms=9000;
    
    void delay_init(void)
    {
    	//设置外部源时钟 72MHZ/8=9MHZ
    	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);//9MHZ
    }
    
    //最多能计16,777,216个数,延时最多延时1,864,135us
    int delay_us(int nus)//1us计9个数,500us计500*9
    {
    	u32 temp;
    	//重装载寄存器赋值
    	SysTick->LOAD = nus*f_us-1;
    	
    	//计数器赋值为0,防止误差,只有VAL为0时,重装载寄存器才会赋值给它
    	SysTick->VAL=0X00;
    	
    	//使能定时器
    	SysTick->CTRL|=(0X01<<0);
    	
    	do
    	{
    		temp=SysTick->CTRL;
    	}//判断定时器是否开启,以及定时器是否计算完毕
    	while((temp&(0x01<<0))&&(!(temp&(0x01<<16))));
    	
    	//关闭定时器
    	SysTick->CTRL&=~(0X01<<0);
    }
    
    //最多能计16,777,216个数,延时最多延时1,864ms
    int delay_ms(int nms)
    {
    	u32 temp;
    	//重装载寄存器赋值
    	SysTick->LOAD = nms*f_ms-1;
    	
    	//计数器赋值为0,防止误差,只有VAL为0时,重装载寄存器才会赋值给它
    	SysTick->VAL=0X00;
    	
    	//使能定时器
    	SysTick->CTRL|=(0X01<<0);
    	
    	do
    	{
    		temp=SysTick->CTRL;
    	}//判断定时器是否开启,以及定时器是否计算完毕
    	while((temp&(0x01<<0))&&(!(temp&(0x01<<16))));
    	
    	//关闭定时器
    	SysTick->CTRL&=~(0X01<<0);
    }
    
    int delay_s(int ns)
    {
    	int n;
    	for(n=0;n<ns;n++)
    	{
    		delay_ms(1000);
    	}
    }
    
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入了解stm32F103C8T6上三种常用延时函数的原理

    发表回复