发新帖我要提问
12
返回列表
打印

使用systick函数进行准确延时

[复制链接]
楼主: sunmeat
手机看帖
扫描二维码
随时随地手机跟帖
21
crwang| | 2014-11-5 10:24 | 只看该作者 回帖奖励 |倒序浏览
我也是在其他地方看到,觉得说的蛮有道理的,欢迎讨论:)

使用特权

评论回复
22
sunmeat|  楼主 | 2014-11-5 11:01 | 只看该作者
crwang 发表于 2014-11-5 10:22
任何比SysTick优先级高的中断不能调用SysTick_delay,这种情况下systick延时就不能用 ...

这个延时应该不会出现在中断中吧

使用特权

评论回复
23
ayb_ice| | 2014-11-5 16:33 | 只看该作者
这种精确没有意义,

高优先级中断来了怎么办,

再说了,这么重要的资源就被占用了

使用特权

评论回复
24
shdjdq| | 2014-11-5 16:52 | 只看该作者
当然有意义了,你总不能在中断中延时1ms吧,一般是在中断中放个数比较一下,到了是一个状态,没到是另一个状态。

使用特权

评论回复
25
flashtt| | 2014-11-5 17:24 | 只看该作者
这个延时用的是中断,在有其它中断的情况下就要考虑中断优先级的问题,不过Systick定时器延时还可以有不用中断的方法,我是在原子的例程中学到的,挺好用的,具体可参考原子板子的例程

使用特权

评论回复
26
sunmeat|  楼主 | 2014-11-5 23:00 | 只看该作者
flashtt 发表于 2014-11-5 17:24
这个延时用的是中断,在有其它中断的情况下就要考虑中断优先级的问题,不过Systick定时器延时还可以有不用 ...

明天看看去

使用特权

评论回复
27
sunmeat|  楼主 | 2014-11-5 23:02 | 只看该作者
ayb_ice 发表于 2014-11-5 16:33
这种精确没有意义,

高优先级中断来了怎么办,

这么重要的资源就被占用了,这倒是个问题。
高优先级中断来了怎么办,假设用的普通的延时函数,高优先级中断来了还得执行高优先级中断呀,看来用作延时的时候,需要把systick中断设成最低优先级

使用特权

评论回复
28
sunmeat|  楼主 | 2014-11-7 11:15 | 只看该作者
ayb_ice 发表于 2014-11-5 16:33
这种精确没有意义,

高优先级中断来了怎么办,

看了好几遍,终于懂了你这个高优先级中断的意思,意思是高优先级中断中调用了systick延时,那么这样就产生了逻辑冲突,systick到底该不该执行呢,对吧?

使用特权

评论回复
29
ayb_ice| | 2014-11-7 11:46 | 只看该作者
sunmeat 发表于 2014-11-7 11:15
看了好几遍,终于懂了你这个高优先级中断的意思,意思是高优先级中断中调用了systick延时,那么这样就产 ...

这个定时器是用作滴答定时器的

延时一般基于多少个滴答的

延时也不会在那里死等,否则做不了什么实事

使用特权

评论回复
30
zkcaptain| | 2014-11-7 17:30 | 只看该作者
本帖最后由 zkcaptain 于 2014-11-7 17:31 编辑

楼主,还有一种延迟方法咧,利用DWT,先计算出想要的延迟时间花费的时钟数,然后执行这么多时钟数,即可达到精确延迟,什么都不占用,刚开始是在看国外四轴代码时看到的,后来百度了一下,发现原子论坛有人也给出了代码,如下,未实测是否有bug:
楼主可否帮忙测一下看是否好用。

#define  DWT_CR      *(volatile u32 *)0xE0001000
#define  DWT_CYCCNT  *(volatile u32 *)0xE0001004
#define  DEM_CR      *(volatile u32 *)0xE000EDFC
#define  DEM_CR_TRCENA                   (1 << 24)
#define  DWT_CR_CYCCNTENA                (1 <<  0)

#define Delayms(msec)         Delayus(msec*1000)  //对于延时毫秒级的只需要定义一个宏



static u32 cpuclkfeq;     //用于保存cpu运行频率,可运行时动态修改




//初始化延时系统,参数为CPU频率
void DelayInit(u32 clk)

{
    cpuclkfeq = clk;

//打开CYCCNT功能,并把计数器清零,最后打开计数器对cpu时钟进行向上计数
    DEM_CR         |=  DEM_CR_TRCENA;
//    DWT_CYCCNT      = 0u;    //根据需要如果调试,或其他程序要使用CYCCNT时注释掉,否则可直接清零
    DWT_CR         |= DWT_CR_CYCCNTENA;
}




//延时函数,参数为需要延时的微秒数

void Delayus(u32 usec)
{
     u32 startts,endts,ts;
  //保存进入函数时的计数器值
     startts = DWT_CYCCNT;
     ts =  usec * (cpuclkfeq /(1000*1000) );        //计算达到所需延时值的cpu时钟数,^-^如果想要更精确此处可以减去运行前面代码所需的时钟数。
     endts = startts + ts;           //计算达到所需延时时间的DWT_CYCCNT计数值,超过32bit所能表达的最大值2的32次方-1是自动绕回丢弃进位
      if(endts > startts)            //判断是否跨越最大值边界
      {
          while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值
       }
       else
      {
           while(DWT_CYCCNT > endts);       //等待跨域32bit的最大值,2的32次方-1
           while(DWT_CYCCNT < endts);        //等到计数到所需延时值的cpu时钟数值
      }

}


使用特权

评论回复
评分
参与人数 1威望 +4 收起 理由
sunmeat + 4
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则