打印
[STM32]

立创商城STM32F系列——delay_us函数

[复制链接]
1144|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
小乐Tzz|  楼主 | 2018-8-24 10:09 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
delay_us函数
/**********************************************************/
该函数用来延时指定的 us,其参数nus为要延时的微秒数。该函数有使用OS和不使用OS
两个版本,这里我们分别介绍,首先是不使用 OS的时候,实现函数如下:
//延时nus
//nus为要延时的us数.                              
void delay_us(u32 nus)
{     
  u32 temp;            
  SysTick->LOAD=nus*fac_us;    //时间加载            
  SysTick->VAL=0x00;           //清空计数器
  SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;    //开始倒数      
  do
  {
    temp=SysTick->CTRL;
  }while((temp&0x01)&&!(temp&(1<<16)));//等待时间到达     
  SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
  SysTick->VAL =0X00;       //清空计数器     
}
有了上面对SysTick 寄存器的描述,这段代码不难理解。其实就是先把要延时的 us数换算成 SysTick 的时钟数,然后写入LOAD寄存器。然后清空当前寄存器VAL的内容,再开启倒数功能。等到倒数结束,即延时了 nus。最后关闭 SysTick,清空 VAL 的值。实现一次延时 nus的操作,但是这里要注意 nus 的值,不能太大,必须保证 nus<=(2^24)/fac_us,否则将导致延时时间不准确。这里特别说明一下:temp&0x01,这一句是用来判断systick定时器是否还处于开启状态,可以防止 systick被意外关闭导致的死循环。
再来看看使用OS的时候,delay_us的实现函数如下:
//延时nus
//nus为要延时的us数.                              
void delay_us(u32 nus)
{     
  u32 ticks;
  u32 told,tnow,tcnt=0;
  u32 reload=SysTick->LOAD;      //LOAD的值            
  ticks=nus*fac_us;             //需要的节拍数            
  delay_osschedlock();          //阻止 OS 调度,防止打断us延时
  told=SysTick->VAL;               //刚进入时的计数器值
  while(1)
  {
    tnow=SysTick->VAL;   
    if(tnow!=told)
    {        
      if(tnow<told)tcnt+=told-tnow;  //注意 SYSTICK是一个递减的计数器.
      else tcnt+=reload-tnow+told;        
      told=tnow;
      if(tcnt>=ticks)break;      //时间超过/等于要延迟的时间,则退出.
    }   
  };
  delay_osschedunlock();          //恢复 OS 调度
}
这里就正是利用了我们前面提到的时钟摘取法,ticks 是延时 nus 需要等待的 SysTick 计数次数(也就是延时时间),told 用于记录最近一次的 SysTick->VAL 值,然后 tnow 则是当前的SysTick->VAL值,通过他们的对比累加,实现SysTick 计数次数的统计,统计值存放在tcnt里面,然后通过对比 tcnt 和 ticks,来判断延时是否到达,从而达到不修改 SysTick 实现 nus 的延时,从而可以和OS 共用一个SysTick。
上面的 delay_osschedlock 和 delay_osschedunlock 是 OS 提供的两个函数,用于调度上锁和解锁,这里为了防止 OS 在 delay_us 的时候打断延时,可能导致的延时不准,所以我们利用这两个函数来实现免打断,从而保证延时精度!同时,此时的delay_us,,可以实现最长2^32/fac_us,在 168M主频下,最大延时,大概是204秒。
/**********************************************************/


【立创商城】STM32F103CBT6 托盘  https://item.szlcsc.com/8796.html

相关帖子

沙发
ayb_ice| | 2018-8-24 11:39 | 只看该作者
这样使用都不能重入,意义不大

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

70

主题

70

帖子

0

粉丝