STM32 使用通用计时器实现微秒延时

本文介绍如何使用STM32的通用计时器实现精确的微秒级延时,通过调整预分频系数和计数值,实现了不同时间尺度(微秒、毫秒、秒)的延时功能。
AI助手已提取文章相关产品:

STM32 使用通用计时器实现微秒延时

为了驱动ARF2496K这款芯片,做STM32上的移植,所以第一步需要解决的就是时序问题,很显然在STM32下类似于51的延时方法并不适用,自然想到了采用定时器进行定时来延时。目前使用的是查询方式进行延时。


环境: STM32F107主控,采用STLINK仿真

代码如下:

static void TIM5_Init_Query(CALC_TYPE type,uint32_t val)
{
	TIM_TimeBaseInitTypeDef Tim5;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE);
	Tim5.TIM_Period=1; //???
	if(type==CALC_TYPE_S) //延时以S为单位时,时钟频率57600Hz,外部需要1250次计时
	{
		Tim5.TIM_Prescaler=57600-1; //预分频 72MHz / 57600= 1250Hz
	}else if(type==CALC_TYPE_MS)
	{
		Tim5.TIM_Prescaler=2880-1; //25000Hz ,定时器计数25次为ms
	}else if(type==CALC_TYPE_US)
	{	
		Tim5.TIM_Prescaler=72-1; //1MHz ,计数1次为us
	}else
	{
		Tim5.TIM_Prescaler=7200-1;
	}
	Tim5.TIM_ClockDivision=0;
	Tim5.TIM_CounterMode=TIM_CounterMode_Down; //向下计数
	TIM_TimeBaseInit(TIM5,&Tim5);		
}

static void TIM5_S_CALC(uint32_t s)
{
    u16 counter=(s*1250)&0xFFFF; //前提定时器时钟为1250Hz
    TIM_Cmd(TIM5,ENABLE);
    TIM_SetCounter(TIM5,counter); //设置计数值
    
    while(counter>1)
    {
        counter=TIM_GetCounter(TIM5);
    }
    TIM_Cmd(TIM5,DISABLE);
}

static void TIM5_MS_CALC(uint32_t ms)
{
    u16 counter=(ms*25)&0xFFFF; 
    TIM_Cmd(TIM5,ENABLE);
    TIM_SetCounter(TIM5,counter); //设置计数值
    
    while(counter>1)
    {
        counter=TIM_GetCounter(TIM5);
    }
    TIM_Cmd(TIM5,DISABLE);
}

static void TIM5_US_CALC(uint32_t us)
{
    u16 counter=us&0xffff;
    TIM_Cmd(TIM5,ENABLE);
    TIM_SetCounter(TIM5,counter); //设置计数值

    while(counter>1)
    {
        counter=TIM_GetCounter(TIM5);
    }
    TIM_Cmd(TIM5,DISABLE);
}

int main()
{
    SystemInit(); //库函数 初始化系统时钟源选择,PLL等  

#ifdef _DEBUG
    Init_PD11();
#endif
    TIM5_Init_Query(CALC_TYPE_US);

    while(1)
    {
        PD11_U; //产生方波
        TIM5_US_CALC(1);   //TIM5_MS_CALC(1); 毫秒延时, TIM5_S_CALC(1); 秒级别延时 
        PD11_D;
        TIM5_US_CALC(1);
    }
}

实验数据:

延时1微秒时,略有出入,下图:

(延时1us,并不精准,这与while循环中的语句有关)

延时20微秒时,比较准确,下图:


延时1毫秒时,下图:

(差了0.2ms,也就是才延时0.9ms,可以将分频系数降低,然后延时值加大些进行改善)

延时20毫秒时,下图:


延时1秒时,下图:



毫秒延时那里修改成下面代码,基本上能精准。

Tim5.TIM_Prescaler=720-1; //100KHz ,定时器计数100次为1ms
static void TIM5_MS_CALC(uint32_t ms)
{
    u16 counter=(ms*100)&0xFFFF; //前提定时器时钟为100KHz
    TIM_Cmd(TIM5,ENABLE);
    TIM_SetCounter(TIM5,counter); //设置计数值
    
    while(counter>1)
    {
        counter=TIM_GetCounter(TIM5);
    }
    TIM_Cmd(TIM5,DISABLE);
}



您可能感兴趣的与本文相关内容

STM32使用 HAL 库通过定时器实现微秒级延迟,是一种常见且高效的方法,适用于需要高精度延时的嵌入式应用场景。该方法依赖于通用定时器(如 TIM5 或 TIM14)的计数器功能,通过设置初始计数值并轮询当前计数值,实现非中断式的精确延时。 ### 定时器配置与初始化 在使用定时器实现微秒级延迟前,需通过 STM32CubeMX 或手动配置定时器的时钟源、计数模式和频率。通常将定时器配置为向上计数模式,并设置其时钟频率为 1MHz,以确保每个计数周期对应 1 微秒[^1]。 例如,使用 TIM14 时,其初始化代码如下: ```c htim14.Instance = TIM14; htim14.Init.Prescaler = SystemCoreClock / 1000000 - 1; // 设置预分频器,使计数频率为1MHz htim14.Init.CounterMode = TIM_COUNTERMODE_UP; htim14.Init.Period = 0xFFFF; // 设置自动重载值为最大 htim14.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; HAL_TIM_Base_Start(&htim14); ``` ### 微秒级延迟函数实现 在初始化完成后,可以通过设置计数器初值并轮询当前值来实现延时。例如,使用 TIM14 实现的 `HAL_Delay_us` 函数如下: ```c void HAL_Delay_us(uint32_t Delay_us) { uint16_t wait = Delay_us; if (wait < UINT16_MAX) wait++; __HAL_TIM_SET_COUNTER(&htim14, 0); // 将计数器清零 HAL_TIM_Base_Start(&htim14); // 启动定时器 while(__HAL_TIM_GET_COUNTER(&htim14) < wait); // 等待达到指定微秒数 HAL_TIM_Base_Stop(&htim14); // 停止定时器 } ``` 该函数通过将计数器设置为 0,启动定时器并等待其计数值达到指定的微秒数,从而实现精确延时。此方法适用于短时间的延时需求,且不依赖中断机制,避免了中断服务程序的开销[^1]。 ### 另一种实现方式:使用 TIM5 若使用 TIM5 实现类似功能,可通过设置计数器初值为 `0xFFFF - us - 5`,然后等待计数器溢出,从而实现延时。其函数实现如下: ```c void HAL_Delay_us(uint16_t us) { uint16_t delay = 0xFFFF - us - 5; HAL_TIM_Base_Start(&htim5); __HAL_TIM_SetCounter(&htim5, delay); while (delay < 0xFFFF - 5) { delay = __HAL_TIM_Get_COUNTER(&htim5); } HAL_TIM_Base_Stop(&htim5); } ``` 该方法通过反向计数的方式,利用计数器从设定值递增到最大值的时间实现延时,适用于需要更高精度控制的场景[^2]。 ### 注意事项 - **定时器时钟配置**:必须确保定时器的时钟源配置正确,通常设置为 1MHz,以保证每个计数周期对应 1 微秒。 - **计数器位宽限制**:16 位定时器的最大计数值为 65535,因此单次延时时间不应超过 65535 微秒。 - **性能影响**:频繁启停定时器可能引入额外开销,可根据实际需求决定是否保留 `HAL_TIM_Base_Stop` 调用。 ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值