STM32的三种延时函数

非精准延时

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

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

缺点也很明显,就是无法实现精准延时,只能估摸着个大概,并且会造成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);
	}
}

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐